From 40e2c33c6f8426615f1713d3428bdb87a90091c6 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 29 Jun 2021 15:25:03 -0400 Subject: [PATCH] hal/gles: hack around cubemap support --- wgpu-hal/src/gles/device.rs | 24 +++++++-- wgpu-hal/src/gles/queue.rs | 101 ++++++++++++++++++++++++++---------- 2 files changed, 96 insertions(+), 29 deletions(-) diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 1dd1f1d00..e8e2e78ab 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -451,6 +451,14 @@ impl crate::Device for super::Device { super::TextureInner::Renderbuffer { raw } } else { let raw = gl.create_texture().unwrap(); + //HACK: detect a cube map + let cube_count = if desc.size.width == desc.size.height + && desc.size.depth_or_array_layers % 6 == 0 + { + Some(desc.size.depth_or_array_layers / 6) + } else { + None + }; let target = match desc.dimension { wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => { if desc.sample_count > 1 { @@ -465,8 +473,11 @@ impl crate::Device for super::Device { true, ); target - } else if desc.size.depth_or_array_layers > 1 { - let target = glow::TEXTURE_2D_ARRAY; + } else if desc.size.depth_or_array_layers > 1 && cube_count != Some(1) { + let target = match cube_count { + Some(_) => glow::TEXTURE_CUBE_MAP_ARRAY, + None => glow::TEXTURE_2D_ARRAY, + }; gl.bind_texture(target, Some(raw)); gl.tex_storage_3d( target, @@ -478,7 +489,10 @@ impl crate::Device for super::Device { ); target } else { - let target = glow::TEXTURE_2D; + let target = match cube_count { + Some(_) => glow::TEXTURE_CUBE_MAP, + None => glow::TEXTURE_2D, + }; gl.bind_texture(target, Some(raw)); gl.tex_storage_2d( target, @@ -772,6 +786,10 @@ impl crate::Device for super::Device { } wgt::BindingType::Texture { .. } => { let view = desc.textures[entry.resource_index as usize].view; + if view.mip_levels.start != 0 || view.array_layers.start != 0 { + log::error!("Unable to create a sampled texture binding for non-zero mipmap level or array layer.\n{}", + "This is an implementation problem of wgpu-hal/gles backend.") + } match view.inner { super::TextureInner::Renderbuffer { .. } => { panic!("Unable to use a renderbuffer in a group") diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index a00fa883d..04e34d48c 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -5,6 +5,15 @@ use std::{mem, ops::Range, slice}; const DEBUG_ID: u32 = 0; +const CUBEMAP_FACES: [u32; 6] = [ + glow::TEXTURE_CUBE_MAP_POSITIVE_X, + glow::TEXTURE_CUBE_MAP_NEGATIVE_X, + glow::TEXTURE_CUBE_MAP_POSITIVE_Y, + glow::TEXTURE_CUBE_MAP_NEGATIVE_Y, + glow::TEXTURE_CUBE_MAP_POSITIVE_Z, + glow::TEXTURE_CUBE_MAP_NEGATIVE_Z, +]; + fn extract_marker<'a>(data: &'a [u8], range: &Range) -> &'a str { std::str::from_utf8(&data[range.start as usize..range.end as usize]).unwrap() } @@ -191,6 +200,7 @@ impl super::Queue { dst_target, ref copy, } => { + //TODO: cubemaps //TODO: how is depth handled? gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(self.copy_fbo)); for layer in 0..copy.size.depth_or_array_layers as i32 { @@ -260,32 +270,70 @@ impl super::Queue { let unpack_data = glow::PixelUnpackData::BufferOffset(copy.buffer_layout.offset as u32); gl.bind_texture(dst_target, Some(dst)); - if is_3d_target(dst_target) { - gl.tex_sub_image_3d( - dst_target, - copy.texture_base.mip_level as i32, - copy.texture_base.origin.x as i32, - copy.texture_base.origin.y as i32, - copy.texture_base.origin.z as i32, - copy.size.width as i32, - copy.size.height as i32, - copy.size.depth_or_array_layers as i32, - dst_info.external_format, - dst_info.data_type, - unpack_data, - ); - } else { - gl.tex_sub_image_2d( - dst_target, - copy.texture_base.mip_level as i32, - copy.texture_base.origin.x as i32, - copy.texture_base.origin.y as i32, - copy.size.width as i32, - copy.size.height as i32, - dst_info.external_format, - dst_info.data_type, - unpack_data, - ); + match dst_target { + glow::TEXTURE_3D | glow::TEXTURE_2D_ARRAY => { + gl.tex_sub_image_3d( + dst_target, + copy.texture_base.mip_level as i32, + copy.texture_base.origin.x as i32, + copy.texture_base.origin.y as i32, + copy.texture_base.origin.z as i32, + copy.size.width as i32, + copy.size.height as i32, + copy.size.depth_or_array_layers as i32, + dst_info.external_format, + dst_info.data_type, + unpack_data, + ); + } + glow::TEXTURE_2D => { + gl.tex_sub_image_2d( + dst_target, + copy.texture_base.mip_level as i32, + copy.texture_base.origin.x as i32, + copy.texture_base.origin.y as i32, + copy.size.width as i32, + copy.size.height as i32, + dst_info.external_format, + dst_info.data_type, + unpack_data, + ); + } + glow::TEXTURE_CUBE_MAP => { + let mut offset = copy.buffer_layout.offset as u32; + for face_index in 0..copy.size.depth_or_array_layers { + gl.tex_sub_image_2d( + CUBEMAP_FACES[(copy.texture_base.origin.z + face_index) as usize], + copy.texture_base.mip_level as i32, + copy.texture_base.origin.x as i32, + copy.texture_base.origin.y as i32, + copy.size.width as i32, + copy.size.height as i32, + dst_info.external_format, + dst_info.data_type, + glow::PixelUnpackData::BufferOffset(offset), + ); + offset += copy.buffer_layout.rows_per_image.map_or(0, |rpi| rpi.get()) + * copy.buffer_layout.bytes_per_row.map_or(0, |bpr| bpr.get()); + } + } + glow::TEXTURE_CUBE_MAP_ARRAY => { + //Note: not sure if this is correct! + gl.tex_sub_image_3d( + dst_target, + copy.texture_base.mip_level as i32, + copy.texture_base.origin.x as i32, + copy.texture_base.origin.y as i32, + copy.texture_base.origin.z as i32, + copy.size.width as i32, + copy.size.height as i32, + copy.size.depth_or_array_layers as i32, + dst_info.external_format, + dst_info.data_type, + unpack_data, + ); + } + _ => unreachable!(), } } C::CopyTextureToBuffer { @@ -297,6 +345,7 @@ impl super::Queue { ref copy, } => { //TODO: compressed data + //TODO: cubemaps let row_texels = copy .buffer_layout .bytes_per_row