From bac09ad2a33ee8d42ab1057bbc2e014f02691bf0 Mon Sep 17 00:00:00 2001 From: chyyran Date: Thu, 26 Sep 2024 03:21:14 -0400 Subject: [PATCH] reflect: allow validation of shaders without reflecting against semantics --- librashader-reflect/src/back/mod.rs | 11 ++++++ librashader-reflect/src/back/spirv.rs | 4 +++ librashader-reflect/src/reflect/cross/mod.rs | 21 ++++++++++-- librashader-reflect/src/reflect/mod.rs | 3 ++ librashader-reflect/src/reflect/naga/mod.rs | 36 ++++++++++++++++++-- librashader-reflect/src/reflect/presets.rs | 7 ++-- 6 files changed, 74 insertions(+), 8 deletions(-) diff --git a/librashader-reflect/src/back/mod.rs b/librashader-reflect/src/back/mod.rs index f41604d..d5f6b46 100644 --- a/librashader-reflect/src/back/mod.rs +++ b/librashader-reflect/src/back/mod.rs @@ -32,6 +32,9 @@ pub trait CompileShader { type Context; /// Consume the object and return the compiled output of the shader. + /// + /// The shader should either be reflected or validated as + /// [ReflectShader] before being compiled, or the results may not be valid. fn compile( self, options: Self::Options, @@ -139,6 +142,10 @@ where ) -> Result { self.backend.reflect(pass_number, semantics) } + + fn validate(&mut self) -> Result<(), ShaderReflectError> { + self.backend.validate() + } } impl ReflectShader for Box { @@ -149,6 +156,10 @@ impl ReflectShader for Box { ) -> Result { (**self).reflect(pass_number, semantics) } + + fn validate(&mut self) -> Result<(), ShaderReflectError> { + (**self).validate() + } } impl CompileShader for Box diff --git a/librashader-reflect/src/back/spirv.rs b/librashader-reflect/src/back/spirv.rs index d5f0f7c..79a955f 100644 --- a/librashader-reflect/src/back/spirv.rs +++ b/librashader-reflect/src/back/spirv.rs @@ -72,6 +72,10 @@ impl ReflectShader for WriteSpirV { ) -> Result { self.reflect.reflect(pass_number, semantics) } + + fn validate(&mut self) -> Result<(), ShaderReflectError> { + self.reflect.validate() + } } impl CompileShader for WriteSpirV { diff --git a/librashader-reflect/src/reflect/cross/mod.rs b/librashader-reflect/src/reflect/cross/mod.rs index 8f4ef4a..6c1e2d8 100644 --- a/librashader-reflect/src/reflect/cross/mod.rs +++ b/librashader-reflect/src/reflect/cross/mod.rs @@ -160,7 +160,7 @@ impl CrossReflect where T: spirv_cross2::compile::CompilableTarget, { - fn validate( + fn validate_semantics( &self, vertex_res: &AllResources, fragment_res: &AllResources, @@ -714,7 +714,7 @@ where ) -> Result { let vertex_res = self.vertex.shader_resources()?.all_resources()?; let fragment_res = self.fragment.shader_resources()?.all_resources()?; - self.validate(&vertex_res, &fragment_res)?; + self.validate_semantics(&vertex_res, &fragment_res)?; let vertex_ubo = vertex_res.uniform_buffers.first(); let fragment_ubo = fragment_res.uniform_buffers.first(); @@ -797,6 +797,23 @@ where meta, }) } + + fn validate(&mut self) -> Result<(), ShaderReflectError> { + let vertex_res = self.vertex.shader_resources()?.all_resources()?; + let fragment_res = self.fragment.shader_resources()?.all_resources()?; + self.validate_semantics(&vertex_res, &fragment_res)?; + let vertex_ubo = vertex_res.uniform_buffers.first(); + let fragment_ubo = fragment_res.uniform_buffers.first(); + + self.reflect_ubos(vertex_ubo, fragment_ubo)?; + + let vertex_push = vertex_res.push_constant_buffers.first(); + let fragment_push = fragment_res.push_constant_buffers.first(); + + self.reflect_push_constant_buffer(vertex_push, fragment_push)?; + + Ok(()) + } } #[cfg(test)] diff --git a/librashader-reflect/src/reflect/mod.rs b/librashader-reflect/src/reflect/mod.rs index 9960a3a..611f606 100644 --- a/librashader-reflect/src/reflect/mod.rs +++ b/librashader-reflect/src/reflect/mod.rs @@ -25,6 +25,9 @@ pub trait ReflectShader { pass_number: usize, semantics: &ShaderSemantics, ) -> Result; + + /// Validate the shader without doing reflection against a set of semantics. + fn validate(&mut self) -> Result<(), ShaderReflectError>; } pub use semantics::ShaderReflection; diff --git a/librashader-reflect/src/reflect/naga/mod.rs b/librashader-reflect/src/reflect/naga/mod.rs index cdd1ca3..6901e78 100644 --- a/librashader-reflect/src/reflect/naga/mod.rs +++ b/librashader-reflect/src/reflect/naga/mod.rs @@ -239,7 +239,7 @@ impl ValidateTypeSemantics<&TypeInner> for TextureSemantics { impl NagaReflect { fn reflect_ubos( - &mut self, + &self, vertex_ubo: Option>, fragment_ubo: Option>, ) -> Result>, ShaderReflectError> { @@ -429,7 +429,7 @@ impl NagaReflect { } } - fn validate(&self) -> Result<(), ShaderReflectError> { + fn validate_semantics(&self) -> Result<(), ShaderReflectError> { // Verify types if self.vertex.global_variables.iter().any(|(_, gv)| { let ty = &self.vertex.types[gv.ty]; @@ -882,7 +882,7 @@ impl ReflectShader for NagaReflect { pass_number: usize, semantics: &ShaderSemantics, ) -> Result { - self.validate()?; + self.validate_semantics()?; // Validate verifies that there's only one uniform block. let vertex_ubo = self @@ -1012,6 +1012,36 @@ impl ReflectShader for NagaReflect { meta, }) } + + fn validate(&mut self) -> Result<(), ShaderReflectError> { + self.validate_semantics()?; + let vertex_push = self + .vertex + .global_variables + .iter() + .find_map(|(handle, gv)| { + if gv.space == AddressSpace::PushConstant { + Some(handle) + } else { + None + } + }); + + let fragment_push = self + .fragment + .global_variables + .iter() + .find_map(|(handle, gv)| { + if gv.space == AddressSpace::PushConstant { + Some(handle) + } else { + None + } + }); + + self.reflect_push_constant_buffer(vertex_push, fragment_push)?; + Ok(()) + } } #[cfg(test)] diff --git a/librashader-reflect/src/reflect/presets.rs b/librashader-reflect/src/reflect/presets.rs index 65b523a..eee1a56 100644 --- a/librashader-reflect/src/reflect/presets.rs +++ b/librashader-reflect/src/reflect/presets.rs @@ -219,7 +219,10 @@ impl ShaderSemantics { /// Create pass semantics for a single pass in the given shader preset. /// /// This is meant as a convenience function for reflection use only. - pub fn create_pass_semantics(preset: &ShaderPreset, index: usize) -> Result + pub fn create_pass_semantics( + preset: &ShaderPreset, + index: usize, + ) -> Result where E: From, E: From, @@ -268,6 +271,4 @@ impl ShaderSemantics { texture_semantics, }) } - } -