-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add GLSL output to naga snapshots #9204
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
Open
cwfitzgerald
wants to merge
1
commit into
gfx-rs:trunk
Choose a base branch
from
cwfitzgerald:cw/naga-glsl-spirv-snapshots
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -198,6 +198,109 @@ Note: this is an issue with snapshot configuration, not code. If you added a new | |
| } | ||
| } | ||
|
|
||
| fn spirv_cross_stage_name(stage: naga::ShaderStage) -> &'static str { | ||
| match stage { | ||
| naga::ShaderStage::Vertex => "vert", | ||
| naga::ShaderStage::Fragment => "frag", | ||
| naga::ShaderStage::Compute => "comp", | ||
| naga::ShaderStage::Task => "task", | ||
| naga::ShaderStage::Mesh => "mesh", | ||
| naga::ShaderStage::RayGeneration => "rgen", | ||
| naga::ShaderStage::Miss => "rmiss", | ||
| naga::ShaderStage::AnyHit => "rahit", | ||
| naga::ShaderStage::ClosestHit => "rchit", | ||
| } | ||
| } | ||
|
|
||
| fn run_spirv_cross( | ||
| spv_binary: &[u32], | ||
| entry_point: &str, | ||
| stage: naga::ShaderStage, | ||
| ) -> Result<String, String> { | ||
| use std::io::Write; | ||
| use std::process::{Command, Stdio}; | ||
|
|
||
| let stage_name = spirv_cross_stage_name(stage); | ||
| let bytes: &[u8] = bytemuck::cast_slice(spv_binary); | ||
|
|
||
| let mut child = Command::new("spirv-cross") | ||
| .args([ | ||
| "-V", | ||
| "--version", "460", | ||
| "--entry", entry_point, | ||
| "--stage", stage_name, | ||
| "-", | ||
| ]) | ||
| .stdin(Stdio::piped()) | ||
| .stdout(Stdio::piped()) | ||
| .stderr(Stdio::piped()) | ||
| .spawn() | ||
| .expect( | ||
| "Failed to execute spirv-cross. Install it via the Vulkan SDK \ | ||
| or from https://github.com/KhronosGroup/SPIRV-Cross", | ||
| ); | ||
|
|
||
| child.stdin.take().unwrap().write_all(bytes).unwrap(); | ||
|
|
||
| let output = child.wait_with_output().unwrap(); | ||
| let stderr = String::from_utf8_lossy(&output.stderr).replace("\r\n", "\n"); | ||
| let stdout = String::from_utf8_lossy(&output.stdout).replace("\r\n", "\n"); | ||
|
|
||
| if !output.status.success() { | ||
| let mut commented = String::new(); | ||
| for line in stderr.lines() { | ||
| commented.push_str(&format!("// {line}\n")); | ||
| } | ||
| Err(commented) | ||
| } else { | ||
| Ok(stdout) | ||
| } | ||
| } | ||
|
|
||
| /// Writes GLSL output generated by SPIRV-Cross for the given SPIR-V binary. | ||
| /// | ||
| /// Behavior: | ||
| /// - For multiple entry points, each GLSL output is prefixed with a comment block | ||
| /// indicating the entry point name and shader stage (e.g., `// Entry point: "main" (frag) //`). | ||
| /// - For a single entry point, no header is added (cleaner output for single-shader files). | ||
| /// - On SPIRV-Cross failure, stderr is captured as commented lines in the output file, | ||
| /// and the function continues to write remaining entry points. This ensures test | ||
| /// snapshots are always generated even when translation fails. | ||
| fn write_spirv_cross_glsl( | ||
| input: &Input, | ||
| spv_binary: &[u32], | ||
| entry_points: &[(String, naga::ShaderStage)], | ||
| extension: &str, | ||
| ) { | ||
| let multiple = entry_points.len() > 1; | ||
| let mut output = String::new(); | ||
|
|
||
| for (i, (name, stage)) in entry_points.iter().enumerate() { | ||
| if multiple { | ||
| if i > 0 { | ||
| output.push('\n'); | ||
| } | ||
| let stage_name = spirv_cross_stage_name(*stage); | ||
| let inner = format!(" Entry point: \"{name}\" ({stage_name}) "); | ||
| let width = inner.len() + 4; // "// " + inner + " //" | ||
| let bar: String = "/".repeat(width); | ||
| output.push_str(&bar); | ||
| output.push('\n'); | ||
| output.push_str(&format!("//{inner}//")); | ||
| output.push('\n'); | ||
| output.push_str(&bar); | ||
| output.push('\n'); | ||
| } | ||
|
|
||
| match run_spirv_cross(spv_binary, name, *stage) { | ||
| Ok(glsl) => output.push_str(&glsl), | ||
| Err(err) => output.push_str(&err), | ||
| } | ||
| } | ||
|
|
||
| input.write_output_file("spv", extension, output, DIR_OUT); | ||
| } | ||
|
|
||
| fn write_output_spv( | ||
| input: &Input, | ||
| module: &naga::Module, | ||
|
|
@@ -221,17 +324,29 @@ fn write_output_spv( | |
| entry_point: ep.name.clone(), | ||
| shader_stage: ep.stage, | ||
| }; | ||
| write_output_spv_inner( | ||
| let spv_binary = write_output_spv_inner( | ||
| input, | ||
| &module, | ||
| &info, | ||
| &options, | ||
| Some(&pipeline_options), | ||
| &format!("{}.spvasm", ep.name), | ||
| ); | ||
| write_spirv_cross_glsl( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if in this case we should still combine them into one file, even if the spirv entry points will be written separately? |
||
| input, | ||
| &spv_binary, | ||
| &[(ep.name.clone(), ep.stage)], | ||
| &format!("{}.spvasm.glsl", ep.name), | ||
| ); | ||
| } | ||
| } else { | ||
| write_output_spv_inner(input, &module, &info, &options, None, "spvasm"); | ||
| let spv_binary = write_output_spv_inner(input, &module, &info, &options, None, "spvasm"); | ||
| let entry_points: Vec<(String, naga::ShaderStage)> = module | ||
| .entry_points | ||
| .iter() | ||
| .map(|ep| (ep.name.clone(), ep.stage)) | ||
| .collect(); | ||
| write_spirv_cross_glsl(input, &spv_binary, &entry_points, "spvasm.glsl"); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -242,12 +357,12 @@ fn write_output_spv_inner( | |
| options: &naga::back::spv::Options<'_>, | ||
| pipeline_options: Option<&naga::back::spv::PipelineOptions>, | ||
| extension: &str, | ||
| ) { | ||
| ) -> Vec<u32> { | ||
| use naga::back::spv; | ||
| use rspirv::binary::Disassemble; | ||
| println!("Generating SPIR-V for {:?}", input.file_name); | ||
| let spv = spv::write_vec(module, info, options, pipeline_options).unwrap(); | ||
| let dis = rspirv::dr::load_words(spv) | ||
| let dis = rspirv::dr::load_words(spv.clone()) | ||
| .expect("Produced invalid SPIR-V") | ||
| .disassemble(); | ||
| // HACK escape CR/LF if source code is in side. | ||
|
|
@@ -258,6 +373,7 @@ fn write_output_spv_inner( | |
| dis | ||
| }; | ||
| input.write_output_file("spv", extension, dis, DIR_OUT); | ||
| spv | ||
| } | ||
|
|
||
| fn write_output_msl( | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| #version 450 | ||
| layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; | ||
|
|
||
| void _4() | ||
| { | ||
| barrier(); | ||
| memoryBarrierBuffer(); | ||
| memoryBarrierImage(); | ||
| barrier(); | ||
| memoryBarrier(); | ||
| barrier(); | ||
| } | ||
|
|
||
| void main() | ||
| { | ||
| _4(); | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| #version 450 | ||
| layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; | ||
|
|
||
| struct _5 | ||
| { | ||
| float _m0; | ||
| }; | ||
|
|
||
| struct _8 | ||
| { | ||
| uvec2 _m0; | ||
| }; | ||
|
|
||
| layout(binding = 0, std430) buffer _12_11 | ||
| { | ||
| _5 _m0; | ||
| } _11; | ||
|
|
||
| layout(binding = 1, std430) readonly buffer _15_14 | ||
| { | ||
| _8 _m0; | ||
| } _14; | ||
|
|
||
| uniform sampler2D SPIRV_Cross_CombinedSPIRV_Cross_DummySampler; | ||
|
|
||
| void _20() | ||
| { | ||
| _11._m0._m0 = vec4(texelFetch(SPIRV_Cross_CombinedSPIRV_Cross_DummySampler, ivec2(_14._m0._m0), 0).x).x; | ||
| } | ||
|
|
||
| void main() | ||
| { | ||
| _20(); | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| #version 450 | ||
| #extension GL_EXT_fragment_shader_barycentric : require | ||
|
|
||
| layout(location = 0) pervertexEXT in float _25[3]; | ||
| layout(location = 0) out vec4 _28; | ||
| float _9[3] = float[](0.0, 0.0, 0.0); | ||
| vec4 _12 = vec4(0.0); | ||
|
|
||
| void _16() | ||
| { | ||
| _12 = vec4(_9[0], _9[1], _9[2], 1.0); | ||
| } | ||
|
|
||
| void main() | ||
| { | ||
| _9 = _25; | ||
| _16(); | ||
| _28 = _12; | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| #version 450 | ||
|
|
||
| #if defined(GL_KHR_shader_subgroup_basic) | ||
| #extension GL_KHR_shader_subgroup_basic : require | ||
| #elif defined(GL_NV_shader_thread_group) | ||
| #extension GL_NV_shader_thread_group : require | ||
| #elif defined(GL_ARB_shader_ballot) && defined(GL_ARB_shader_int64) | ||
| #extension GL_ARB_shader_int64 : enable | ||
| #extension GL_ARB_shader_ballot : require | ||
| #elif defined(GL_AMD_gcn_shader) && (defined(GL_AMD_gpu_shader_int64) || defined(GL_NV_gpu_shader5)) | ||
| #extension GL_AMD_gpu_shader_int64 : enable | ||
| #extension GL_NV_gpu_shader5 : enable | ||
| #extension GL_AMD_gcn_shader : require | ||
| #else | ||
| #error No extensions available to emulate requested subgroup feature. | ||
| #endif | ||
|
|
||
| #if defined(GL_KHR_shader_subgroup_basic) | ||
| #extension GL_KHR_shader_subgroup_basic : require | ||
| #endif | ||
| layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; | ||
|
|
||
| #ifndef GL_KHR_shader_subgroup_basic | ||
| void subgroupBarrier() { memoryBarrierShared(); } | ||
| #endif | ||
|
|
||
| #ifndef GL_KHR_shader_subgroup_basic | ||
| void subgroupMemoryBarrier() { groupMemoryBarrier(); } | ||
| void subgroupMemoryBarrierBuffer() { groupMemoryBarrier(); } | ||
| void subgroupMemoryBarrierShared() { memoryBarrierShared(); } | ||
| void subgroupMemoryBarrierImage() { groupMemoryBarrier(); } | ||
| #endif | ||
|
|
||
| void _4() | ||
| { | ||
| subgroupMemoryBarrier(); | ||
| subgroupBarrier(); | ||
| } | ||
|
|
||
| void main() | ||
| { | ||
| _4(); | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| #version 460 | ||
| layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; | ||
|
|
||
| void _5() | ||
| { | ||
| int _10 = 0; | ||
| uvec2 _27 = uvec2(4294967295u); | ||
| for (;;) | ||
| { | ||
| if (all(equal(uvec2(0u), _27))) | ||
| { | ||
| break; | ||
| } | ||
| _27 -= uvec2(uint(_27.y == 0u), 1u); | ||
| if (!(_10 < 4)) | ||
| { | ||
| break; | ||
| } | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| void main() | ||
| { | ||
| _5(); | ||
| } | ||
|
|
41 changes: 41 additions & 0 deletions
41
naga/tests/out/spv/wgsl-6438-conflicting-idents.spvasm.glsl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| ////////////////////////////// | ||
| // Entry point: "vs" (vert) // | ||
| ////////////////////////////// | ||
| #version 460 | ||
|
|
||
| struct _6 | ||
| { | ||
| vec4 _m0; | ||
| vec2 _m1; | ||
| }; | ||
|
|
||
| layout(location = 0) in vec2 _8; | ||
| layout(location = 0) out vec2 _13; | ||
|
|
||
| void main() | ||
| { | ||
| _6 _19 = _6(vec4(0.0), vec2(0.0)); | ||
| _19._m0 = vec4(_8, 0.0, 1.0); | ||
| gl_Position = _19._m0; | ||
| _13 = _19._m1; | ||
| } | ||
|
|
||
|
|
||
| ////////////////////////////// | ||
| // Entry point: "fs" (frag) // | ||
| ////////////////////////////// | ||
| #version 460 | ||
|
|
||
| struct _6 | ||
| { | ||
| vec4 _m0; | ||
| vec2 _m1; | ||
| }; | ||
|
|
||
| layout(location = 0) out vec4 _32; | ||
|
|
||
| void main() | ||
| { | ||
| _32 = vec4(1.0, 0.0, 0.0, 1.0); | ||
| } | ||
|
|
9 changes: 9 additions & 0 deletions
9
naga/tests/out/spv/wgsl-6772-unpack-expr-accesses.spvasm.glsl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #version 460 | ||
| #extension GL_EXT_shader_explicit_arithmetic_types_int8 : require | ||
| #extension GL_EXT_shader_8bit_storage : require | ||
| layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; | ||
|
|
||
| void main() | ||
| { | ||
| } | ||
|
|
13 changes: 13 additions & 0 deletions
13
naga/tests/out/spv/wgsl-7048-multiple-dynamic-1.spvasm.glsl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #version 460 | ||
| layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; | ||
|
|
||
| const vec3 _13[2] = vec3[](vec3(0.0), vec3(0.0)); | ||
|
|
||
| void main() | ||
| { | ||
| vec4 _17 = vec4(0.0); | ||
| int _19 = 0; | ||
| int _21 = 0; | ||
| _17.x += (_13[_21].y * _13[_19].z); | ||
| } | ||
|
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add an extra line like "spirv-cross error:", this also makes errors more searchable