Skip to content

Add feature gated 16-bit normalized texture support #2282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 13, 2021

Conversation

aloucks
Copy link
Contributor

@aloucks aloucks commented Dec 11, 2021

Connections
Fixes #1934

Description
Adds 16-bit signed and unsigned normalized texture format support for Vulkan, DX12, and Metal backends via a new TEXTURE_FORMAT_16BIT_NORM feature (I'm open to bikeshedding the name).

It appears that 16-bit normalized formats are supported for filtered sampling everywhere expect older android devices, based on what I can tell from the following sources:

Testing

I used a modified version of the texture-arrays example to test the Vulkan backend. I have not tested the DX12 or Metal backends.

diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs
index af074e21..05eac6d7 100644
--- a/wgpu/examples/texture-arrays/main.rs
+++ b/wgpu/examples/texture-arrays/main.rs
@@ -53,10 +53,11 @@ enum Color {
     Green,
 }
 
-fn create_texture_data(color: Color) -> [u8; 4] {
+fn create_texture_data(color: Color) -> [u16; 4] {
+    let max = u16::MAX;
     match color {
-        Color::Red => [255, 0, 0, 255],
-        Color::Green => [0, 255, 0, 255],
+        Color::Red => [max, 0, 0, max],
+        Color::Green => [0, max, 0, max],
     }
 }
 
@@ -76,7 +77,9 @@ impl framework::Example for Example {
             | wgpu::Features::PUSH_CONSTANTS
     }
     fn required_features() -> wgpu::Features {
-        wgpu::Features::TEXTURE_BINDING_ARRAY | wgpu::Features::SPIRV_SHADER_PASSTHROUGH
+        wgpu::Features::TEXTURE_BINDING_ARRAY
+            | wgpu::Features::SPIRV_SHADER_PASSTHROUGH
+            | wgpu::Features::TEXTURE_FORMAT_16BIT_NORM
     }
     fn required_limits() -> wgpu::Limits {
         wgpu::Limits {
@@ -133,7 +136,7 @@ impl framework::Example for Example {
             mip_level_count: 1,
             sample_count: 1,
             dimension: wgpu::TextureDimension::D2,
-            format: wgpu::TextureFormat::Rgba8UnormSrgb,
+            format: wgpu::TextureFormat::Rgba16Unorm,
             usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
             label: None,
         };
@@ -151,20 +154,20 @@ impl framework::Example for Example {
 
         queue.write_texture(
             red_texture.as_image_copy(),
-            &red_texture_data,
+            bytemuck::bytes_of(&red_texture_data),
             wgpu::ImageDataLayout {
                 offset: 0,
-                bytes_per_row: Some(NonZeroU32::new(4).unwrap()),
+                bytes_per_row: Some(NonZeroU32::new(8).unwrap()),
                 rows_per_image: None,
             },
             wgpu::Extent3d::default(),
         );
         queue.write_texture(
             green_texture.as_image_copy(),
-            &green_texture_data,
+            bytemuck::bytes_of(&green_texture_data),
             wgpu::ImageDataLayout {
                 offset: 0,
-                bytes_per_row: Some(NonZeroU32::new(4).unwrap()),
+                bytes_per_row: Some(NonZeroU32::new(8).unwrap()),
                 rows_per_image: None,
             },
             wgpu::Extent3d::default(),

@kvark
Copy link
Member

kvark commented Dec 12, 2021

Main question is, what usages are guaranteed to be supported by this feature? In Vulkan, not all usages are guaranteed to be supported. Even worse, on Metal these formats can't be resolve targets, even though you can render to them! Since we don't have a RESOLVE usage, this becomes a bit problematic. I filed gpuweb/gpuweb#2408 upstream to discuss this.

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super solid work! Just one thing to figure out

@aloucks aloucks force-pushed the norm16 branch 2 times, most recently from 8247481 to 1bf1fe3 Compare December 12, 2021 05:17
@aloucks aloucks marked this pull request as ready for review December 13, 2021 14:07
@aloucks
Copy link
Contributor Author

aloucks commented Dec 14, 2021

@kvark Could this also be backported to v0.11?

@kvark
Copy link
Member

kvark commented Dec 14, 2021

Technically, it changes enum TextureFormat, which is non-exhaustive and public. So we can't simply back-port it.

@aloucks
Copy link
Contributor Author

aloucks commented Dec 14, 2021

Technically, it changes enum TextureFormat, which is non-exhaustive and public. So we can't simply back-port it.

Ah, right, that makes sense. Should TextureFormat become non-exhaustive eventually so that new formats could be added without causing breakage?

And, is 0.12 on the horizon for a release soon? I'm really hoping the 16-bit formats will be available in the next release of bevy.

@kvark
Copy link
Member

kvark commented Dec 14, 2021

It's not exactly trivial. Generally, marking an enum as non-exhaustive only affects the public users of a library. That is, library logic can still treat it as any other enum, and do exhaustive matching. wgpu-hal needs to do a lot of matching of texture formats in the backends. However, enum TextureFormat lives in wgpu-types, so it's external to wgpu-hal... Therefore, wgpu-hal would have to match it with a catch-all case at all times.

With this in mind, I think we should just start preparing for wgpu-0.12. Do you have a schedule for Bevy that we'd need to align to?

@aloucks
Copy link
Contributor Author

aloucks commented Dec 15, 2021

Do you have a schedule for Bevy that we'd need to align to?

I couldn't say when 0.6 will be released, but the new pipelined renderer is a major milestone for 0.6 and it's now been merged into main. Once bevy-0.6 is released, it won't be possible to upgrade to wgpu-0.12 until bevy-0.7 and I imagine that will be quite a long time from now. Ideally wgpu-0.12 is released "soon" and bevy can upgrade before 0.6.

@aloucks aloucks deleted the norm16 branch December 15, 2021 18:26
cwfitzgerald pushed a commit that referenced this pull request Oct 25, 2023
* Support buffer resource arrays in IR, wgsl-in, and spv-out

* spv-out: refactor non-uniform indexing semantics to support buffers

* Update the doc comment on BindingArray type

* Improve TypeInfo restrictions on binding arrays

* Strip DATA out of binding arrays

* Include suggested documentation, more binding array tests, enforce structs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support normalized 16-bit texture formats
2 participants