From e28344edbb87cae7d6596d69838cca9fa3dd57e7 Mon Sep 17 00:00:00 2001 From: Gordon-F Date: Thu, 24 Jun 2021 13:59:35 +0300 Subject: [PATCH] [hlsl-out] Return entry points name to users --- cli/src/main.rs | 7 +++-- src/back/hlsl/mod.rs | 44 +++++++++++++++------------- src/back/hlsl/writer.rs | 42 ++++++++++++++++---------- tests/in/quad.wgsl | 7 +++++ tests/out/hlsl/empty.hlsl | 2 +- tests/out/hlsl/empty.hlsl.config | 2 +- tests/out/hlsl/quad-vert.hlsl | 8 ++--- tests/out/hlsl/quad-vert.hlsl.config | 2 +- tests/out/hlsl/quad.hlsl | 12 ++++---- tests/out/hlsl/quad.hlsl.config | 4 +-- tests/snapshots.rs | 24 ++++++++------- 11 files changed, 92 insertions(+), 62 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index afc1d6f04..0a2c22b89 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -304,9 +304,12 @@ fn main() { } "hlsl" => { use naga::back::hlsl; - let hlsl = hlsl::write_string(&module, info.as_ref().unwrap(), ¶ms.hlsl) + let mut buffer = String::new(); + let mut writer = hlsl::Writer::new(&mut buffer, ¶ms.hlsl); + writer + .write(&module, info.as_ref().unwrap()) .unwrap_pretty(); - fs::write(output_path, hlsl).unwrap(); + fs::write(output_path, buffer).unwrap(); } "wgsl" => { use naga::back::wgsl; diff --git a/src/back/hlsl/mod.rs b/src/back/hlsl/mod.rs index f42f5e01d..0631952c6 100644 --- a/src/back/hlsl/mod.rs +++ b/src/back/hlsl/mod.rs @@ -15,30 +15,45 @@ pub enum ShaderModel { V6_0, } +impl ShaderModel { + pub fn to_profile_string(self, stage: crate::ShaderStage) -> String { + let stage_prefix = match stage { + crate::ShaderStage::Vertex => "vs_", + crate::ShaderStage::Fragment => "ps_", + crate::ShaderStage::Compute => "cs_", + }; + + let version = match self { + Self::V5_0 => "5_0", + Self::V5_1 => "5_1", + Self::V6_0 => "6_0", + }; + + format!("{}{}", stage_prefix, version) + } +} + /// Structure that contains the configuration used in the [`Writer`](Writer) #[derive(Debug, Clone)] pub struct Options { /// The hlsl shader model to be used pub shader_model: ShaderModel, - /// The vertex entry point name in generated shader - pub vertex_entry_point_name: String, - /// The fragment entry point name in generated shader - pub fragment_entry_point_name: String, - /// The comput entry point name in generated shader - pub compute_entry_point_name: String, } impl Default for Options { fn default() -> Self { Options { shader_model: ShaderModel::V5_0, - vertex_entry_point_name: String::from("vert_main"), - fragment_entry_point_name: String::from("frag_main"), - compute_entry_point_name: String::from("comp_main"), } } } +pub struct ReflectionInfo { + /// Information about all entry points (stage, name). + pub entry_points: Vec<(crate::ShaderStage, String)>, + // TODO: locations +} + #[derive(Error, Debug)] pub enum Error { #[error(transparent)] @@ -50,14 +65,3 @@ pub enum Error { #[error("{0}")] Custom(String), } - -pub fn write_string( - module: &crate::Module, - info: &crate::valid::ModuleInfo, - options: &Options, -) -> Result { - let mut w = Writer::new(String::new(), options); - w.write(module, info)?; - let output = w.finish(); - Ok(output) -} diff --git a/src/back/hlsl/writer.rs b/src/back/hlsl/writer.rs index e46ae1bc2..4c27dccfa 100644 --- a/src/back/hlsl/writer.rs +++ b/src/back/hlsl/writer.rs @@ -13,9 +13,14 @@ const LOCATION_SEMANTIC: &str = "LOC"; /// Shorthand result used internally by the backend type BackendResult = Result<(), Error>; +/// Structure contains information required for generating +/// wrapped structure of all entry points arguments struct EntryPointBinding { + /// Associated shader stage stage: ShaderStage, + /// Generated structure name name: String, + /// Members of generated structure members: Vec, } @@ -29,8 +34,11 @@ pub struct Writer<'a, W> { out: W, names: crate::FastHashMap, namer: proc::Namer, + /// HLSL backend options options: &'a Options, + /// Information about entry point arguments wrapped into structure ep_inputs: Vec>, + /// Set of expressions that have associated temporary variables named_expressions: crate::NamedExpressions, } @@ -54,7 +62,11 @@ impl<'a, W: Write> Writer<'a, W> { self.ep_inputs.clear(); } - pub fn write(&mut self, module: &Module, info: &valid::ModuleInfo) -> BackendResult { + pub fn write( + &mut self, + module: &Module, + info: &valid::ModuleInfo, + ) -> Result { self.reset(module); // Write all constants @@ -102,7 +114,7 @@ impl<'a, W: Write> Writer<'a, W> { // Write all entry points wrapped structs for (index, ep) in module.entry_points.iter().enumerate() { - self.write_ep_input_struct(module, &ep.function, ep.stage, index)?; + self.write_ep_input_struct(module, &ep.function, ep.stage, &ep.name, index)?; } // Write all regular functions @@ -121,6 +133,8 @@ impl<'a, W: Write> Writer<'a, W> { writeln!(self.out)?; } + let mut entry_points_info = Vec::with_capacity(module.entry_points.len()); + // Write all entry points for (index, ep) in module.entry_points.iter().enumerate() { let ctx = back::FunctionCtx { @@ -140,20 +154,20 @@ impl<'a, W: Write> Writer<'a, W> { )?; } - let name = match ep.stage { - ShaderStage::Vertex => &self.options.vertex_entry_point_name, - ShaderStage::Fragment => &self.options.fragment_entry_point_name, - ShaderStage::Compute => &self.options.compute_entry_point_name, - }; + let name = self.names[&NameKey::EntryPoint(index as u16)].clone(); - self.write_function(module, name, &ep.function, &ctx)?; + self.write_function(module, &name, &ep.function, &ctx)?; if index < module.entry_points.len() - 1 { writeln!(self.out)?; } + + entry_points_info.push((ep.stage, name)) } - Ok(()) + Ok(super::ReflectionInfo { + entry_points: entry_points_info, + }) } fn write_binding(&mut self, binding: &crate::Binding) -> BackendResult { @@ -174,14 +188,16 @@ impl<'a, W: Write> Writer<'a, W> { module: &Module, func: &crate::Function, stage: ShaderStage, + entry_point_name: &str, index: usize, ) -> BackendResult { if !func.arguments.is_empty() { - let struct_name = self.namer.call_unique(match stage { + let struct_name_prefix = match stage { ShaderStage::Vertex => "VertexInput", ShaderStage::Fragment => "FragmentInput", ShaderStage::Compute => "ComputeInput", - }); + }; + let struct_name = format!("{}_{}", struct_name_prefix, entry_point_name); let mut members = Vec::with_capacity(func.arguments.len()); @@ -1058,10 +1074,6 @@ impl<'a, W: Write> Writer<'a, W> { Ok(()) } - - pub fn finish(self) -> W { - self.out - } } fn image_dimension_str(dim: crate::ImageDimension) -> &'static str { diff --git a/tests/in/quad.wgsl b/tests/in/quad.wgsl index df1786361..ca1655400 100644 --- a/tests/in/quad.wgsl +++ b/tests/in/quad.wgsl @@ -29,3 +29,10 @@ fn main([[location(0)]] uv : vec2) -> [[location(0)]] vec4 { let premultiplied = color.a * color; return premultiplied; } + + +// We need to make sure that backends are successfully handling multiple entry points for the same shader stage. +//[[stage(fragment)]] +//fn fs_extra() -> [[location(0)]] vec4 { +// return vec4(0.0, 0.5, 0.0, 0.5); +//} diff --git a/tests/out/hlsl/empty.hlsl b/tests/out/hlsl/empty.hlsl index a1b3590ec..e79d36b9c 100644 --- a/tests/out/hlsl/empty.hlsl +++ b/tests/out/hlsl/empty.hlsl @@ -1,5 +1,5 @@ [numthreads(1, 1, 1)] -void comp_main() +void main() { return; } diff --git a/tests/out/hlsl/empty.hlsl.config b/tests/out/hlsl/empty.hlsl.config index f20f94588..71412ac2d 100644 --- a/tests/out/hlsl/empty.hlsl.config +++ b/tests/out/hlsl/empty.hlsl.config @@ -1,2 +1,2 @@ compute=cs_5_0 -compute_name=comp_main +compute_name=main diff --git a/tests/out/hlsl/quad-vert.hlsl b/tests/out/hlsl/quad-vert.hlsl index 4c28ecfb6..06a1a2fcd 100644 --- a/tests/out/hlsl/quad-vert.hlsl +++ b/tests/out/hlsl/quad-vert.hlsl @@ -18,7 +18,7 @@ static float2 a_uv1; static gl_PerVertex perVertexStruct = { float4(0.0, 0.0, 0.0, 1.0), 1.0, float(0.0), float(0.0) }; static float2 a_pos1; -struct VertexInput { +struct VertexInput_main { float2 a_uv2 : LOC1; float2 a_pos2 : LOC0; }; @@ -32,10 +32,10 @@ void main1() return; } -type10 vert_main(VertexInput vertexinput) +type10 main(VertexInput_main vertexinput_main) { - a_uv1 = vertexinput.a_uv2; - a_pos1 = vertexinput.a_pos2; + a_uv1 = vertexinput_main.a_uv2; + a_pos1 = vertexinput_main.a_pos2; main1(); float2 _expr10 = v_uv; float4 _expr11 = perVertexStruct.gl_Position; diff --git a/tests/out/hlsl/quad-vert.hlsl.config b/tests/out/hlsl/quad-vert.hlsl.config index c01697983..49efa2b9a 100644 --- a/tests/out/hlsl/quad-vert.hlsl.config +++ b/tests/out/hlsl/quad-vert.hlsl.config @@ -1,2 +1,2 @@ vertex=vs_5_0 -vertex_name=vert_main +vertex_name=main diff --git a/tests/out/hlsl/quad.hlsl b/tests/out/hlsl/quad.hlsl index bb524e835..6e616106d 100644 --- a/tests/out/hlsl/quad.hlsl +++ b/tests/out/hlsl/quad.hlsl @@ -8,24 +8,24 @@ struct VertexOutput { Texture2D u_texture : register(t0); SamplerState u_sampler : register(s1); -struct VertexInput { +struct VertexInput_main { float2 pos1 : LOC0; float2 uv2 : LOC1; }; -struct FragmentInput { +struct FragmentInput_main { float2 uv3 : LOC0; }; -VertexOutput vert_main(VertexInput vertexinput) +VertexOutput main(VertexInput_main vertexinput_main) { - const VertexOutput vertexoutput1 = { vertexinput.uv2, float4((c_scale * vertexinput.pos1), 0.0, 1.0) }; + const VertexOutput vertexoutput1 = { vertexinput_main.uv2, float4((c_scale * vertexinput_main.pos1), 0.0, 1.0) }; return vertexoutput1; } -float4 frag_main(FragmentInput fragmentinput) : SV_Target0 +float4 main1(FragmentInput_main fragmentinput_main) : SV_Target0 { - float4 color = u_texture.Sample(u_sampler, fragmentinput.uv3); + float4 color = u_texture.Sample(u_sampler, fragmentinput_main.uv3); if ((color.w == 0.0)) { discard; } diff --git a/tests/out/hlsl/quad.hlsl.config b/tests/out/hlsl/quad.hlsl.config index a11240919..bae3c1cc6 100644 --- a/tests/out/hlsl/quad.hlsl.config +++ b/tests/out/hlsl/quad.hlsl.config @@ -1,4 +1,4 @@ vertex=vs_5_0 -vertex_name=vert_main +vertex_name=main fragment=ps_5_0 -fragment_name=frag_main +fragment_name=main1 diff --git a/tests/snapshots.rs b/tests/snapshots.rs index d906b9894..7ea614461 100644 --- a/tests/snapshots.rs +++ b/tests/snapshots.rs @@ -261,26 +261,30 @@ fn write_output_hlsl( file_name: &str, ) { use naga::back::hlsl; + let mut buffer = String::new(); let options = hlsl::Options::default(); - let string = hlsl::write_string(module, info, &options).unwrap(); + let mut writer = hlsl::Writer::new(&mut buffer, &options); + let reflection_info = writer.write(module, info).unwrap(); - fs::write(destination.join(format!("hlsl/{}.hlsl", file_name)), string).unwrap(); + fs::write(destination.join(format!("hlsl/{}.hlsl", file_name)), buffer).unwrap(); // We need a config file for validation script // This file contains an info about profiles (shader stages) contains inside generated shader // This info will be passed to dxc let mut config_str = String::from(""); - for ep in module.entry_points.iter() { - let (stage_str, profile, ep_name) = match ep.stage { - naga::ShaderStage::Vertex => ("vertex", "vs_5_0", &options.vertex_entry_point_name), - naga::ShaderStage::Fragment => { - ("fragment", "ps_5_0", &options.fragment_entry_point_name) - } - naga::ShaderStage::Compute => ("compute", "cs_5_0", &options.compute_entry_point_name), + for (stage, name) in reflection_info.entry_points.iter() { + let stage_str = match stage { + naga::ShaderStage::Vertex => "vertex", + naga::ShaderStage::Fragment => "fragment", + naga::ShaderStage::Compute => "compute", }; config_str = format!( "{}{}={}\n{}_name={}\n", - config_str, stage_str, profile, stage_str, ep_name + config_str, + stage_str, + options.shader_model.to_profile_string(*stage), + stage_str, + name ); } fs::write(