From 8cd4bd602fdc09aef3692ab018f17eca21422712 Mon Sep 17 00:00:00 2001 From: Jamie Nicol Date: Wed, 25 Jun 2025 08:48:57 +0100 Subject: [PATCH] [naga hlsl-out] Handle external texture color space conversion This adds several fields to `ExternalTextureDescriptor`, specifying how to handle color space conversion for an external texture. These fields consist of transfer functions for the source and destination color spaces, and a matrix for converting between gamuts. This allows `ImageSample` and `ImageLoad` operations on external textures to return values in a desired destination color space rather than the source color space of the underlying planes. These fields are plumbed through to the `ExternalTextureParams` uniform buffer from which they are exposed to the shader. Following conversion from YUV to RGB after sampling/loading from the external texture planes, the shader uses them to gamma decode to linear RGB in the source color space, convert from source to destination gamut, then finally gamma encode to non-linear RGB in the destination color space. --- naga/src/back/hlsl/help.rs | 70 +++++++++-- naga/src/back/wgsl/writer.rs | 1 + naga/src/compact/mod.rs | 11 ++ naga/src/front/type_gen.rs | 105 ++++++++++++++-- naga/src/front/wgsl/lower/mod.rs | 13 +- naga/src/ir/mod.rs | 41 ++++-- .../tests/out/hlsl/wgsl-texture-external.hlsl | 31 ++++- naga/tests/out/ir/spv-fetch_depth.compact.ron | 1 + naga/tests/out/ir/spv-fetch_depth.ron | 1 + naga/tests/out/ir/spv-shadow.compact.ron | 1 + naga/tests/out/ir/spv-shadow.ron | 1 + .../out/ir/spv-spec-constants.compact.ron | 1 + naga/tests/out/ir/spv-spec-constants.ron | 1 + naga/tests/out/ir/wgsl-access.compact.ron | 1 + naga/tests/out/ir/wgsl-access.ron | 1 + naga/tests/out/ir/wgsl-collatz.compact.ron | 1 + naga/tests/out/ir/wgsl-collatz.ron | 1 + .../out/ir/wgsl-const_assert.compact.ron | 1 + naga/tests/out/ir/wgsl-const_assert.ron | 1 + .../out/ir/wgsl-diagnostic-filter.compact.ron | 1 + naga/tests/out/ir/wgsl-diagnostic-filter.ron | 1 + .../out/ir/wgsl-index-by-value.compact.ron | 1 + naga/tests/out/ir/wgsl-index-by-value.ron | 1 + .../tests/out/ir/wgsl-local-const.compact.ron | 1 + naga/tests/out/ir/wgsl-local-const.ron | 1 + naga/tests/out/ir/wgsl-must-use.compact.ron | 1 + naga/tests/out/ir/wgsl-must-use.ron | 1 + ...ides-atomicCompareExchangeWeak.compact.ron | 1 + ...sl-overrides-atomicCompareExchangeWeak.ron | 1 + .../ir/wgsl-overrides-ray-query.compact.ron | 1 + .../tests/out/ir/wgsl-overrides-ray-query.ron | 1 + naga/tests/out/ir/wgsl-overrides.compact.ron | 1 + naga/tests/out/ir/wgsl-overrides.ron | 1 + .../out/ir/wgsl-storage-textures.compact.ron | 1 + naga/tests/out/ir/wgsl-storage-textures.ron | 1 + ...l-template-list-trailing-comma.compact.ron | 1 + .../ir/wgsl-template-list-trailing-comma.ron | 1 + .../out/ir/wgsl-texture-external.compact.ron | 119 ++++++++++++++---- naga/tests/out/ir/wgsl-texture-external.ron | 119 ++++++++++++++---- .../ir/wgsl-types_with_comments.compact.ron | 1 + .../tests/out/ir/wgsl-types_with_comments.ron | 1 + .../wgpu-validation/api/external_texture.rs | 45 +++++++ wgpu-core/src/device/resource.rs | 57 ++++++++- wgpu-types/src/lib.rs | 49 ++++++++ wgpu/src/lib.rs | 29 ++--- 45 files changed, 614 insertions(+), 108 deletions(-) diff --git a/naga/src/back/hlsl/help.rs b/naga/src/back/hlsl/help.rs index 70c0a692a..8083d15e8 100644 --- a/naga/src/back/hlsl/help.rs +++ b/naga/src/back/hlsl/help.rs @@ -264,6 +264,61 @@ impl super::Writer<'_, W> { Ok(()) } + /// Helper function used by [`Self::write_wrapped_image_load_function`] and + /// [`Self::write_wrapped_image_sample_function`] to write the shared YUV + /// to RGB conversion code for external textures. Expects the preceding + /// code to declare the Y component as a `float` variable of name `y`, the + /// UV components as a `float2` variable of name `uv`, and the external + /// texture params as a variable of name `params`. The emitted code will + /// return the result. + fn write_convert_yuv_to_rgb_and_return( + &mut self, + level: crate::back::Level, + y: &str, + uv: &str, + params: &str, + ) -> BackendResult { + let l1 = level; + let l2 = l1.next(); + + // Convert from YUV to non-linear RGB in the source color space. We + // declare our matrices as row_major in HLSL, therefore we must reverse + // the order of this multiplication + writeln!( + self.out, + "{l1}float3 srcGammaRgb = mul(float4({y}, {uv}, 1.0), {params}.yuv_conversion_matrix).rgb;" + )?; + + // Apply the inverse of the source transfer function to convert to + // linear RGB in the source color space. + writeln!( + self.out, + "{l1}float3 srcLinearRgb = srcGammaRgb < {params}.src_tf.k * {params}.src_tf.b ?" + )?; + writeln!(self.out, "{l2}srcGammaRgb / {params}.src_tf.k :")?; + writeln!(self.out, "{l2}pow((srcGammaRgb + {params}.src_tf.a - 1.0) / {params}.src_tf.a, {params}.src_tf.g);")?; + + // Multiply by the gamut conversion matrix to convert to linear RGB in + // the destination color space. We declare our matrices as row_major in + // HLSL, therefore we must reverse the order of this multiplication. + writeln!( + self.out, + "{l1}float3 dstLinearRgb = mul(srcLinearRgb, {params}.gamut_conversion_matrix);" + )?; + + // Finally, apply the dest transfer function to convert to non-linear + // RGB in the destination color space, and return the result. + writeln!( + self.out, + "{l1}float3 dstGammaRgb = dstLinearRgb < {params}.dst_tf.b ?" + )?; + writeln!(self.out, "{l2}{params}.dst_tf.k * dstLinearRgb :")?; + writeln!(self.out, "{l2}{params}.dst_tf.a * pow(dstLinearRgb, 1.0 / {params}.dst_tf.g) - ({params}.dst_tf.a - 1);")?; + + writeln!(self.out, "{l1}return float4(dstGammaRgb, 1.0);")?; + Ok(()) + } + pub(super) fn write_wrapped_image_load_function( &mut self, module: &crate::Module, @@ -346,12 +401,7 @@ impl super::Writer<'_, W> { writeln!(self.out, "{l3}uv = float2(plane1.Load(uint3(plane1_coords, 0u)).x, plane2.Load(uint3(plane2_coords, 0u)).x);")?; writeln!(self.out, "{l2}}}")?; - // Convert from YUV to RGB. We declare our matrices as row_major in HLSL, - // therefore we must reverse the order of this multiplication - writeln!( - self.out, - "{l2}return mul(float4(y, uv, 1.0), params.yuv_conversion_matrix);" - )?; + self.write_convert_yuv_to_rgb_and_return(l2, "y", "uv", "params")?; writeln!(self.out, "{l1}}}")?; writeln!(self.out, "}}")?; @@ -478,12 +528,8 @@ impl super::Writer<'_, W> { writeln!(self.out, "{l3}uv = float2(plane1.SampleLevel(samp, plane1_coords, 0.0f).x, plane2.SampleLevel(samp, plane2_coords, 0.0f).x);")?; writeln!(self.out, "{l2}}}")?; - // Convert from YUV to RGB. We declare our matrices as row_major in HLSL, - // therefore we must reverse the order of this multiplication - writeln!( - self.out, - "{l2}return mul(float4(y, uv, 1.0), params.yuv_conversion_matrix);" - )?; + self.write_convert_yuv_to_rgb_and_return(l2, "y", "uv", "params")?; + writeln!(self.out, "{l1}}}")?; writeln!(self.out, "}}")?; writeln!(self.out)?; diff --git a/naga/src/back/wgsl/writer.rs b/naga/src/back/wgsl/writer.rs index dd2696c17..8982242da 100644 --- a/naga/src/back/wgsl/writer.rs +++ b/naga/src/back/wgsl/writer.rs @@ -131,6 +131,7 @@ impl Writer { .values() .any(|t| *t == ty) || Some(ty) == module.special_types.external_texture_params + || Some(ty) == module.special_types.external_texture_transfer_function } pub fn write(&mut self, module: &Module, info: &valid::ModuleInfo) -> BackendResult { diff --git a/naga/src/compact/mod.rs b/naga/src/compact/mod.rs index 7fbb5c532..d059ba21e 100644 --- a/naga/src/compact/mod.rs +++ b/naga/src/compact/mod.rs @@ -381,6 +381,7 @@ impl<'module> ModuleTracer<'module> { ref ray_vertex_return, ref predeclared_types, ref external_texture_params, + ref external_texture_transfer_function, } = *special_types; if let Some(ray_desc) = *ray_desc { @@ -398,6 +399,9 @@ impl<'module> ModuleTracer<'module> { if let Some(external_texture_params) = *external_texture_params { self.types_used.insert(external_texture_params); } + if let Some(external_texture_transfer_function) = *external_texture_transfer_function { + self.types_used.insert(external_texture_transfer_function); + } for (_, &handle) in predeclared_types { self.types_used.insert(handle); } @@ -540,6 +544,7 @@ impl ModuleMap { ref mut ray_vertex_return, ref mut predeclared_types, ref mut external_texture_params, + ref mut external_texture_transfer_function, } = *special; if let Some(ref mut ray_desc) = *ray_desc { @@ -557,6 +562,12 @@ impl ModuleMap { self.types.adjust(external_texture_params); } + if let Some(ref mut external_texture_transfer_function) = + *external_texture_transfer_function + { + self.types.adjust(external_texture_transfer_function); + } + for handle in predeclared_types.values_mut() { self.types.adjust(handle); } diff --git a/naga/src/front/type_gen.rs b/naga/src/front/type_gen.rs index d58561796..4165f051d 100644 --- a/naga/src/front/type_gen.rs +++ b/naga/src/front/type_gen.rs @@ -276,14 +276,29 @@ impl crate::Module { handle } - /// Generate [`SpecialTypes::external_texture_params`]. + /// Generate [`SpecialTypes::external_texture_params`] and + /// [`SpecialTypes::external_texture_transfer_function`]. + /// + /// Other than the WGSL backend, every backend that supports external + /// textures does so by lowering them to a set of ordinary textures and + /// some parameters saying how to sample from them. These types are used + /// for said parameters. Note that they are not used by the IR, but + /// generated purely as a convenience for the backends. /// /// [`SpecialTypes::external_texture_params`]: crate::ir::SpecialTypes::external_texture_params - pub fn generate_external_texture_params_type(&mut self) -> Handle { - if let Some(handle) = self.special_types.external_texture_params { - return handle; + /// [`SpecialTypes::external_texture_transfer_function`]: crate::ir::SpecialTypes::external_texture_transfer_function + pub fn generate_external_texture_types(&mut self) { + if self.special_types.external_texture_params.is_some() { + return; } + let ty_f32 = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Scalar(crate::Scalar::F32), + }, + Span::UNDEFINED, + ); let ty_u32 = self.types.insert( crate::Type { name: None, @@ -312,6 +327,17 @@ impl crate::Module { }, Span::UNDEFINED, ); + let ty_mat3x3f = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Matrix { + columns: crate::VectorSize::Tri, + rows: crate::VectorSize::Tri, + scalar: crate::Scalar::F32, + }, + }, + Span::UNDEFINED, + ); let ty_mat4x4f = self.types.insert( crate::Type { name: None, @@ -324,7 +350,44 @@ impl crate::Module { Span::UNDEFINED, ); - let handle = self.types.insert( + let transfer_fn_handle = self.types.insert( + crate::Type { + name: Some("NagaExternalTextureTransferFn".to_string()), + inner: crate::TypeInner::Struct { + members: vec![ + crate::StructMember { + name: Some("a".to_string()), + ty: ty_f32, + binding: None, + offset: 0, + }, + crate::StructMember { + name: Some("b".to_string()), + ty: ty_f32, + binding: None, + offset: 4, + }, + crate::StructMember { + name: Some("g".to_string()), + ty: ty_f32, + binding: None, + offset: 8, + }, + crate::StructMember { + name: Some("k".to_string()), + ty: ty_f32, + binding: None, + offset: 12, + }, + ], + span: 16, + }, + }, + Span::UNDEFINED, + ); + self.special_types.external_texture_transfer_function = Some(transfer_fn_handle); + + let params_handle = self.types.insert( crate::Type { name: Some("NagaExternalTextureParams".to_string()), inner: crate::TypeInner::Struct { @@ -335,39 +398,55 @@ impl crate::Module { binding: None, offset: 0, }, + crate::StructMember { + name: Some("gamut_conversion_matrix".to_string()), + ty: ty_mat3x3f, + binding: None, + offset: 64, + }, + crate::StructMember { + name: Some("src_tf".to_string()), + ty: transfer_fn_handle, + binding: None, + offset: 112, + }, + crate::StructMember { + name: Some("dst_tf".to_string()), + ty: transfer_fn_handle, + binding: None, + offset: 128, + }, crate::StructMember { name: Some("sample_transform".to_string()), ty: ty_mat3x2f, binding: None, - offset: 64, + offset: 144, }, crate::StructMember { name: Some("load_transform".to_string()), ty: ty_mat3x2f, binding: None, - offset: 88, + offset: 168, }, crate::StructMember { name: Some("size".to_string()), ty: ty_vec2u, binding: None, - offset: 112, + offset: 192, }, crate::StructMember { name: Some("num_planes".to_string()), ty: ty_u32, binding: None, - offset: 120, + offset: 200, }, ], - span: 128, + span: 208, }, }, Span::UNDEFINED, ); - - self.special_types.external_texture_params = Some(handle); - handle + self.special_types.external_texture_params = Some(params_handle); } /// Populate this module's [`SpecialTypes::predeclared_types`] type and return the handle. diff --git a/naga/src/front/wgsl/lower/mod.rs b/naga/src/front/wgsl/lower/mod.rs index 3b6e7806c..e90d7eab0 100644 --- a/naga/src/front/wgsl/lower/mod.rs +++ b/naga/src/front/wgsl/lower/mod.rs @@ -3991,14 +3991,15 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { // sample from them. We don't know which backend will // consume the `Module` we're building, but in case it's not // WGSL, populate `SpecialTypes::external_texture_params` - // with the type the backend will use for the parameter + // and `SpecialTypes::external_texture_transfer_function` + // with the types the backend will use for the parameter // buffer. // - // This is *not* the type we are lowering here: that's an - // ordinary `TypeInner::Image`. But the fact we are - // lowering a `texture_external` implies the backends may - // need `SpecialTypes::external_texture_params` too. - ctx.module.generate_external_texture_params_type(); + // Neither of these are the type we are lowering here: + // that's an ordinary `TypeInner::Image`. But the fact we + // are lowering a `texture_external` implies the backends + // may need these additional types too. + ctx.module.generate_external_texture_types(); } ir::TypeInner::Image { dim, diff --git a/naga/src/ir/mod.rs b/naga/src/ir/mod.rs index 50cc89a5b..257445952 100644 --- a/naga/src/ir/mod.rs +++ b/naga/src/ir/mod.rs @@ -2369,19 +2369,42 @@ pub struct SpecialTypes { /// In WGSL, this type would be: /// /// ```ignore - /// struct NagaExternalTextureParams { // align size offset - /// yuv_conversion_matrix: mat4x4, // 16 64 0 - /// sample_transform: mat3x2, // 8 24 64 - /// load_transform: mat3x2, // 8 24 88 - /// size: vec2, // 8 8 112 - /// num_planes: u32, // 4 4 120 - /// } // whole struct: 16 128 + /// struct NagaExternalTextureParams { // align size offset + /// yuv_conversion_matrix: mat4x4, // 16 64 0 + /// gamut_conversion_matrix: mat3x3, // 16 48 64 + /// src_tf: NagaExternalTextureTransferFn, // 4 16 112 + /// dst_tf: NagaExternalTextureTransferFn, // 4 16 128 + /// sample_transform: mat3x2, // 8 24 144 + /// load_transform: mat3x2, // 8 24 168 + /// size: vec2, // 8 8 192 + /// num_planes: u32, // 4 4 200 + /// } // whole struct: 16 208 /// ``` /// - /// Call [`Module::generate_external_texture_params_type`] to populate this - /// if needed and return the handle. + /// Call [`Module::generate_external_texture_types`] to populate this if + /// needed. pub external_texture_params: Option>, + /// Struct describing a gamma encoding transfer function. Member of + /// `NagaExternalTextureParams`, describing how the backend should perform + /// color space conversion when sampling from [`ImageClass::External`] + /// textures. + /// + /// In WGSL, this type would be: + /// + /// ```ignore + /// struct NagaExternalTextureTransferFn { // align size offset + /// a: f32, // 4 4 0 + /// b: f32, // 4 4 4 + /// g: f32, // 4 4 8 + /// k: f32, // 4 4 12 + /// } // whole struct: 4 16 + /// ``` + /// + /// Call [`Module::generate_external_texture_types`] to populate this if + /// needed. + pub external_texture_transfer_function: Option>, + /// Types for predeclared wgsl types instantiated on demand. /// /// Call [`Module::generate_predeclared_type`] to populate this if diff --git a/naga/tests/out/hlsl/wgsl-texture-external.hlsl b/naga/tests/out/hlsl/wgsl-texture-external.hlsl index 517d6a724..dbf57609d 100644 --- a/naga/tests/out/hlsl/wgsl-texture-external.hlsl +++ b/naga/tests/out/hlsl/wgsl-texture-external.hlsl @@ -1,5 +1,16 @@ +struct NagaExternalTextureTransferFn { + float a; + float b; + float g; + float k; +}; + struct NagaExternalTextureParams { row_major float4x4 yuv_conversion_matrix; + row_major float3x3 gamut_conversion_matrix; + int _pad2_0; + NagaExternalTextureTransferFn src_tf; + NagaExternalTextureTransferFn dst_tf; float2 sample_transform_0; float2 sample_transform_1; float2 sample_transform_2; float2 load_transform_0; float2 load_transform_1; float2 load_transform_2; uint2 size; @@ -55,7 +66,15 @@ float4 nagaTextureSampleBaseClampToEdge( float2 plane2_coords = clamp(coords, bounds.xy + plane2_half_texel, bounds.zw - plane2_half_texel); uv = float2(plane1.SampleLevel(samp, plane1_coords, 0.0f).x, plane2.SampleLevel(samp, plane2_coords, 0.0f).x); } - return mul(float4(y, uv, 1.0), params.yuv_conversion_matrix); + float3 srcGammaRgb = mul(float4(y, uv, 1.0), params.yuv_conversion_matrix).rgb; + float3 srcLinearRgb = srcGammaRgb < params.src_tf.k * params.src_tf.b ? + srcGammaRgb / params.src_tf.k : + pow((srcGammaRgb + params.src_tf.a - 1.0) / params.src_tf.a, params.src_tf.g); + float3 dstLinearRgb = mul(srcLinearRgb, params.gamut_conversion_matrix); + float3 dstGammaRgb = dstLinearRgb < params.dst_tf.b ? + params.dst_tf.k * dstLinearRgb : + params.dst_tf.a * pow(dstLinearRgb, 1.0 / params.dst_tf.g) - (params.dst_tf.a - 1); + return float4(dstGammaRgb, 1.0); } } @@ -92,7 +111,15 @@ float4 nagaTextureLoadExternal( uint2 plane2_coords = uint2(floor(float2(plane0_coords) * float2(plane2_size) / float2(plane0_size))); uv = float2(plane1.Load(uint3(plane1_coords, 0u)).x, plane2.Load(uint3(plane2_coords, 0u)).x); } - return mul(float4(y, uv, 1.0), params.yuv_conversion_matrix); + float3 srcGammaRgb = mul(float4(y, uv, 1.0), params.yuv_conversion_matrix).rgb; + float3 srcLinearRgb = srcGammaRgb < params.src_tf.k * params.src_tf.b ? + srcGammaRgb / params.src_tf.k : + pow((srcGammaRgb + params.src_tf.a - 1.0) / params.src_tf.a, params.src_tf.g); + float3 dstLinearRgb = mul(srcLinearRgb, params.gamut_conversion_matrix); + float3 dstGammaRgb = dstLinearRgb < params.dst_tf.b ? + params.dst_tf.k * dstLinearRgb : + params.dst_tf.a * pow(dstLinearRgb, 1.0 / params.dst_tf.g) - (params.dst_tf.a - 1); + return float4(dstGammaRgb, 1.0); } } diff --git a/naga/tests/out/ir/spv-fetch_depth.compact.ron b/naga/tests/out/ir/spv-fetch_depth.compact.ron index c2b7b9b5f..1fbee2deb 100644 --- a/naga/tests/out/ir/spv-fetch_depth.compact.ron +++ b/naga/tests/out/ir/spv-fetch_depth.compact.ron @@ -68,6 +68,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/spv-fetch_depth.ron b/naga/tests/out/ir/spv-fetch_depth.ron index dd019d62a..186f78354 100644 --- a/naga/tests/out/ir/spv-fetch_depth.ron +++ b/naga/tests/out/ir/spv-fetch_depth.ron @@ -131,6 +131,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/spv-shadow.compact.ron b/naga/tests/out/ir/spv-shadow.compact.ron index 04547e651..b49cd9b55 100644 --- a/naga/tests/out/ir/spv-shadow.compact.ron +++ b/naga/tests/out/ir/spv-shadow.compact.ron @@ -156,6 +156,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/spv-shadow.ron b/naga/tests/out/ir/spv-shadow.ron index 0babda31f..e1f0f60b6 100644 --- a/naga/tests/out/ir/spv-shadow.ron +++ b/naga/tests/out/ir/spv-shadow.ron @@ -279,6 +279,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/spv-spec-constants.compact.ron b/naga/tests/out/ir/spv-spec-constants.compact.ron index a07dd0aca..3fa6ffef4 100644 --- a/naga/tests/out/ir/spv-spec-constants.compact.ron +++ b/naga/tests/out/ir/spv-spec-constants.compact.ron @@ -172,6 +172,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/spv-spec-constants.ron b/naga/tests/out/ir/spv-spec-constants.ron index 643d3c730..94c90aa78 100644 --- a/naga/tests/out/ir/spv-spec-constants.ron +++ b/naga/tests/out/ir/spv-spec-constants.ron @@ -263,6 +263,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/wgsl-access.compact.ron b/naga/tests/out/ir/wgsl-access.compact.ron index fff8d0bcf..30e88984f 100644 --- a/naga/tests/out/ir/wgsl-access.compact.ron +++ b/naga/tests/out/ir/wgsl-access.compact.ron @@ -422,6 +422,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-access.ron b/naga/tests/out/ir/wgsl-access.ron index fff8d0bcf..30e88984f 100644 --- a/naga/tests/out/ir/wgsl-access.ron +++ b/naga/tests/out/ir/wgsl-access.ron @@ -422,6 +422,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-collatz.compact.ron b/naga/tests/out/ir/wgsl-collatz.compact.ron index 30168b262..f72c652d0 100644 --- a/naga/tests/out/ir/wgsl-collatz.compact.ron +++ b/naga/tests/out/ir/wgsl-collatz.compact.ron @@ -45,6 +45,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-collatz.ron b/naga/tests/out/ir/wgsl-collatz.ron index 30168b262..f72c652d0 100644 --- a/naga/tests/out/ir/wgsl-collatz.ron +++ b/naga/tests/out/ir/wgsl-collatz.ron @@ -45,6 +45,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-const_assert.compact.ron b/naga/tests/out/ir/wgsl-const_assert.compact.ron index 4d77a5749..2816364f8 100644 --- a/naga/tests/out/ir/wgsl-const_assert.compact.ron +++ b/naga/tests/out/ir/wgsl-const_assert.compact.ron @@ -5,6 +5,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-const_assert.ron b/naga/tests/out/ir/wgsl-const_assert.ron index 4d77a5749..2816364f8 100644 --- a/naga/tests/out/ir/wgsl-const_assert.ron +++ b/naga/tests/out/ir/wgsl-const_assert.ron @@ -5,6 +5,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-diagnostic-filter.compact.ron b/naga/tests/out/ir/wgsl-diagnostic-filter.compact.ron index 10f533f10..c5746696d 100644 --- a/naga/tests/out/ir/wgsl-diagnostic-filter.compact.ron +++ b/naga/tests/out/ir/wgsl-diagnostic-filter.compact.ron @@ -5,6 +5,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-diagnostic-filter.ron b/naga/tests/out/ir/wgsl-diagnostic-filter.ron index 10f533f10..c5746696d 100644 --- a/naga/tests/out/ir/wgsl-diagnostic-filter.ron +++ b/naga/tests/out/ir/wgsl-diagnostic-filter.ron @@ -5,6 +5,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-index-by-value.compact.ron b/naga/tests/out/ir/wgsl-index-by-value.compact.ron index 31a601054..a4f84a7a6 100644 --- a/naga/tests/out/ir/wgsl-index-by-value.compact.ron +++ b/naga/tests/out/ir/wgsl-index-by-value.compact.ron @@ -82,6 +82,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-index-by-value.ron b/naga/tests/out/ir/wgsl-index-by-value.ron index 31a601054..a4f84a7a6 100644 --- a/naga/tests/out/ir/wgsl-index-by-value.ron +++ b/naga/tests/out/ir/wgsl-index-by-value.ron @@ -82,6 +82,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-local-const.compact.ron b/naga/tests/out/ir/wgsl-local-const.compact.ron index b7deb55ac..512972657 100644 --- a/naga/tests/out/ir/wgsl-local-const.compact.ron +++ b/naga/tests/out/ir/wgsl-local-const.compact.ron @@ -27,6 +27,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/wgsl-local-const.ron b/naga/tests/out/ir/wgsl-local-const.ron index b7deb55ac..512972657 100644 --- a/naga/tests/out/ir/wgsl-local-const.ron +++ b/naga/tests/out/ir/wgsl-local-const.ron @@ -27,6 +27,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/wgsl-must-use.compact.ron b/naga/tests/out/ir/wgsl-must-use.compact.ron index 4d148b906..a701a6805 100644 --- a/naga/tests/out/ir/wgsl-must-use.compact.ron +++ b/naga/tests/out/ir/wgsl-must-use.compact.ron @@ -13,6 +13,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-must-use.ron b/naga/tests/out/ir/wgsl-must-use.ron index 4d148b906..a701a6805 100644 --- a/naga/tests/out/ir/wgsl-must-use.ron +++ b/naga/tests/out/ir/wgsl-must-use.ron @@ -13,6 +13,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-overrides-atomicCompareExchangeWeak.compact.ron b/naga/tests/out/ir/wgsl-overrides-atomicCompareExchangeWeak.compact.ron index 1e568ebbc..640ee25ca 100644 --- a/naga/tests/out/ir/wgsl-overrides-atomicCompareExchangeWeak.compact.ron +++ b/naga/tests/out/ir/wgsl-overrides-atomicCompareExchangeWeak.compact.ron @@ -54,6 +54,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: { AtomicCompareExchangeWeakResult(( kind: Uint, diff --git a/naga/tests/out/ir/wgsl-overrides-atomicCompareExchangeWeak.ron b/naga/tests/out/ir/wgsl-overrides-atomicCompareExchangeWeak.ron index 1e568ebbc..640ee25ca 100644 --- a/naga/tests/out/ir/wgsl-overrides-atomicCompareExchangeWeak.ron +++ b/naga/tests/out/ir/wgsl-overrides-atomicCompareExchangeWeak.ron @@ -54,6 +54,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: { AtomicCompareExchangeWeakResult(( kind: Uint, diff --git a/naga/tests/out/ir/wgsl-overrides-ray-query.compact.ron b/naga/tests/out/ir/wgsl-overrides-ray-query.compact.ron index 649ba28d4..f65e8f186 100644 --- a/naga/tests/out/ir/wgsl-overrides-ray-query.compact.ron +++ b/naga/tests/out/ir/wgsl-overrides-ray-query.compact.ron @@ -86,6 +86,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-overrides-ray-query.ron b/naga/tests/out/ir/wgsl-overrides-ray-query.ron index 649ba28d4..f65e8f186 100644 --- a/naga/tests/out/ir/wgsl-overrides-ray-query.ron +++ b/naga/tests/out/ir/wgsl-overrides-ray-query.ron @@ -86,6 +86,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-overrides.compact.ron b/naga/tests/out/ir/wgsl-overrides.compact.ron index eca515610..81221ff79 100644 --- a/naga/tests/out/ir/wgsl-overrides.compact.ron +++ b/naga/tests/out/ir/wgsl-overrides.compact.ron @@ -27,6 +27,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-overrides.ron b/naga/tests/out/ir/wgsl-overrides.ron index eca515610..81221ff79 100644 --- a/naga/tests/out/ir/wgsl-overrides.ron +++ b/naga/tests/out/ir/wgsl-overrides.ron @@ -27,6 +27,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-storage-textures.compact.ron b/naga/tests/out/ir/wgsl-storage-textures.compact.ron index eb70e3bad..ec63fecac 100644 --- a/naga/tests/out/ir/wgsl-storage-textures.compact.ron +++ b/naga/tests/out/ir/wgsl-storage-textures.compact.ron @@ -72,6 +72,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-storage-textures.ron b/naga/tests/out/ir/wgsl-storage-textures.ron index eb70e3bad..ec63fecac 100644 --- a/naga/tests/out/ir/wgsl-storage-textures.ron +++ b/naga/tests/out/ir/wgsl-storage-textures.ron @@ -72,6 +72,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-template-list-trailing-comma.compact.ron b/naga/tests/out/ir/wgsl-template-list-trailing-comma.compact.ron index bfcd83f7f..a8208c09b 100644 --- a/naga/tests/out/ir/wgsl-template-list-trailing-comma.compact.ron +++ b/naga/tests/out/ir/wgsl-template-list-trailing-comma.compact.ron @@ -29,6 +29,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-template-list-trailing-comma.ron b/naga/tests/out/ir/wgsl-template-list-trailing-comma.ron index bfcd83f7f..a8208c09b 100644 --- a/naga/tests/out/ir/wgsl-template-list-trailing-comma.ron +++ b/naga/tests/out/ir/wgsl-template-list-trailing-comma.ron @@ -29,6 +29,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [], diff --git a/naga/tests/out/ir/wgsl-texture-external.compact.ron b/naga/tests/out/ir/wgsl-texture-external.compact.ron index 2bceb18a5..dbffbddcd 100644 --- a/naga/tests/out/ir/wgsl-texture-external.compact.ron +++ b/naga/tests/out/ir/wgsl-texture-external.compact.ron @@ -1,5 +1,12 @@ ( types: [ + ( + name: None, + inner: Scalar(( + kind: Float, + width: 4, + )), + ), ( name: None, inner: Scalar(( @@ -28,6 +35,17 @@ ), ), ), + ( + name: None, + inner: Matrix( + columns: Tri, + rows: Tri, + scalar: ( + kind: Float, + width: 4, + ), + ), + ), ( name: None, inner: Matrix( @@ -39,42 +57,92 @@ ), ), ), + ( + name: Some("NagaExternalTextureTransferFn"), + inner: Struct( + members: [ + ( + name: Some("a"), + ty: 0, + binding: None, + offset: 0, + ), + ( + name: Some("b"), + ty: 0, + binding: None, + offset: 4, + ), + ( + name: Some("g"), + ty: 0, + binding: None, + offset: 8, + ), + ( + name: Some("k"), + ty: 0, + binding: None, + offset: 12, + ), + ], + span: 16, + ), + ), ( name: Some("NagaExternalTextureParams"), inner: Struct( members: [ ( name: Some("yuv_conversion_matrix"), - ty: 3, + ty: 5, binding: None, offset: 0, ), ( - name: Some("sample_transform"), - ty: 2, + name: Some("gamut_conversion_matrix"), + ty: 4, binding: None, offset: 64, ), ( - name: Some("load_transform"), - ty: 2, - binding: None, - offset: 88, - ), - ( - name: Some("size"), - ty: 1, + name: Some("src_tf"), + ty: 6, binding: None, offset: 112, ), ( - name: Some("num_planes"), - ty: 0, + name: Some("dst_tf"), + ty: 6, binding: None, - offset: 120, + offset: 128, + ), + ( + name: Some("sample_transform"), + ty: 3, + binding: None, + offset: 144, + ), + ( + name: Some("load_transform"), + ty: 3, + binding: None, + offset: 168, + ), + ( + name: Some("size"), + ty: 2, + binding: None, + offset: 192, + ), + ( + name: Some("num_planes"), + ty: 1, + binding: None, + offset: 200, ), ], - span: 128, + span: 208, ), ), ( @@ -106,7 +174,8 @@ ray_desc: None, ray_intersection: None, ray_vertex_return: None, - external_texture_params: Some(4), + external_texture_params: Some(7), + external_texture_transfer_function: Some(6), predeclared_types: {}, ), constants: [], @@ -119,7 +188,7 @@ group: 0, binding: 0, )), - ty: 5, + ty: 8, init: None, ), ( @@ -129,7 +198,7 @@ group: 0, binding: 1, )), - ty: 6, + ty: 9, init: None, ), ], @@ -140,28 +209,28 @@ arguments: [ ( name: Some("t"), - ty: 5, + ty: 8, binding: None, ), ], result: Some(( - ty: 7, + ty: 10, binding: None, )), local_variables: [ ( name: Some("a"), - ty: 7, + ty: 10, init: None, ), ( name: Some("b"), - ty: 7, + ty: 10, init: None, ), ( name: Some("c"), - ty: 1, + ty: 2, init: None, ), ], @@ -285,7 +354,7 @@ name: Some("fragment_main"), arguments: [], result: Some(( - ty: 7, + ty: 10, binding: Some(Location( location: 0, interpolation: Some(Perspective), @@ -324,7 +393,7 @@ name: Some("vertex_main"), arguments: [], result: Some(( - ty: 7, + ty: 10, binding: Some(BuiltIn(Position( invariant: false, ))), diff --git a/naga/tests/out/ir/wgsl-texture-external.ron b/naga/tests/out/ir/wgsl-texture-external.ron index 2bceb18a5..dbffbddcd 100644 --- a/naga/tests/out/ir/wgsl-texture-external.ron +++ b/naga/tests/out/ir/wgsl-texture-external.ron @@ -1,5 +1,12 @@ ( types: [ + ( + name: None, + inner: Scalar(( + kind: Float, + width: 4, + )), + ), ( name: None, inner: Scalar(( @@ -28,6 +35,17 @@ ), ), ), + ( + name: None, + inner: Matrix( + columns: Tri, + rows: Tri, + scalar: ( + kind: Float, + width: 4, + ), + ), + ), ( name: None, inner: Matrix( @@ -39,42 +57,92 @@ ), ), ), + ( + name: Some("NagaExternalTextureTransferFn"), + inner: Struct( + members: [ + ( + name: Some("a"), + ty: 0, + binding: None, + offset: 0, + ), + ( + name: Some("b"), + ty: 0, + binding: None, + offset: 4, + ), + ( + name: Some("g"), + ty: 0, + binding: None, + offset: 8, + ), + ( + name: Some("k"), + ty: 0, + binding: None, + offset: 12, + ), + ], + span: 16, + ), + ), ( name: Some("NagaExternalTextureParams"), inner: Struct( members: [ ( name: Some("yuv_conversion_matrix"), - ty: 3, + ty: 5, binding: None, offset: 0, ), ( - name: Some("sample_transform"), - ty: 2, + name: Some("gamut_conversion_matrix"), + ty: 4, binding: None, offset: 64, ), ( - name: Some("load_transform"), - ty: 2, - binding: None, - offset: 88, - ), - ( - name: Some("size"), - ty: 1, + name: Some("src_tf"), + ty: 6, binding: None, offset: 112, ), ( - name: Some("num_planes"), - ty: 0, + name: Some("dst_tf"), + ty: 6, binding: None, - offset: 120, + offset: 128, + ), + ( + name: Some("sample_transform"), + ty: 3, + binding: None, + offset: 144, + ), + ( + name: Some("load_transform"), + ty: 3, + binding: None, + offset: 168, + ), + ( + name: Some("size"), + ty: 2, + binding: None, + offset: 192, + ), + ( + name: Some("num_planes"), + ty: 1, + binding: None, + offset: 200, ), ], - span: 128, + span: 208, ), ), ( @@ -106,7 +174,8 @@ ray_desc: None, ray_intersection: None, ray_vertex_return: None, - external_texture_params: Some(4), + external_texture_params: Some(7), + external_texture_transfer_function: Some(6), predeclared_types: {}, ), constants: [], @@ -119,7 +188,7 @@ group: 0, binding: 0, )), - ty: 5, + ty: 8, init: None, ), ( @@ -129,7 +198,7 @@ group: 0, binding: 1, )), - ty: 6, + ty: 9, init: None, ), ], @@ -140,28 +209,28 @@ arguments: [ ( name: Some("t"), - ty: 5, + ty: 8, binding: None, ), ], result: Some(( - ty: 7, + ty: 10, binding: None, )), local_variables: [ ( name: Some("a"), - ty: 7, + ty: 10, init: None, ), ( name: Some("b"), - ty: 7, + ty: 10, init: None, ), ( name: Some("c"), - ty: 1, + ty: 2, init: None, ), ], @@ -285,7 +354,7 @@ name: Some("fragment_main"), arguments: [], result: Some(( - ty: 7, + ty: 10, binding: Some(Location( location: 0, interpolation: Some(Perspective), @@ -324,7 +393,7 @@ name: Some("vertex_main"), arguments: [], result: Some(( - ty: 7, + ty: 10, binding: Some(BuiltIn(Position( invariant: false, ))), diff --git a/naga/tests/out/ir/wgsl-types_with_comments.compact.ron b/naga/tests/out/ir/wgsl-types_with_comments.compact.ron index 1139fab19..7186209f0 100644 --- a/naga/tests/out/ir/wgsl-types_with_comments.compact.ron +++ b/naga/tests/out/ir/wgsl-types_with_comments.compact.ron @@ -38,6 +38,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/naga/tests/out/ir/wgsl-types_with_comments.ron b/naga/tests/out/ir/wgsl-types_with_comments.ron index a1761c17c..480b0d233 100644 --- a/naga/tests/out/ir/wgsl-types_with_comments.ron +++ b/naga/tests/out/ir/wgsl-types_with_comments.ron @@ -63,6 +63,7 @@ ray_intersection: None, ray_vertex_return: None, external_texture_params: None, + external_texture_transfer_function: None, predeclared_types: {}, ), constants: [ diff --git a/tests/tests/wgpu-validation/api/external_texture.rs b/tests/tests/wgpu-validation/api/external_texture.rs index b3dcffb93..989fe5ac8 100644 --- a/tests/tests/wgpu-validation/api/external_texture.rs +++ b/tests/tests/wgpu-validation/api/external_texture.rs @@ -49,6 +49,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -63,6 +66,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -77,6 +83,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -95,6 +104,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -113,6 +125,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -131,6 +146,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -151,6 +169,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -169,6 +190,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -187,6 +211,9 @@ fn create_external_texture() { width: r_texture.width(), height: r_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -212,6 +239,9 @@ fn create_external_texture() { width: uint_texture.width(), height: uint_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -237,6 +267,9 @@ fn create_external_texture() { width: d3_texture.width(), height: d3_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -263,6 +296,9 @@ fn create_external_texture() { width: multisampled_texture.width(), height: multisampled_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -288,6 +324,9 @@ fn create_external_texture() { width: non_binding_texture.width(), height: non_binding_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, @@ -339,6 +378,9 @@ fn external_texture_binding() { height: texture_descriptor.size.height, format: ExternalTextureFormat::Rgba, yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }; @@ -568,6 +610,9 @@ fn destroyed_external_texture_plane() { width: plane_texture.width(), height: plane_texture.height(), yuv_conversion_matrix: [0.0; 16], + gamut_conversion_matrix: [0.0; 9], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), sample_transform: [0.0; 6], load_transform: [0.0; 6], }, diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 68a425c05..b55676ea5 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -76,8 +76,12 @@ pub(crate) struct CommandIndices { pub(crate) next_acceleration_structure_build_command_index: u64, } -/// Parameters provided to shaders via a uniform buffer, describing a -/// [`binding_model::BindingResource::ExternalTexture`] resource binding. +/// Parameters provided to shaders via a uniform buffer of the type +/// [`NagaExternalTextureParams`], describing an [`ExternalTexture`] resource +/// binding. +/// +/// [`NagaExternalTextureParams`]: naga::SpecialTypes::external_texture_params +/// [`ExternalTexture`]: binding_model::BindingResource::ExternalTexture #[repr(C)] #[derive(Copy, Clone, bytemuck::Zeroable, bytemuck::Pod)] pub struct ExternalTextureParams { @@ -87,6 +91,29 @@ pub struct ExternalTextureParams { /// This is ignored when `num_planes` is 1. pub yuv_conversion_matrix: [f32; 16], + /// 3x3 column-major matrix to transform linear RGB values in the source + /// color space to linear RGB values in the destination color space. In + /// combination with [`Self::src_transfer_function`] and + /// [`Self::dst_transfer_function`] this can be used to ensure that + /// [`ImageSample`] and [`ImageLoad`] operations return values in the + /// desired destination color space rather than the source color space of + /// the underlying planes. + /// + /// Includes a padding element after each column. + /// + /// [`ImageSample`]: naga::ir::Expression::ImageSample + /// [`ImageLoad`]: naga::ir::Expression::ImageLoad + pub gamut_conversion_matrix: [f32; 12], + + /// Transfer function for the source color space. The *inverse* of this + /// will be applied to decode non-linear RGB to linear RGB in the source + /// color space. + pub src_transfer_function: wgt::ExternalTextureTransferFunction, + + /// Transfer function for the destination color space. This will be applied + /// to encode linear RGB to non-linear RGB in the destination color space. + pub dst_transfer_function: wgt::ExternalTextureTransferFunction, + /// Transform to apply to [`ImageSample`] coordinates. /// /// This is a 3x2 column-major matrix representing an affine transform from @@ -140,8 +167,26 @@ pub struct ExternalTextureParams { impl ExternalTextureParams { pub fn from_desc(desc: &wgt::ExternalTextureDescriptor) -> Self { + let gamut_conversion_matrix = [ + desc.gamut_conversion_matrix[0], + desc.gamut_conversion_matrix[1], + desc.gamut_conversion_matrix[2], + 0.0, // padding + desc.gamut_conversion_matrix[3], + desc.gamut_conversion_matrix[4], + desc.gamut_conversion_matrix[5], + 0.0, // padding + desc.gamut_conversion_matrix[6], + desc.gamut_conversion_matrix[7], + desc.gamut_conversion_matrix[8], + 0.0, // padding + ]; + Self { yuv_conversion_matrix: desc.yuv_conversion_matrix, + gamut_conversion_matrix, + src_transfer_function: desc.src_transfer_function, + dst_transfer_function: desc.dst_transfer_function, size: [desc.width, desc.height], sample_transform: desc.sample_transform, load_transform: desc.load_transform, @@ -445,6 +490,14 @@ impl Device { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, ], + #[rustfmt::skip] + gamut_conversion_matrix: [ + 1.0, 0.0, 0.0, /* padding */ 0.0, + 0.0, 1.0, 0.0, /* padding */ 0.0, + 0.0, 0.0, 1.0, /* padding */ 0.0, + ], + src_transfer_function: Default::default(), + dst_transfer_function: Default::default(), size: [0, 0], #[rustfmt::skip] sample_transform: [ diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 10ec85121..2e21cb904 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -6285,6 +6285,31 @@ pub enum ExternalTextureFormat { Yu12, } +/// Parameters describing a gamma encoding transfer function in the form +/// tf = { k * linear | linear < b +/// { a * pow(linear, 1/g) - (a-1) | linear >= b +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq, bytemuck::Zeroable, bytemuck::Pod)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[allow(missing_docs)] +pub struct ExternalTextureTransferFunction { + pub a: f32, + pub b: f32, + pub g: f32, + pub k: f32, +} + +impl Default for ExternalTextureTransferFunction { + fn default() -> Self { + Self { + a: 1.0, + b: 1.0, + g: 1.0, + k: 1.0, + } + } +} + /// Describes an [`ExternalTexture`](../wgpu/struct.ExternalTexture.html). /// /// Note that [`width`] and [`height`] are the values that should be returned by @@ -6325,6 +6350,27 @@ pub struct ExternalTextureDescriptor { /// This is ignored when `format` is [`ExternalTextureFormat::Rgba`]. pub yuv_conversion_matrix: [f32; 16], + /// 3x3 column-major matrix to transform linear RGB values in the source + /// color space to linear RGB values in the destination color space. In + /// combination with [`Self::src_transfer_function`] and + /// [`Self::dst_transfer_function`] this can be used to ensure that + /// [`ImageSample`] and [`ImageLoad`] operations return values in the + /// desired destination color space rather than the source color space of + /// the underlying planes. + /// + /// [`ImageSample`]: https://docs.rs/naga/latest/naga/ir/enum.Expression.html#variant.ImageSample + /// [`ImageLoad`]: https://docs.rs/naga/latest/naga/ir/enum.Expression.html#variant.ImageLoad + pub gamut_conversion_matrix: [f32; 9], + + /// Transfer function for the source color space. The *inverse* of this + /// will be applied to decode non-linear RGB to linear RGB in the source + /// color space. + pub src_transfer_function: ExternalTextureTransferFunction, + + /// Transfer function for the destination color space. This will be applied + /// to encode linear RGB to non-linear RGB in the destination color space. + pub dst_transfer_function: ExternalTextureTransferFunction, + /// Transform to apply to [`ImageSample`] coordinates. /// /// This is a 3x2 column-major matrix representing an affine transform from @@ -6370,6 +6416,9 @@ impl ExternalTextureDescriptor { yuv_conversion_matrix: self.yuv_conversion_matrix, sample_transform: self.sample_transform, load_transform: self.load_transform, + gamut_conversion_matrix: self.gamut_conversion_matrix, + src_transfer_function: self.src_transfer_function, + dst_transfer_function: self.dst_transfer_function, } } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 893d8101b..dcfc19338 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -91,20 +91,21 @@ pub use wgt::{ CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, CopyExternalImageDestInfo, CoreCounters, DepthBiasState, DepthStencilState, DeviceLostReason, DeviceType, DownlevelCapabilities, DownlevelFlags, DownlevelLimits, Dx12BackendOptions, Dx12Compiler, - DxcShaderModel, DynamicOffset, Extent3d, ExternalTextureFormat, Face, Features, FeaturesWGPU, - FeaturesWebGPU, FilterMode, FrontFace, GlBackendOptions, GlFenceBehavior, Gles3MinorVersion, - HalCounters, ImageSubresourceRange, IndexFormat, InstanceDescriptor, InstanceFlags, - InternalCounters, Limits, MemoryBudgetThresholds, MemoryHints, MultisampleState, - NoopBackendOptions, Origin2d, Origin3d, PipelineStatisticsTypes, PollError, PollStatus, - PolygonMode, PowerPreference, PredefinedColorSpace, PresentMode, PresentationTimestamp, - PrimitiveState, PrimitiveTopology, PushConstantRange, QueryType, RenderBundleDepthStencil, - RequestAdapterError, SamplerBindingType, SamplerBorderColor, ShaderLocation, ShaderModel, - ShaderRuntimeChecks, ShaderStages, StencilFaceState, StencilOperation, StencilState, - StorageTextureAccess, SurfaceCapabilities, SurfaceStatus, TexelCopyBufferLayout, TextureAspect, - TextureDimension, TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, - TextureSampleType, TextureTransition, TextureUsages, TextureUses, TextureViewDimension, Trace, - VertexAttribute, VertexFormat, VertexStepMode, WasmNotSend, WasmNotSendSync, WasmNotSync, - COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT, + DxcShaderModel, DynamicOffset, Extent3d, ExternalTextureFormat, + ExternalTextureTransferFunction, Face, Features, FeaturesWGPU, FeaturesWebGPU, FilterMode, + FrontFace, GlBackendOptions, GlFenceBehavior, Gles3MinorVersion, HalCounters, + ImageSubresourceRange, IndexFormat, InstanceDescriptor, InstanceFlags, InternalCounters, + Limits, MemoryBudgetThresholds, MemoryHints, MultisampleState, NoopBackendOptions, Origin2d, + Origin3d, PipelineStatisticsTypes, PollError, PollStatus, PolygonMode, PowerPreference, + PredefinedColorSpace, PresentMode, PresentationTimestamp, PrimitiveState, PrimitiveTopology, + PushConstantRange, QueryType, RenderBundleDepthStencil, RequestAdapterError, + SamplerBindingType, SamplerBorderColor, ShaderLocation, ShaderModel, ShaderRuntimeChecks, + ShaderStages, StencilFaceState, StencilOperation, StencilState, StorageTextureAccess, + SurfaceCapabilities, SurfaceStatus, TexelCopyBufferLayout, TextureAspect, TextureDimension, + TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType, + TextureTransition, TextureUsages, TextureUses, TextureViewDimension, Trace, VertexAttribute, + VertexFormat, VertexStepMode, WasmNotSend, WasmNotSendSync, WasmNotSync, COPY_BUFFER_ALIGNMENT, + COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT, QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_ALIGNMENT, };