From a58a88b3dfdd85ab016c8acc2740dc7d89d8d051 Mon Sep 17 00:00:00 2001 From: Frizi Date: Thu, 3 Jun 2021 20:49:52 +0200 Subject: [PATCH 1/2] add minimal support for cubemap textures in gl backend --- src/backend/gl/src/command.rs | 26 ++- src/backend/gl/src/conv.rs | 14 -- src/backend/gl/src/device.rs | 291 +++++++++++++++++----------------- src/backend/gl/src/native.rs | 1 - src/backend/gl/src/queue.rs | 64 +++++++- 5 files changed, 214 insertions(+), 182 deletions(-) diff --git a/src/backend/gl/src/command.rs b/src/backend/gl/src/command.rs index b3e1975f56..d60105cffc 100644 --- a/src/backend/gl/src/command.rs +++ b/src/backend/gl/src/command.rs @@ -908,21 +908,17 @@ impl command::CommandBuffer for CommandBuffer { level_count, layer_count, .. - } => { - let is_3d = layer_count == 1; //TODO? - n::ImageView::Texture { - target, - raw, - is_3d, - sub: image::SubresourceRange { - aspects: Aspects::COLOR, - layer_start: 0, - layer_count: Some(layer_count), - level_start: 0, - level_count: Some(level_count), - }, - } - } + } => n::ImageView::Texture { + target, + raw, + sub: image::SubresourceRange { + aspects: Aspects::COLOR, + layer_start: 0, + layer_count: Some(layer_count), + level_start: 0, + level_count: Some(level_count), + }, + }, }; self.data.push_cmd(Command::BindFramebuffer { target: glow::DRAW_FRAMEBUFFER, diff --git a/src/backend/gl/src/conv.rs b/src/backend/gl/src/conv.rs index 5a4f48a854..7ad694cb69 100644 --- a/src/backend/gl/src/conv.rs +++ b/src/backend/gl/src/conv.rs @@ -1,20 +1,6 @@ use crate::native::VertexAttribFunction; use hal::{format::Format, image as i, pso}; -/* -pub fn _image_kind_to_gl(kind: i::Kind) -> t::GLenum { - match kind { - i::Kind::D1(_) => glow::TEXTURE_1D, - i::Kind::D1Array(_, _) => glow::TEXTURE_1D_ARRAY, - i::Kind::D2(_, _, i::AaMode::Single) => glow::TEXTURE_2D, - i::Kind::D2(_, _, _) => glow::TEXTURE_2D_MULTISAMPLE, - i::Kind::D2Array(_, _, _, i::AaMode::Single) => glow::TEXTURE_2D_ARRAY, - i::Kind::D2Array(_, _, _, _) => glow::TEXTURE_2D_MULTISAMPLE_ARRAY, - i::Kind::D3(_, _, _) => glow::TEXTURE_3D, - i::Kind::Cube(_) => glow::TEXTURE_CUBE_MAP, - i::Kind::CubeArray(_, _) => glow::TEXTURE_CUBE_MAP_ARRAY, - } -}*/ pub fn filter_to_gl(mag: i::Filter, min: i::Filter, mip: i::Filter) -> (u32, u32) { use hal::image::Filter::*; diff --git a/src/backend/gl/src/device.rs b/src/backend/gl/src/device.rs index 9d9d642b06..319c6b6d3d 100644 --- a/src/backend/gl/src/device.rs +++ b/src/backend/gl/src/device.rs @@ -252,60 +252,20 @@ impl Device { Ok((program, sampler_map)) } - fn _bind_target_compat(gl: &GlContainer, point: u32, attachment: u32, view: &n::ImageView) { - match *view { - n::ImageView::Renderbuffer { raw: rb, .. } => unsafe { - gl.framebuffer_renderbuffer(point, attachment, glow::RENDERBUFFER, Some(rb)); - }, - n::ImageView::Texture { - target, - raw, - ref sub, - is_3d: false, - } => unsafe { - gl.bind_texture(target, Some(raw)); - gl.framebuffer_texture_2d( - point, - attachment, - target, - Some(raw), - sub.level_start as _, - ); - }, - n::ImageView::Texture { - target, - raw, - ref sub, - is_3d: true, - } => unsafe { - gl.bind_texture(target, Some(raw)); - gl.framebuffer_texture_3d( - point, - attachment, - target, - Some(raw), - sub.level_start as _, - sub.layer_start as _, - ); - }, - } - } - pub(crate) fn bind_target(gl: &GlContainer, point: u32, attachment: u32, view: &n::ImageView) { match *view { n::ImageView::Renderbuffer { raw: rb, .. } => unsafe { gl.framebuffer_renderbuffer(point, attachment, glow::RENDERBUFFER, Some(rb)); }, n::ImageView::Texture { - target: _, + target: target @ glow::TEXTURE_2D, raw, ref sub, - is_3d: false, } => unsafe { gl.framebuffer_texture_2d( point, attachment, - glow::TEXTURE_2D, + target, Some(raw), sub.level_start as _, ); @@ -314,7 +274,6 @@ impl Device { target: _, raw, ref sub, - is_3d: true, } => unsafe { gl.framebuffer_texture_layer( point, @@ -1458,7 +1417,7 @@ impl d::Device for Device { _tiling: i::Tiling, usage: i::Usage, _sparse: memory::SparseFlags, - _view_caps: i::ViewCapabilities, + view_caps: i::ViewCapabilities, ) -> Result { let gl = &self.share.context; @@ -1468,117 +1427,148 @@ impl d::Device for Device { let mut pixel_count: u64 = 0; let image = if num_levels > 1 || usage.intersects(i::Usage::STORAGE | i::Usage::SAMPLED) { let name = gl.create_texture().unwrap(); - let target = match kind { - i::Kind::D2(w, h, 1, 1) => { - gl.bind_texture(glow::TEXTURE_2D, Some(name)); - if self.share.private_caps.image_storage { - gl.tex_storage_2d( - glow::TEXTURE_2D, - num_levels as _, - desc.tex_internal, + let (w, h, l, target) = match kind { + i::Kind::D2(w, h, 1, 1) => (w, h, 1, glow::TEXTURE_2D), + i::Kind::D2(w, h, 6, 1) + if view_caps.contains(i::ViewCapabilities::KIND_CUBE) && w == h => + { + (w, h, 6, glow::TEXTURE_CUBE_MAP) + } + i::Kind::D2(w, h, l, 1) => (w, h, l as u32, glow::TEXTURE_2D_ARRAY), + i::Kind::D3(w, h, l) => (w, h, l, glow::TEXTURE_3D), + _ => unimplemented!(), + }; + + gl.bind_texture(target, Some(name)); + + match (self.share.private_caps.image_storage, target) { + (true, glow::TEXTURE_2D) | (true, glow::TEXTURE_CUBE_MAP) => { + gl.tex_storage_2d(target, num_levels as _, desc.tex_internal, w as _, h as _); + let mut w = w as u64; + let mut h = h as u64; + for i in 0..num_levels { + pixel_count += w * h * h; + w = std::cmp::max(w / 2, 1); + h = std::cmp::max(h / 2, 1); + } + } + (false, glow::TEXTURE_2D) => { + gl.tex_parameter_i32(target, glow::TEXTURE_MAX_LEVEL, (num_levels - 1) as _); + let mut w = w; + let mut h = h; + for i in 0..num_levels { + gl.tex_image_2d( + target, + i as _, + desc.tex_internal as i32, w as _, h as _, + 0, + desc.tex_external, + desc.data_type, + None, ); - pixel_count += (w * h) as u64 * num_levels as u64; - } else { - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MAX_LEVEL, - (num_levels - 1) as _, - ); - let mut w = w; - let mut h = h; - for i in 0..num_levels { - gl.tex_image_2d( - glow::TEXTURE_2D, - i as _, - desc.tex_internal as i32, - w as _, - h as _, - 0, - desc.tex_external, - desc.data_type, - None, - ); - pixel_count += (w * h) as u64; - w = std::cmp::max(w / 2, 1); - h = std::cmp::max(h / 2, 1); - } + pixel_count += (w * h) as u64; + w = std::cmp::max(w / 2, 1); + h = std::cmp::max(h / 2, 1); } - match channel { - ChannelType::Uint | ChannelType::Sint => { - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MIN_FILTER, - glow::NEAREST as _, - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MAG_FILTER, - glow::NEAREST as _, - ); - } - _ => {} - }; - glow::TEXTURE_2D } - i::Kind::D2(w, h, l, 1) => { - gl.bind_texture(glow::TEXTURE_2D_ARRAY, Some(name)); - if self.share.private_caps.image_storage { - gl.tex_storage_3d( - glow::TEXTURE_2D_ARRAY, - num_levels as _, - desc.tex_internal, + (true, glow::TEXTURE_2D_ARRAY) => { + gl.tex_storage_3d( + target, + num_levels as _, + desc.tex_internal, + w as _, + h as _, + l as _, + ); + let mut w = w as u64; + let mut h = h as u64; + let l = l as u64; + for i in 0..num_levels { + pixel_count += w * h * l; + w = std::cmp::max(w / 2, 1); + h = std::cmp::max(h / 2, 1); + } + } + (false, glow::TEXTURE_2D_ARRAY) => { + gl.tex_parameter_i32(target, glow::TEXTURE_MAX_LEVEL, (num_levels - 1) as _); + let mut w = w as u64; + let mut h = h as u64; + let l = l as u64; + for i in 0..num_levels { + gl.tex_image_3d( + target, + i as _, + desc.tex_internal as i32, w as _, h as _, l as _, + 0, + desc.tex_external, + desc.data_type, + None, ); - pixel_count += (w * h) as u64 * l as u64 * num_levels as u64; - } else { - gl.tex_parameter_i32( - glow::TEXTURE_2D_ARRAY, - glow::TEXTURE_MAX_LEVEL, - (num_levels - 1) as _, + pixel_count += w * h * l; + w = std::cmp::max(w / 2, 1); + h = std::cmp::max(h / 2, 1); + } + } + (true, glow::TEXTURE_3D) => { + gl.tex_storage_3d( + target, + num_levels as _, + desc.tex_internal, + w as _, + h as _, + l as _, + ); + let mut w = w as u64; + let mut h = h as u64; + let mut l = l as u64; + for i in 0..num_levels { + pixel_count += w * h * l; + w = std::cmp::max(w / 2, 1); + h = std::cmp::max(h / 2, 1); + l = std::cmp::max(l / 2, 1); + } + } + (false, glow::TEXTURE_3D) => { + gl.tex_parameter_i32(target, glow::TEXTURE_MAX_LEVEL, (num_levels - 1) as _); + let mut w = w as u64; + let mut h = h as u64; + let mut l = l as u64; + for i in 0..num_levels { + gl.tex_image_3d( + target, + i as _, + desc.tex_internal as i32, + w as _, + h as _, + l as _, + 0, + desc.tex_external, + desc.data_type, + None, ); - let mut w = w; - let mut h = h; - for i in 0..num_levels { - gl.tex_image_3d( - glow::TEXTURE_2D_ARRAY, - i as _, - desc.tex_internal as i32, - w as _, - h as _, - l as _, - 0, - desc.tex_external, - desc.data_type, - None, - ); - pixel_count += (w * h) as u64 * l as u64; - w = std::cmp::max(w / 2, 1); - h = std::cmp::max(h / 2, 1); - } + pixel_count += w * h * l; + w = std::cmp::max(w / 2, 1); + h = std::cmp::max(h / 2, 1); + l = std::cmp::max(l / 2, 1); } - match channel { - ChannelType::Uint | ChannelType::Sint => { - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MIN_FILTER, - glow::NEAREST as _, - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MAG_FILTER, - glow::NEAREST as _, - ); - } - _ => {} - }; - glow::TEXTURE_2D_ARRAY } _ => unimplemented!(), + } + + match channel { + ChannelType::Uint | ChannelType::Sint => { + gl.tex_parameter_i32(target, glow::TEXTURE_MIN_FILTER, glow::NEAREST as _); + gl.tex_parameter_i32(target, glow::TEXTURE_MAG_FILTER, glow::NEAREST as _); + } + _ => {} }; + gl.bind_texture(target, None); + n::ImageType::Texture { target, raw: name, @@ -1703,10 +1693,6 @@ impl d::Device for Device { format, .. } => { - let is_3d = match kind { - i::ViewKind::D1 | i::ViewKind::D2 => false, - _ => true, - }; match conv::describe_format(view_format) { Some(description) => { let raw_view_format = description.tex_external; @@ -1722,10 +1708,23 @@ impl d::Device for Device { log::warn!("View format {:?} is not supported", view_format); } } + let kind_target = match kind { + i::ViewKind::D1 => glow::TEXTURE_1D, + i::ViewKind::D1Array => glow::TEXTURE_1D_ARRAY, + i::ViewKind::D2 => glow::TEXTURE_2D, + i::ViewKind::D2Array => glow::TEXTURE_2D_ARRAY, + i::ViewKind::D3 => glow::TEXTURE_3D, + i::ViewKind::Cube => glow::TEXTURE_CUBE_MAP, + i::ViewKind::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY, + }; + + if kind_target != target { + todo!("image view of different kind than original texture"); + } + Ok(n::ImageView::Texture { target, raw, - is_3d, sub: range, }) } diff --git a/src/backend/gl/src/native.rs b/src/backend/gl/src/native.rs index b81e3c8d73..6376ecf74f 100644 --- a/src/backend/gl/src/native.rs +++ b/src/backend/gl/src/native.rs @@ -173,7 +173,6 @@ pub enum ImageView { Texture { target: TextureTarget, raw: Texture, - is_3d: bool, sub: i::SubresourceRange, }, } diff --git a/src/backend/gl/src/queue.rs b/src/backend/gl/src/queue.rs index 2ee2217007..3cf9e23bcb 100644 --- a/src/backend/gl/src/queue.rs +++ b/src/backend/gl/src/queue.rs @@ -115,7 +115,7 @@ impl Queue { (glow::BYTE, glow::SHORT, glow::INT), C::Uint | C::Unorm => (glow::UNSIGNED_BYTE, glow::UNSIGNED_SHORT, glow::UNSIGNED_INT), - C::Float => (glow::ZERO, glow::HALF_FLOAT, glow::FLOAT), + C::Float => (glow::ZERO, glow::HALF_FLOAT, glow), C::Srgb => { log::error!("Unsupported Srgb channel type"); return @@ -678,12 +678,12 @@ impl Queue { gl.active_texture(glow::TEXTURE0); gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, Some(src_buffer)); + gl.bind_texture(texture_target, Some(dst_texture)); match texture_target { glow::TEXTURE_2D => { - gl.bind_texture(glow::TEXTURE_2D, Some(dst_texture)); gl.tex_sub_image_2d( - glow::TEXTURE_2D, + texture_target, data.image_layers.level as _, data.image_offset.x, data.image_offset.y, @@ -694,10 +694,9 @@ impl Queue { glow::PixelUnpackData::BufferOffset(data.buffer_offset as u32), ); } - glow::TEXTURE_2D_ARRAY => { - gl.bind_texture(glow::TEXTURE_2D_ARRAY, Some(dst_texture)); + glow::TEXTURE_2D_ARRAY | glow::TEXTURE_3D => { gl.tex_sub_image_3d( - glow::TEXTURE_2D_ARRAY, + texture_target, data.image_layers.level as _, data.image_offset.x, data.image_offset.y, @@ -711,9 +710,61 @@ impl Queue { glow::PixelUnpackData::BufferOffset(data.buffer_offset as u32), ); } + glow::TEXTURE_CUBE_MAP => { + let components = match texture_format { + glow::RED + | glow::RED_INTEGER + | glow::DEPTH_COMPONENT + | glow::DEPTH_STENCIL => 1, + glow::RG | glow::RG_INTEGER => 2, + glow::RGB | glow::RGB_INTEGER => 3, + glow::RGBA | glow::BGRA | glow::RGBA_INTEGER => 4, + _ => unreachable!(), + }; + + let component_size = match pixel_type { + glow::BYTE | glow::UNSIGNED_BYTE => 1, + glow::SHORT | glow::UNSIGNED_SHORT | glow::HALF_FLOAT => 2, + glow::INT + | glow::UNSIGNED_INT + | glow::UNSIGNED_NORMALIZED + | glow::FLOAT => 4, + _ => unreachable!(), + }; + + let mut buffer_offset = data.buffer_offset as u32; + let layer_size = + data.buffer_width * data.buffer_height * component_size * components; + + let faces_range = data.image_layers.layers.start as usize + ..data.image_layers.layers.end as usize; + for &face in &[ + 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, + ][faces_range] + { + gl.tex_sub_image_2d( + face, + data.image_layers.level as _, + data.image_offset.x, + data.image_offset.y, + data.image_extent.width as _, + data.image_extent.height as _, + texture_format, + pixel_type, + glow::PixelUnpackData::BufferOffset(buffer_offset), + ); + buffer_offset += layer_size; + } + } _ => unimplemented!(), } + gl.bind_texture(texture_target, None); gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, None); }, com::Command::CopyBufferToRenderbuffer(..) => { @@ -749,6 +800,7 @@ impl Queue { glow::PixelPackData::BufferOffset(data.buffer_offset as u32), ); gl.bind_buffer(glow::PIXEL_PACK_BUFFER, None); + gl.bind_texture(glow::TEXTURE_2D, None); } } else { //TODO: use FBO From f0e4d7e1c9986f240384642a8e8f27f381261d42 Mon Sep 17 00:00:00 2001 From: Frizi Date: Fri, 11 Jun 2021 12:50:40 +0200 Subject: [PATCH 2/2] add support for S3TC texture formats in gl backend --- src/backend/dx12/src/lib.rs | 4 +- src/backend/gl/Cargo.toml | 3 +- src/backend/gl/src/command.rs | 11 ++- src/backend/gl/src/conv.rs | 128 ++++++++++++++++++++++++++++++- src/backend/gl/src/device.rs | 5 +- src/backend/gl/src/info.rs | 9 ++- src/backend/gl/src/native.rs | 3 +- src/backend/gl/src/queue.rs | 75 ++++++++++++++---- src/backend/metal/src/command.rs | 4 +- 9 files changed, 211 insertions(+), 31 deletions(-) diff --git a/src/backend/dx12/src/lib.rs b/src/backend/dx12/src/lib.rs index d24ef02b32..251a8d7e49 100644 --- a/src/backend/dx12/src/lib.rs +++ b/src/backend/dx12/src/lib.rs @@ -1356,8 +1356,8 @@ impl hal::Instance for Instance { Features::UNSIZED_DESCRIPTOR_ARRAY | Features::DRAW_INDIRECT_COUNT | Features::INDEPENDENT_BLENDING | - Features::SAMPLE_RATE_SHADING | - Features::FRAGMENT_STORES_AND_ATOMICS | + Features::SAMPLE_RATE_SHADING | + Features::FRAGMENT_STORES_AND_ATOMICS | tiled_resource_features | conservative_faster_features, properties: PhysicalDeviceProperties { diff --git a/src/backend/gl/Cargo.toml b/src/backend/gl/Cargo.toml index 49cfe9c460..0f1fb84d19 100644 --- a/src/backend/gl/Cargo.toml +++ b/src/backend/gl/Cargo.toml @@ -25,7 +25,8 @@ bitflags = "1" fxhash = "0.2.1" log = "0.4" hal = { package = "gfx-hal", path = "../../hal", version = "0.8" } -glow = "0.9" +glow = "0.10" + parking_lot = "0.11" raw-window-handle = "0.3" diff --git a/src/backend/gl/src/command.rs b/src/backend/gl/src/command.rs index d60105cffc..53123091ae 100644 --- a/src/backend/gl/src/command.rs +++ b/src/backend/gl/src/command.rs @@ -127,6 +127,7 @@ pub enum Command { dst_texture: n::Texture, texture_target: n::TextureTarget, texture_format: n::TextureFormat, + internal_format: n::TextureFormat, pixel_type: n::DataType, data: command::BufferImageCopy, }, @@ -1346,14 +1347,16 @@ impl command::CommandBuffer for CommandBuffer { n::ImageType::Texture { raw, target, - format, + format_external, + format_internal, pixel_type, .. } => Command::CopyBufferToTexture { src_buffer: src_bounded_buffer.raw, dst_texture: raw, texture_target: target, - texture_format: format, + texture_format: format_external, + internal_format: format_internal, pixel_type, data: r, }, @@ -1387,13 +1390,13 @@ impl command::CommandBuffer for CommandBuffer { n::ImageType::Texture { raw, target, - format, + format_external, pixel_type, .. } => Command::CopyTextureToBuffer { src_texture: raw, texture_target: target, - texture_format: format, + texture_format: format_external, pixel_type: pixel_type, dst_buffer: dst_bounded_buffer.raw, data: r, diff --git a/src/backend/gl/src/conv.rs b/src/backend/gl/src/conv.rs index 7ad694cb69..441a4f1cd1 100644 --- a/src/backend/gl/src/conv.rs +++ b/src/backend/gl/src/conv.rs @@ -1,6 +1,9 @@ use crate::native::VertexAttribFunction; -use hal::{format::Format, image as i, pso}; - +use hal::{ + format::Format, + image::{self as i, Extent}, + pso, +}; pub fn filter_to_gl(mag: i::Filter, min: i::Filter, mip: i::Filter) -> (u32, u32) { use hal::image::Filter::*; @@ -73,6 +76,70 @@ impl FormatDescription { } } +pub const COMPRESSED_RGB_S3TC_DXT1_EXT: u32 = 0x83F0; +pub const COMPRESSED_RGBA_S3TC_DXT1_EXT: u32 = 0x83F1; +pub const COMPRESSED_SRGB_S3TC_DXT1_EXT: u32 = 0x8C4C; +pub const COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: u32 = 0x8C4D; +pub const COMPRESSED_RGBA_S3TC_DXT3_EXT: u32 = 0x83F2; +pub const COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: u32 = 0x8C4E; +pub const COMPRESSED_RGBA_S3TC_DXT5_EXT: u32 = 0x83F3; +pub const COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: u32 = 0x8C4F; + +#[derive(Clone, Debug)] +pub struct CompressedFormatInfo { + pub internal_format: u32, + pub compressed_block_width: u32, + pub compressed_block_height: u32, + pub compressed_block_depth: u32, + pub compressed_block_size: u32, + pub component_count: u32, + pub srgb: bool, +} + +impl CompressedFormatInfo { + const fn new( + internal_format: u32, + compressed_block_width: u32, + compressed_block_height: u32, + compressed_block_depth: u32, + compressed_block_size: u32, + component_count: u32, + srgb: bool, + ) -> Self { + Self { + internal_format, + compressed_block_width, + compressed_block_height, + compressed_block_depth, + compressed_block_size, + component_count, + srgb, + } + } + + pub const fn compute_compressed_image_size(&self, size: Extent) -> u32 { + let num_blocks_wide = + (size.width + self.compressed_block_width - 1) / self.compressed_block_width; + let num_blocks_high = + (size.height + self.compressed_block_height - 1) / self.compressed_block_height; + num_blocks_wide * num_blocks_high * (self.compressed_block_size / 8) * size.depth + } +} + +pub const fn compressed_format_info(f: u32) -> Option { + Some(match f { + COMPRESSED_RGB_S3TC_DXT1_EXT => CompressedFormatInfo::new(f, 4, 4, 1, 64, 3, false), + COMPRESSED_RGBA_S3TC_DXT1_EXT => CompressedFormatInfo::new(f, 4, 4, 1, 64, 4, false), + COMPRESSED_SRGB_S3TC_DXT1_EXT => CompressedFormatInfo::new(f, 4, 4, 1, 64, 3, true), + COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT => CompressedFormatInfo::new(f, 4, 4, 1, 64, 4, true), + COMPRESSED_RGBA_S3TC_DXT3_EXT => CompressedFormatInfo::new(f, 4, 4, 1, 128, 4, false), + COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT => CompressedFormatInfo::new(f, 4, 4, 1, 128, 4, true), + COMPRESSED_RGBA_S3TC_DXT5_EXT => CompressedFormatInfo::new(f, 4, 4, 1, 128, 4, false), + COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT => CompressedFormatInfo::new(f, 4, 4, 1, 128, 4, true), + _ => return None, + }) +} + pub fn describe_format(format: Format) -> Option { use crate::native::VertexAttribFunction::*; use hal::format::Format::*; @@ -236,7 +303,62 @@ pub fn describe_format(format: Format) -> Option { 2, Float, ), - + Bc1RgbUnorm => FormatDescription::new( + COMPRESSED_RGB_S3TC_DXT1_EXT, + glow::RGB, + glow::INVALID_ENUM, + 3, + Float, + ), + Bc1RgbSrgb => FormatDescription::new( + COMPRESSED_SRGB_S3TC_DXT1_EXT, + glow::RGB, + glow::INVALID_ENUM, + 3, + Float, + ), + Bc1RgbaUnorm => FormatDescription::new( + COMPRESSED_RGBA_S3TC_DXT1_EXT, + glow::RGBA, + glow::INVALID_ENUM, + 4, + Float, + ), + Bc1RgbaSrgb => FormatDescription::new( + COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, + glow::RGBA, + glow::INVALID_ENUM, + 4, + Float, + ), + Bc2Unorm => FormatDescription::new( + COMPRESSED_RGBA_S3TC_DXT3_EXT, + glow::RGBA, + glow::INVALID_ENUM, + 4, + Float, + ), + Bc2Srgb => FormatDescription::new( + COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, + glow::RGBA, + glow::INVALID_ENUM, + 4, + Float, + ), + Bc3Unorm => FormatDescription::new( + COMPRESSED_RGBA_S3TC_DXT5_EXT, + glow::RGBA, + glow::INVALID_ENUM, + 4, + Float, + ), + Bc3Srgb => FormatDescription::new( + COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, + glow::RGBA, + glow::INVALID_ENUM, + 4, + Float, + ), _ => return None, }) } diff --git a/src/backend/gl/src/device.rs b/src/backend/gl/src/device.rs index 319c6b6d3d..c07d90c0e5 100644 --- a/src/backend/gl/src/device.rs +++ b/src/backend/gl/src/device.rs @@ -1572,7 +1572,8 @@ impl d::Device for Device { n::ImageType::Texture { target, raw: name, - format: desc.tex_external, + format_internal: desc.tex_internal, + format_external: desc.tex_external, pixel_type: desc.data_type, layer_count: kind.num_layers(), level_count: num_levels, @@ -1690,7 +1691,7 @@ impl d::Device for Device { n::ImageType::Texture { target, raw, - format, + format_external: format, .. } => { match conv::describe_format(view_format) { diff --git a/src/backend/gl/src/info.rs b/src/backend/gl/src/info.rs index 3a3229fee3..2d02118c95 100644 --- a/src/backend/gl/src/info.rs +++ b/src/backend/gl/src/info.rs @@ -626,6 +626,7 @@ pub(crate) fn query_all( max_color_attachments: get_usize(gl, glow::MAX_COLOR_ATTACHMENTS) .unwrap_or(1) .min(MAX_COLOR_ATTACHMENTS), + max_memory_allocation_count: 4096, ..Limits::default() }; @@ -689,6 +690,13 @@ pub(crate) fn query_all( { features |= Features::INDEPENDENT_BLENDING; } + if info.is_supported(&[ + Es(3, 0), + Ext("WEBGL_compressed_texture_s3tc"), + Ext("WEBGL_compressed_texture_s3tc_srgb"), + ]) { + features |= Features::FORMAT_BC; + } // TODO if false && info.is_supported(&[Core(4, 3), Es(3, 1)]) { @@ -749,7 +757,6 @@ pub(crate) fn query_all( if info.is_supported(&[Core(3, 3), Es(3, 0)]) { legacy |= LegacyFeatures::INSTANCED_ATTRIBUTE_BINDING; } - let mut performance_caveats = PerformanceCaveats::empty(); //TODO: extension if !info.is_supported(&[Core(4, 2)]) { diff --git a/src/backend/gl/src/native.rs b/src/backend/gl/src/native.rs index 6376ecf74f..436c2b46a7 100644 --- a/src/backend/gl/src/native.rs +++ b/src/backend/gl/src/native.rs @@ -151,7 +151,8 @@ pub enum ImageType { raw: Texture, level_count: i::Level, layer_count: i::Layer, - format: TextureFormat, + format_internal: TextureFormat, + format_external: TextureFormat, pixel_type: DataType, }, } diff --git a/src/backend/gl/src/queue.rs b/src/backend/gl/src/queue.rs index 3cf9e23bcb..644b20939b 100644 --- a/src/backend/gl/src/queue.rs +++ b/src/backend/gl/src/queue.rs @@ -1,6 +1,6 @@ use crate::{ - command as com, device, info::LegacyFeatures, native, state, Backend, Device, GlContext, Share, - Starc, Surface, MAX_COLOR_ATTACHMENTS, + command as com, conv, device, info::LegacyFeatures, native, state, Backend, Device, GlContext, + Share, Starc, Surface, MAX_COLOR_ATTACHMENTS, }; use arrayvec::ArrayVec; @@ -637,7 +637,6 @@ impl Queue { glow::COPY_WRITE_BUFFER }; let gl = &self.share.context; - gl.bind_buffer(copy_src_target, Some(src_buffer)); gl.bind_buffer(copy_dst_target, Some(dst_buffer)); @@ -668,6 +667,7 @@ impl Queue { dst_texture, texture_target, texture_format, + internal_format, pixel_type, ref data, } => unsafe { @@ -680,8 +680,19 @@ impl Queue { gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, Some(src_buffer)); gl.bind_texture(texture_target, Some(dst_texture)); - match texture_target { - glow::TEXTURE_2D => { + let compressed_format = conv::compressed_format_info(internal_format); + + 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, + ]; + + match (texture_target, compressed_format) { + (glow::TEXTURE_2D, None) => { gl.tex_sub_image_2d( texture_target, data.image_layers.level as _, @@ -694,7 +705,24 @@ impl Queue { glow::PixelUnpackData::BufferOffset(data.buffer_offset as u32), ); } - glow::TEXTURE_2D_ARRAY | glow::TEXTURE_3D => { + (glow::TEXTURE_2D, Some(compressed_info)) => { + let layer_size = + compressed_info.compute_compressed_image_size(data.image_extent); + let mut buffer_offset = data.buffer_offset as u32; + gl.compressed_tex_sub_image_2d( + texture_target, + data.image_layers.level as _, + data.image_offset.x, + data.image_offset.y, + data.image_extent.width as _, + data.image_extent.height as _, + internal_format, + glow::CompressedPixelUnpackData::BufferRange( + buffer_offset..buffer_offset + layer_size, + ), + ); + } + (glow::TEXTURE_2D_ARRAY, None) | (glow::TEXTURE_3D, None) => { gl.tex_sub_image_3d( texture_target, data.image_layers.level as _, @@ -710,7 +738,7 @@ impl Queue { glow::PixelUnpackData::BufferOffset(data.buffer_offset as u32), ); } - glow::TEXTURE_CUBE_MAP => { + (glow::TEXTURE_CUBE_MAP, None) => { let components = match texture_format { glow::RED | glow::RED_INTEGER @@ -738,15 +766,7 @@ impl Queue { let faces_range = data.image_layers.layers.start as usize ..data.image_layers.layers.end as usize; - for &face in &[ - 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, - ][faces_range] - { + for &face in &CUBEMAP_FACES[faces_range] { gl.tex_sub_image_2d( face, data.image_layers.level as _, @@ -761,6 +781,29 @@ impl Queue { buffer_offset += layer_size; } } + (glow::TEXTURE_CUBE_MAP, Some(compressed_info)) => { + let mut buffer_offset = data.buffer_offset as u32; + let layer_size = + compressed_info.compute_compressed_image_size(data.image_extent); + + let faces_range = data.image_layers.layers.start as usize + ..data.image_layers.layers.end as usize; + for &face in &CUBEMAP_FACES[faces_range] { + gl.compressed_tex_sub_image_2d( + face, + data.image_layers.level as _, + data.image_offset.x, + data.image_offset.y, + data.image_extent.width as _, + data.image_extent.height as _, + internal_format, + glow::CompressedPixelUnpackData::BufferRange( + buffer_offset..buffer_offset + layer_size, + ), + ); + buffer_offset += layer_size; + } + } _ => unimplemented!(), } diff --git a/src/backend/metal/src/command.rs b/src/backend/metal/src/command.rs index 22657803b3..55b4be4ede 100644 --- a/src/backend/metal/src/command.rs +++ b/src/backend/metal/src/command.rs @@ -775,7 +775,9 @@ impl State { result_sizes.clear(); for br in stage_info.sized_bindings.iter() { // If it's None, this isn't the right time to update the sizes - let size = self.storage_buffer_length_map.get(&(br.group as pso::DescriptorSetIndex, br.binding))?; + let size = self + .storage_buffer_length_map + .get(&(br.group as pso::DescriptorSetIndex, br.binding))?; result_sizes.push(*size); } Some(slot as _)