diff --git a/examples/features/src/framework.rs b/examples/features/src/framework.rs index aef3ca6626c..67803a3195c 100644 --- a/examples/features/src/framework.rs +++ b/examples/features/src/framework.rs @@ -260,7 +260,8 @@ impl ExampleContext { async fn init_async(surface: &mut SurfaceWrapper, window: Arc) -> Self { log::info!("Initializing wgpu..."); - let instance_descriptor = wgpu::InstanceDescriptor::from_env_or_default(); + let mut instance_descriptor = wgpu::InstanceDescriptor::from_env_or_default(); + instance_descriptor.backend_options.dx12.shader_compiler = wgpu::Dx12Compiler::StaticDxc; let instance = wgpu::Instance::new(&instance_descriptor); surface.pre_adapter(&instance, window); let adapter = get_adapter_with_capabilities_or_from_env( diff --git a/examples/features/src/mesh_shader/mod.rs b/examples/features/src/mesh_shader/mod.rs index 20f069e9a84..02d039a9234 100644 --- a/examples/features/src/mesh_shader/mod.rs +++ b/examples/features/src/mesh_shader/mod.rs @@ -5,38 +5,6 @@ fn compile_wgsl(device: &wgpu::Device) -> wgpu::ShaderModule { source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), }) } -fn compile_hlsl(device: &wgpu::Device, entry: &str, stage_str: &str) -> wgpu::ShaderModule { - let out_path = format!( - "{}/src/mesh_shader/shader.{stage_str}.cso", - env!("CARGO_MANIFEST_DIR") - ); - let cmd = std::process::Command::new("dxc") - .args([ - "-T", - &format!("{stage_str}_6_5"), - "-E", - entry, - &format!("{}/src/mesh_shader/shader.hlsl", env!("CARGO_MANIFEST_DIR")), - "-Fo", - &out_path, - ]) - .output() - .unwrap(); - if !cmd.status.success() { - panic!("DXC failed:\n{}", String::from_utf8(cmd.stderr).unwrap()); - } - let file = std::fs::read(&out_path).unwrap(); - std::fs::remove_file(out_path).unwrap(); - unsafe { - device.create_shader_module_passthrough(wgpu::ShaderModuleDescriptorPassthrough { - entry_point: entry.to_owned(), - label: None, - num_workgroups: (1, 1, 1), - dxil: Some(std::borrow::Cow::Owned(file)), - ..Default::default() - }) - } -} fn compile_msl(device: &wgpu::Device, entry: &str) -> wgpu::ShaderModule { unsafe { @@ -61,7 +29,7 @@ impl crate::framework::Example for Example { _queue: &wgpu::Queue, ) -> Self { let (ts, ms, fs, ts_name, ms_name, fs_name) = match adapter.get_info().backend { - wgpu::Backend::Vulkan => ( + wgpu::Backend::Vulkan | wgpu::Backend::Dx12 => ( compile_wgsl(device), compile_wgsl(device), compile_wgsl(device), @@ -69,14 +37,6 @@ impl crate::framework::Example for Example { "ms_main", "fs_main", ), - wgpu::Backend::Dx12 => ( - compile_hlsl(device, "Task", "as"), - compile_hlsl(device, "Mesh", "ms"), - compile_hlsl(device, "Frag", "ps"), - "main", - "main", - "main", - ), wgpu::Backend::Metal => ( compile_msl(device, "taskShader"), compile_msl(device, "meshShader"), diff --git a/examples/features/src/mesh_shader/shader.hlsl b/examples/features/src/mesh_shader/shader.hlsl deleted file mode 100644 index e70961f2d71..00000000000 --- a/examples/features/src/mesh_shader/shader.hlsl +++ /dev/null @@ -1,53 +0,0 @@ -struct OutVertex { - float4 Position : SV_POSITION; - float4 Color: COLOR; -}; -struct OutPrimitive { - float4 ColorMask : COLOR_MASK : PRIMITIVE; - bool CullPrimitive: SV_CullPrimitive; -}; -struct InVertex { - float4 Color: COLOR; -}; -struct InPrimitive { - float4 ColorMask : COLOR_MASK : PRIMITIVE; -}; -struct PayloadData { - float4 ColorMask; - bool Visible; -}; - - -static const float4 positions[3] = {float4(0., 1.0, 0., 1.0), float4(-1.0, -1.0, 0., 1.0), float4(1.0, -1.0, 0., 1.0)}; -static const float4 colors[3] = {float4(0., 1., 0., 1.), float4(0., 0., 1., 1.), float4(1., 0., 0., 1.)}; - -groupshared PayloadData outPayload; - -[numthreads(1, 1, 1)] -void Task() { - outPayload.ColorMask = float4(1.0, 1.0, 0.0, 1.0); - outPayload.Visible = true; - DispatchMesh(3, 1, 1, outPayload); -} - -[outputtopology("triangle")] -[numthreads(1, 1, 1)] -void Mesh(out indices uint3 triangles[1], out vertices OutVertex vertices[3], out primitives OutPrimitive primitives[1], in payload PayloadData payload) { - SetMeshOutputCounts(3, 1); - - vertices[0].Position = positions[0]; - vertices[1].Position = positions[1]; - vertices[2].Position = positions[2]; - - vertices[0].Color = colors[0] * payload.ColorMask; - vertices[1].Color = colors[1] * payload.ColorMask; - vertices[2].Color = colors[2] * payload.ColorMask; - - triangles[0] = uint3(0, 1, 2); - primitives[0].ColorMask = float4(1.0, 0.0, 0.0, 1.0); - primitives[0].CullPrimitive = !payload.Visible; -} - -float4 Frag(InVertex vertex, InPrimitive primitive) : SV_Target { - return vertex.Color * primitive.ColorMask; -} diff --git a/naga/hlsl-snapshots/src/lib.rs b/naga/hlsl-snapshots/src/lib.rs index ee455432731..6340fd11c2d 100644 --- a/naga/hlsl-snapshots/src/lib.rs +++ b/naga/hlsl-snapshots/src/lib.rs @@ -50,6 +50,8 @@ pub struct Config { pub vertex: Vec, pub fragment: Vec, pub compute: Vec, + pub task: Vec, + pub mesh: Vec, } impl Config { @@ -59,6 +61,8 @@ impl Config { vertex: Default::default(), fragment: Default::default(), compute: Default::default(), + task: Default::default(), + mesh: Default::default(), } } @@ -85,8 +89,14 @@ impl Config { vertex, fragment, compute, + task, + mesh, } = self; - vertex.is_empty() && fragment.is_empty() && compute.is_empty() + vertex.is_empty() + && fragment.is_empty() + && compute.is_empty() + && task.is_empty() + && mesh.is_empty() } } diff --git a/naga/src/back/hlsl/conv.rs b/naga/src/back/hlsl/conv.rs index 6cd3679e817..7a659355355 100644 --- a/naga/src/back/hlsl/conv.rs +++ b/naga/src/back/hlsl/conv.rs @@ -149,8 +149,8 @@ impl crate::StorageFormat { } impl crate::BuiltIn { - pub(super) fn to_hlsl_str(self) -> Result<&'static str, Error> { - Ok(match self { + pub(super) fn to_hlsl_str(self) -> Result, Error> { + Ok(Some(match self { Self::Position { .. } => "SV_Position", // vertex Self::ClipDistance => "SV_ClipDistance", @@ -186,13 +186,15 @@ impl crate::BuiltIn { return Err(Error::Custom(format!("Unsupported builtin {self:?}"))) } Self::CullPrimitive => "SV_CullPrimitive", - Self::PointIndex | Self::LineIndices | Self::TriangleIndices => unimplemented!(), Self::MeshTaskSize | Self::VertexCount | Self::PrimitiveCount | Self::Vertices - | Self::Primitives => unreachable!(), - }) + | Self::Primitives + | Self::PointIndex + | Self::LineIndices + | Self::TriangleIndices => return Ok(None), + })) } } diff --git a/naga/src/back/hlsl/mod.rs b/naga/src/back/hlsl/mod.rs index 0230434a742..0902f0b5bfd 100644 --- a/naga/src/back/hlsl/mod.rs +++ b/naga/src/back/hlsl/mod.rs @@ -155,7 +155,7 @@ use core::fmt::Error as FmtError; use thiserror::Error; -use crate::{back, ir, proc}; +use crate::{back, ir, proc, Handle}; /// Direct3D 12 binding information for a global variable. /// @@ -755,4 +755,8 @@ pub struct Writer<'a, W> { /// [`AccessIndex`]: crate::Expression::AccessIndex temp_access_chain: Vec, need_bake_expressions: back::NeedBakeExpressions, + + // Static var name, groupshared var name, is groupshared var name + task_payload_groupshared_names: + crate::FastHashMap, (String, String, String)>, } diff --git a/naga/src/back/hlsl/writer.rs b/naga/src/back/hlsl/writer.rs index cc85e512f22..32c67f76614 100644 --- a/naga/src/back/hlsl/writer.rs +++ b/naga/src/back/hlsl/writer.rs @@ -3,7 +3,10 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use core::{fmt, mem}; +use core::{ + fmt::{self, Write as _}, + mem, +}; use super::{ help, @@ -83,6 +86,9 @@ pub(super) struct EntryPointInterface { /// The `EntryPointBinding::members` array is sorted by binding, /// So that we can walk it in `Statement::Return` handler. output: Option, + mesh_vertices: Option, + mesh_primitives: Option, + mesh_indices: Option, } #[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] @@ -106,6 +112,8 @@ impl InterfaceKey { enum Io { Input, Output, + MeshVertices, + MeshPrimitives, } const fn is_subgroup_builtin_binding(binding: &Option) -> bool { @@ -147,6 +155,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { continue_ctx: back::continue_forward::ContinueCtx::default(), temp_access_chain: Vec::new(), need_bake_expressions: Default::default(), + task_payload_groupshared_names: Default::default(), } } @@ -166,6 +175,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { self.written_candidate_intersection = false; self.continue_ctx.clear(); self.need_bake_expressions.clear(); + self.task_payload_groupshared_names.clear(); } /// Generates statements to be inserted immediately before and at the very @@ -410,13 +420,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { for index in ep_range.clone() { let ep = &module.entry_points[index]; let ep_name = self.names[&NameKey::EntryPoint(index as u16)].clone(); - let ep_io = self.write_ep_interface( - module, - &ep.function, - ep.stage, - &ep_name, - fragment_entry_point, - )?; + let ep_io = self.write_ep_interface(module, ep, &ep_name, fragment_entry_point)?; self.entry_point_io.insert(index, ep_io); } @@ -461,7 +465,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { self.write_wrapped_functions(module, &ctx)?; - self.write_function(module, name.as_str(), function, &ctx, info)?; + self.write_function(module, name.as_str(), function, &ctx, info, String::new())?; writeln!(self.out)?; } @@ -507,18 +511,27 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { self.write_wrapped_functions(module, &ctx)?; + let mut header = String::new(); if ep.stage.compute_like() { // HLSL is calling workgroup size "num threads" let num_threads = ep.workgroup_size; writeln!( - self.out, + header, "[numthreads({}, {}, {})]", num_threads[0], num_threads[1], num_threads[2] )?; } + if let Some(ref info) = ep.mesh_info { + let topology_str = match info.topology { + crate::MeshOutputTopology::Points => unreachable!(), + crate::MeshOutputTopology::Lines => "line", + crate::MeshOutputTopology::Triangles => "triangle", + }; + writeln!(header, "[outputtopology(\"{topology_str}\")]")?; + } let name = self.names[&NameKey::EntryPoint(index as u16)].clone(); - self.write_function(module, &name, &ep.function, &ctx, info)?; + self.write_function(module, &name, &ep.function, &ctx, info, header)?; if index < module.entry_points.len() - 1 { writeln!(self.out)?; @@ -567,7 +580,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { binding: &Option, stage: Option<(ShaderStage, Io)>, ) -> BackendResult { - match *binding { + let per_primitive = match *binding { Some(crate::Binding::BuiltIn(builtin)) if !is_subgroup_builtin_binding(binding) => { if builtin == crate::BuiltIn::ViewIndex && self.options.shader_model < ShaderModel::V6_1 @@ -577,22 +590,35 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { ShaderModel::V6_1, )); } - let builtin_str = builtin.to_hlsl_str()?; - write!(self.out, " : {builtin_str}")?; + if let Some(builtin_str) = builtin.to_hlsl_str()? { + write!(self.out, " : {builtin_str}")?; + } + false } Some(crate::Binding::Location { - blend_src: Some(1), .. + blend_src: Some(1), + per_primitive, + .. }) => { write!(self.out, " : SV_Target1")?; + per_primitive } - Some(crate::Binding::Location { location, .. }) => { + Some(crate::Binding::Location { + location, + per_primitive, + .. + }) => { if stage == Some((ShaderStage::Fragment, Io::Output)) { write!(self.out, " : SV_Target{location}")?; } else { write!(self.out, " : {LOCATION_SEMANTIC}{location}")?; } + per_primitive } - _ => {} + _ => false, + }; + if per_primitive { + write!(self.out, " : primitive")?; } Ok(()) @@ -603,8 +629,10 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { module: &Module, shader_stage: (ShaderStage, Io), struct_name: String, + var_name: Option<&str>, mut members: Vec, ) -> Result { + let struct_name = self.namer.call(&struct_name); // Sort the members so that first come the user-defined varyings // in ascending locations, and then built-ins. This allows VS and FS // interfaces to match with regards to order. @@ -650,13 +678,15 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { // bring back the original order members.sort_by_key(|m| m.index); } - Io::Output => { + Io::Output | Io::MeshVertices | Io::MeshPrimitives => { // keep it sorted by binding } } Ok(EntryPointBinding { - arg_name: self.namer.call(struct_name.to_lowercase().as_str()), + arg_name: self + .namer + .call(var_name.unwrap_or(struct_name.to_lowercase().as_str())), ty_name: struct_name, members, }) @@ -706,7 +736,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { } } - self.write_interface_struct(module, (stage, Io::Input), struct_name, fake_members) + self.write_interface_struct(module, (stage, Io::Input), struct_name, None, fake_members) } /// Flatten all entry point results into a single struct. @@ -782,7 +812,80 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { }); } - self.write_interface_struct(module, (stage, Io::Output), struct_name, fake_members) + self.write_interface_struct(module, (stage, Io::Output), struct_name, None, fake_members) + } + + fn write_ep_mesh_output_struct( + &mut self, + module: &Module, + entry_point_name: &str, + is_primitive: bool, + mesh_info: &crate::MeshStageInfo, + ) -> Result { + let (in_type, io, var_prefix, arg_name) = if is_primitive { + ( + mesh_info.primitive_output_type, + Io::MeshPrimitives, + "Primitive", + "primitives", + ) + } else { + ( + mesh_info.vertex_output_type, + Io::MeshVertices, + "Vertex", + "vertices", + ) + }; + let struct_name = format!("Mesh{var_prefix}Output_{entry_point_name}",); + + let members = match module.types[in_type].inner { + TypeInner::Struct { ref members, .. } => members, + _ => unreachable!(), + }; + let mut out_members = Vec::new(); + for (index, member) in members.iter().enumerate() { + if matches!( + member.binding, + Some(crate::Binding::BuiltIn( + crate::BuiltIn::PointIndex + | crate::BuiltIn::LineIndices + | crate::BuiltIn::TriangleIndices + )) + ) { + continue; + } + let member_name = self.namer.call_or(&member.name, "member"); + out_members.push(EpStructMember { + name: member_name, + ty: member.ty, + binding: member.binding.clone(), + index: index as u32, + }) + } + self.write_interface_struct( + module, + (ShaderStage::Mesh, io), + struct_name, + Some(arg_name), + out_members, + ) + } + + fn write_ep_mesh_output_indices( + &mut self, + topology: crate::MeshOutputTopology, + ) -> Result { + let (indices_name, indices_type) = match topology { + crate::MeshOutputTopology::Points => unreachable!(), + crate::MeshOutputTopology::Lines => (self.namer.call("lineIndices"), "uint2"), + crate::MeshOutputTopology::Triangles => (self.namer.call("triangleIndices"), "uint3"), + }; + Ok(EntryPointBinding { + ty_name: indices_type.to_string(), + arg_name: indices_name, + members: Vec::new(), + }) } /// Writes special interface structures for an entry point. The special structures have @@ -791,11 +894,12 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { fn write_ep_interface( &mut self, module: &Module, - func: &crate::Function, - stage: ShaderStage, + ep: &crate::EntryPoint, ep_name: &str, frag_ep: Option<&FragmentEntryPoint<'_>>, ) -> Result { + let func = &ep.function; + let stage = ep.stage; Ok(EntryPointInterface { input: if !func.arguments.is_empty() && (stage == ShaderStage::Fragment @@ -814,6 +918,21 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { } _ => None, }, + mesh_vertices: if let Some(ref info) = ep.mesh_info { + Some(self.write_ep_mesh_output_struct(module, ep_name, false, info)?) + } else { + None + }, + mesh_primitives: if let Some(ref info) = ep.mesh_info { + Some(self.write_ep_mesh_output_struct(module, ep_name, true, info)?) + } else { + None + }, + mesh_indices: if let Some(ref info) = ep.mesh_info { + Some(self.write_ep_mesh_output_indices(info.topology)?) + } else { + None + }, }) } @@ -962,6 +1081,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { return self.write_global_sampler(module, handle, global); } + let name = self.names[&NameKey::GlobalVariable(handle)].clone(); + // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-register let register_ty = match global.space { crate::AddressSpace::Function => unreachable!("Function address space"), @@ -975,7 +1096,6 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { self.write_type(module, global.ty)?; "" } - crate::AddressSpace::TaskPayload => unimplemented!(), crate::AddressSpace::Uniform => { // constant buffer declarations are expected to be inlined, e.g. // `cbuffer foo: register(b0) { field1: type1; }` @@ -1008,6 +1128,28 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { write!(self.out, "ConstantBuffer<")?; "b" } + crate::AddressSpace::TaskPayload => { + let static_var_name = self.namer.call(&format!("{}Static", name)); + let groupshared_var_name = self.namer.call(&format!("{}Shared", name)); + let is_groupshared = self.namer.call(&format!("{}IsShared", name)); + write!(self.out, "static ")?; + self.write_type(module, global.ty)?; + writeln!(self.out, " {static_var_name};")?; + + write!(self.out, "groupshared ")?; + self.write_type(module, global.ty)?; + writeln!(self.out, " {groupshared_var_name};")?; + writeln!(self.out, "static bool {is_groupshared};")?; + writeln!( + self.out, + "#define {name} ({is_groupshared} ? {groupshared_var_name} : {static_var_name})" + )?; + self.task_payload_groupshared_names.insert( + handle, + (static_var_name, groupshared_var_name, is_groupshared), + ); + return Ok(()); + } }; // If the global is a immediate data write the type now because it will be a @@ -1024,7 +1166,6 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { write!(self.out, ">")?; } - let name = &self.names[&NameKey::GlobalVariable(handle)]; write!(self.out, " {name}")?; // Immediates need to be assigned a binding explicitly by the consumer @@ -1520,12 +1661,33 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { func: &crate::Function, func_ctx: &back::FunctionCtx<'_>, info: &valid::FunctionInfo, + header: String, ) -> BackendResult { // Function Declaration Syntax - https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-function-syntax self.update_expressions_to_bake(module, func, info); + let ep = match func_ctx.ty { + back::FunctionType::EntryPoint(idx) => Some(&module.entry_points[idx as usize]), + back::FunctionType::Function(_) => None, + }; + let mesh_info = ep.and_then(|a| a.mesh_info.as_ref()); + let task_payload = ep.and_then(|a| a.task_payload); + + let nested = matches!( + ep, + Some(crate::EntryPoint { + stage: ShaderStage::Task | ShaderStage::Mesh, + .. + }) + ); + if !nested { + write!(self.out, "{header}")?; + } - if let Some(ref result) = func.result { + if func.result.is_none() { + write!(self.out, "void")?; + } else { + let result = func.result.as_ref().unwrap(); // Write typedef if return type is an array let array_return_type = match module.types[result.ty].inner { TypeInner::Array { base, size, .. } => { @@ -1567,24 +1729,35 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { } } } - } else { - write!(self.out, "void")?; } + let nested_name = if nested { + self.namer.call(&format!("_{name}")) + } else { + name.to_string() + }; + // Write function name - write!(self.out, " {name}(")?; + write!(self.out, " {nested_name}(")?; let need_workgroup_variables_initialization = self.need_workgroup_variables_initialization(func_ctx, module); + let mut any_args_written = false; + let mut separator = || { + if any_args_written { + ", " + } else { + any_args_written = true; + "" + } + }; + // Write function arguments for non entry point functions match func_ctx.ty { back::FunctionType::Function(handle) => { for (index, arg) in func.arguments.iter().enumerate() { - if index != 0 { - write!(self.out, ", ")?; - } - + write!(self.out, "{}", separator())?; self.write_function_argument(module, handle, arg, index)?; } } @@ -1593,12 +1766,11 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { self.entry_point_io.get(&(ep_index as usize)).unwrap().input { write!(self.out, "{} {}", ep_input.ty_name, ep_input.arg_name)?; + separator(); } else { let stage = module.entry_points[ep_index as usize].stage; for (index, arg) in func.arguments.iter().enumerate() { - if index != 0 { - write!(self.out, ", ")?; - } + write!(self.out, "{}", separator())?; self.write_type(module, arg.ty)?; let argument_name = @@ -1613,17 +1785,10 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { } } if need_workgroup_variables_initialization { - if self - .entry_point_io - .get(&(ep_index as usize)) - .unwrap() - .input - .is_some() - || !func.arguments.is_empty() - { - write!(self.out, ", ")?; + write!(self.out, "{}uint __local_invocation_index", separator())?; + if !nested { + write!(self.out, " : SV_GroupIndex")?; } - write!(self.out, "uint3 __local_invocation_id : SV_GroupThreadID")?; } } } @@ -1642,8 +1807,23 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { writeln!(self.out)?; writeln!(self.out, "{{")?; - if need_workgroup_variables_initialization { - self.write_workgroup_variables_initialization(func_ctx, module)?; + if need_workgroup_variables_initialization && !nested { + let back::FunctionType::EntryPoint(index) = func_ctx.ty else { + unreachable!(); + }; + writeln!( + self.out, + "{}if (all(__local_invocation_index == 0)) {{", + back::INDENT + )?; + self.write_workgroup_variables_initialization( + func_ctx, + module, + module.entry_points[index as usize].stage, + )?; + + writeln!(self.out, "{}}}", back::INDENT)?; + self.write_control_barrier(crate::Barrier::WORK_GROUP, back::Level(1))?; } if let back::FunctionType::EntryPoint(index) = func_ctx.ty { @@ -1694,6 +1874,268 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { writeln!(self.out, "}}")?; + if nested { + let mut any_args_written = false; + let mut separator = || { + if any_args_written { + ", " + } else { + any_args_written = true; + "" + } + }; + + let back::FunctionType::EntryPoint(ep_index) = func_ctx.ty else { + unreachable!(); + }; + let stage = module.entry_points[ep_index as usize].stage; + write!(self.out, "{header}")?; + write!(self.out, "void {name}(")?; + let mut arg_names = Vec::new(); + if let Some(ref ep_input) = self.entry_point_io.get(&(ep_index as usize)).unwrap().input + { + write!(self.out, "{} {}", ep_input.ty_name, ep_input.arg_name)?; + arg_names.push(ep_input.arg_name.clone()); + } else { + for (index, arg) in func.arguments.iter().enumerate() { + write!(self.out, "{}", separator())?; + self.write_type(module, arg.ty)?; + + let argument_name = + &self.names[&NameKey::EntryPointArgument(ep_index, index as u32)]; + arg_names.push(argument_name.clone()); + + write!(self.out, " {argument_name}")?; + if let TypeInner::Array { base, size, .. } = module.types[arg.ty].inner { + self.write_array_size(module, base, size)?; + } + + self.write_semantic(&arg.binding, Some((stage, Io::Input)))?; + } + } + if need_workgroup_variables_initialization || stage == ShaderStage::Mesh { + write!( + self.out, + "{}uint __local_invocation_index : SV_GroupIndex", + separator() + )?; + if !nested { + write!(self.out, " : SV_GroupIndex")?; + } + if need_workgroup_variables_initialization { + arg_names.push("__local_invocation_index".to_string()); + } + } + if let Some(mesh_info) = mesh_info { + let mesh_interface = self.entry_point_io.get(&(ep_index as usize)).unwrap(); + let vert_info = mesh_interface.mesh_vertices.as_ref().unwrap(); + let prim_info = mesh_interface.mesh_primitives.as_ref().unwrap(); + let indices_info = mesh_interface.mesh_indices.as_ref().unwrap(); + write!( + self.out, + "{}out indices {} {}[{}]", + separator(), + indices_info.ty_name, + indices_info.arg_name, + mesh_info.max_primitives + )?; + write!( + self.out, + ", out vertices {} {}[{}]", + vert_info.ty_name, vert_info.arg_name, mesh_info.max_vertices + )?; + write!( + self.out, + ", out primitives {} {}[{}]", + prim_info.ty_name, prim_info.arg_name, mesh_info.max_primitives + )?; + let mut in_payload_name = None; + if let Some(task_payload) = task_payload { + // Set task payload variable + write!(self.out, ", in payload ")?; + let ty = module.global_variables[task_payload].ty; + self.write_type(module, ty)?; + + let out_payload_name = &self.names[&NameKey::GlobalVariable(task_payload)]; + let name = self.namer.call(&format!("_{}", out_payload_name)); + write!(self.out, " {name}")?; + in_payload_name = Some(name); + } + writeln!(self.out, ") {{")?; + if let Some(in_name) = in_payload_name { + let (ref static_name, _, ref is_groupshared) = + self.task_payload_groupshared_names[&task_payload.unwrap()]; + writeln!(self.out, "{}{} = false;", back::INDENT, is_groupshared)?; + writeln!(self.out, "{}{} = {};", back::INDENT, static_name, in_name)?; + } + if need_workgroup_variables_initialization { + writeln!( + self.out, + "{}if (all(__local_invocation_index == 0)) {{", + back::INDENT + )?; + self.write_workgroup_variables_initialization( + func_ctx, + module, + module.entry_points[ep_index as usize].stage, + )?; + writeln!(self.out, "{}}}", back::INDENT)?; + self.write_control_barrier(crate::Barrier::WORK_GROUP, back::Level(1))?; + } + write!(self.out, "{}{nested_name}(", back::INDENT)?; + for (i, arg_name) in arg_names.iter().enumerate() { + if i != 0 { + write!(self.out, ", ")?; + } + write!(self.out, "{arg_name}")?; + } + writeln!(self.out, ");")?; + writeln!( + self.out, + "{}GroupMemoryBarrierWithGroupSync();", + back::INDENT + )?; + + let back::FunctionType::EntryPoint(ep_idx) = func_ctx.ty else { + unreachable!() + }; + let ep = &module.entry_points[ep_idx as usize]; + let mesh_info = ep.mesh_info.as_ref().unwrap(); + let io = self.entry_point_io.get(&(ep_idx as usize)).unwrap(); + + let var_name = &self.names[&NameKey::GlobalVariable(mesh_info.output_variable)]; + let var_type = module.global_variables[mesh_info.output_variable].ty; + let wg_size: u32 = ep.workgroup_size.iter().product(); + + let get_var_member_name = |bi, var_type| { + let TypeInner::Struct { ref members, .. } = module.types[var_type].inner else { + unreachable!() + }; + let idx = members + .iter() + .position(|f| f.binding == Some(crate::Binding::BuiltIn(bi))) + .unwrap(); + self.names[&NameKey::StructMember(var_type, idx as u32)].clone() + }; + + let vert_count = format!( + "{var_name}.{}", + get_var_member_name(crate::BuiltIn::VertexCount, var_type), + ); + let prim_count = format!( + "{var_name}.{}", + get_var_member_name(crate::BuiltIn::PrimitiveCount, var_type), + ); + + let level = back::Level(1); + + writeln!( + self.out, + "{level}SetMeshOutputCounts({vert_count}, {prim_count});" + )?; + + for (array_bi, count, io_interface, is_prim, index_name, ty) in [ + ( + crate::BuiltIn::Vertices, + vert_count, + io.mesh_vertices.as_ref().unwrap(), + false, + "vertIndex", + mesh_info.vertex_output_type, + ), + ( + crate::BuiltIn::Primitives, + prim_count, + io.mesh_primitives.as_ref().unwrap(), + true, + "primIndex", + mesh_info.primitive_output_type, + ), + ] { + let out_var_name = &io_interface.arg_name; + let index_name = self.namer.call(index_name); + let array_name = get_var_member_name(array_bi, var_type); + let item_name = format!("{var_name}.{array_name}[{index_name}]"); + writeln!( + self.out, + "{level}for (int {index_name} = __local_invocation_index; {index_name} < {count}; {index_name} += {}) {{", + wg_size + )?; + { + let level = level.next(); + if is_prim { + let indices_member_name = get_var_member_name( + mesh_info.topology.to_builtin(), + mesh_info.primitive_output_type, + ); + let indices_var_name = &io.mesh_indices.as_ref().unwrap().arg_name; + writeln!( + self.out, + "{level}{indices_var_name}[{index_name}] = {item_name}.{indices_member_name};", + )?; + } + for member in &io_interface.members { + let out_member_name = &member.name; + let in_member_name = + &self.names[&NameKey::StructMember(ty, member.index)]; + writeln!(self.out, "{level}{out_var_name}[{index_name}].{out_member_name} = {item_name}.{in_member_name};",)?; + } + } + writeln!(self.out, "{level}}}")?; + } + // TODO: mesh call and copies + writeln!(self.out, "}}")?; + } else { + writeln!(self.out, ") {{")?; + writeln!( + self.out, + "{}{} = true;", + back::INDENT, + self.task_payload_groupshared_names[&task_payload.unwrap()].2 + )?; + if need_workgroup_variables_initialization { + writeln!( + self.out, + "{}if (all(__local_invocation_index == 0)) {{", + back::INDENT + )?; + self.write_workgroup_variables_initialization( + func_ctx, + module, + module.entry_points[ep_index as usize].stage, + )?; + writeln!(self.out, "{}}}", back::INDENT)?; + self.write_control_barrier(crate::Barrier::WORK_GROUP, back::Level(1))?; + } + let grid_size = self.namer.call("gridSize"); + write!( + self.out, + "{}uint3 {grid_size} = {nested_name}(", + back::INDENT + )?; + for (i, arg_name) in arg_names.iter().enumerate() { + if i != 0 { + write!(self.out, ", ")?; + } + write!(self.out, "{arg_name}")?; + } + writeln!(self.out, ");")?; + writeln!( + self.out, + "{}GroupMemoryBarrierWithGroupSync();", + back::INDENT + )?; + writeln!( + self.out, + "{}DispatchMesh({grid_size}.x, {grid_size}.y, {grid_size}.z, {});", + back::INDENT, + self.names[&NameKey::GlobalVariable(task_payload.unwrap())] + )?; + // TODO: task call and dispatch + writeln!(self.out, "}}")?; + } + } + self.named_expressions.clear(); Ok(()) @@ -1775,7 +2217,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { self.options.zero_initialize_workgroup_memory && func_ctx.ty.is_compute_like_entry_point(module) && module.global_variables.iter().any(|(handle, var)| { - !func_ctx.info[handle].is_empty() && var.space == crate::AddressSpace::WorkGroup + !func_ctx.info[handle].is_empty() && var.space.is_workgroup_like() }) } @@ -1783,27 +2225,27 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { &mut self, func_ctx: &back::FunctionCtx, module: &Module, + stage: ShaderStage, ) -> BackendResult { - let level = back::Level(1); - - writeln!( - self.out, - "{level}if (all(__local_invocation_id == uint3(0u, 0u, 0u))) {{" - )?; - let vars = module.global_variables.iter().filter(|&(handle, var)| { - !func_ctx.info[handle].is_empty() && var.space == crate::AddressSpace::WorkGroup + // Read-only in mesh shaders + let task_needs_zero = + (var.space == crate::AddressSpace::TaskPayload) && stage == ShaderStage::Task; + !func_ctx.info[handle].is_empty() + && (var.space == crate::AddressSpace::WorkGroup || task_needs_zero) }); for (handle, var) in vars { - let name = &self.names[&NameKey::GlobalVariable(handle)]; - write!(self.out, "{}{} = ", level.next(), name)?; + let name = if var.space == crate::AddressSpace::TaskPayload { + &self.task_payload_groupshared_names[&handle].1 + } else { + &self.names[&NameKey::GlobalVariable(handle)] + }; + write!(self.out, "{}{} = ", back::Level(2), name)?; self.write_default_init(module, var.ty)?; writeln!(self.out, ";")?; } - - writeln!(self.out, "{level}}}")?; - self.write_control_barrier(crate::Barrier::WORK_GROUP, level) + Ok(()) } /// Helper method used to write switches @@ -2413,6 +2855,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { result, } => { write!(self.out, "{level}")?; + if let Some(expr) = result { write!(self.out, "const ")?; let name = Baked(expr).to_string(); @@ -2442,7 +2885,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { } self.write_expr(module, *argument, func_ctx)?; } - writeln!(self.out, ");")? + writeln!(self.out, ");")?; } Statement::Atomic { pointer, @@ -3484,6 +3927,11 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { "{}, {}, {}, {}", plane_names[0], plane_names[1], plane_names[2], params_name )?; + } else if global_variable.space == crate::AddressSpace::TaskPayload + && func_ctx.info[handle].contains(valid::GlobalUse::WRITE) + { + let name = &self.task_payload_groupshared_names[&handle].1; + write!(self.out, "{name}")?; } else if !is_binding_array_of_samplers && !is_storage_space { let name = &self.names[&NameKey::GlobalVariable(handle)]; write!(self.out, "{name}")?; diff --git a/naga/src/back/mod.rs b/naga/src/back/mod.rs index 9c9075de69e..6ec5e85c067 100644 --- a/naga/src/back/mod.rs +++ b/naga/src/back/mod.rs @@ -128,6 +128,7 @@ fn get_entry_points( /// [`EntryPoint`]: crate::EntryPoint /// [`Module`]: crate::Module /// [`Module::entry_points`]: crate::Module::entry_points +#[derive(Clone, Copy, Debug)] pub enum FunctionType { /// A regular function. Function(crate::Handle), diff --git a/naga/src/proc/mod.rs b/naga/src/proc/mod.rs index bc1e72e1132..8f5090ac9bc 100644 --- a/naga/src/proc/mod.rs +++ b/naga/src/proc/mod.rs @@ -852,3 +852,19 @@ impl crate::Module { ) } } + +impl crate::MeshOutputTopology { + pub const fn to_builtin(self) -> crate::BuiltIn { + match self { + Self::Points => crate::BuiltIn::PointIndex, + Self::Lines => crate::BuiltIn::LineIndices, + Self::Triangles => crate::BuiltIn::TriangleIndices, + } + } +} + +impl crate::AddressSpace { + pub const fn is_workgroup_like(self) -> bool { + matches!(self, Self::WorkGroup | Self::TaskPayload) + } +} diff --git a/naga/src/valid/analyzer.rs b/naga/src/valid/analyzer.rs index 7f759ee2dc3..92cc2d39786 100644 --- a/naga/src/valid/analyzer.rs +++ b/naga/src/valid/analyzer.rs @@ -269,7 +269,7 @@ pub struct FunctionInfo { /// `FunctionInfo` implements `core::ops::Index>`, /// so you can simply index this struct with a global handle to retrieve /// its usage information. - global_uses: Box<[GlobalUse]>, + pub global_uses: Box<[GlobalUse]>, /// Information about each expression in this function's body. /// diff --git a/naga/tests/in/wgsl/mesh-shader-empty.toml b/naga/tests/in/wgsl/mesh-shader-empty.toml index 148b7004995..24e00ffee54 100644 --- a/naga/tests/in/wgsl/mesh-shader-empty.toml +++ b/naga/tests/in/wgsl/mesh-shader-empty.toml @@ -1,6 +1,9 @@ capabilities = "MESH_SHADER" -targets = "WGSL | SPIRV" +targets = "WGSL | SPIRV | HLSL" [spv] version = [1, 4] capabilities = ["MeshShadingEXT"] + +[hlsl] +shader_model = "V6_5" diff --git a/naga/tests/in/wgsl/mesh-shader-lines.toml b/naga/tests/in/wgsl/mesh-shader-lines.toml index 148b7004995..24e00ffee54 100644 --- a/naga/tests/in/wgsl/mesh-shader-lines.toml +++ b/naga/tests/in/wgsl/mesh-shader-lines.toml @@ -1,6 +1,9 @@ capabilities = "MESH_SHADER" -targets = "WGSL | SPIRV" +targets = "WGSL | SPIRV | HLSL" [spv] version = [1, 4] capabilities = ["MeshShadingEXT"] + +[hlsl] +shader_model = "V6_5" diff --git a/naga/tests/in/wgsl/mesh-shader.toml b/naga/tests/in/wgsl/mesh-shader.toml index 148b7004995..24e00ffee54 100644 --- a/naga/tests/in/wgsl/mesh-shader.toml +++ b/naga/tests/in/wgsl/mesh-shader.toml @@ -1,6 +1,9 @@ capabilities = "MESH_SHADER" -targets = "WGSL | SPIRV" +targets = "WGSL | SPIRV | HLSL" [spv] version = [1, 4] capabilities = ["MeshShadingEXT"] + +[hlsl] +shader_model = "V6_5" diff --git a/naga/tests/in/wgsl/mesh-shader.wgsl b/naga/tests/in/wgsl/mesh-shader.wgsl index ca2f9c911aa..9b57acd10a9 100644 --- a/naga/tests/in/wgsl/mesh-shader.wgsl +++ b/naga/tests/in/wgsl/mesh-shader.wgsl @@ -31,13 +31,21 @@ struct PrimitiveInput { var taskPayload: TaskPayload; var workgroupData: f32; +fn helper_reader() -> bool { + return taskPayload.visible; +} +fn helper_writer(value: bool) { + taskPayload.visible = value; +} + @task @payload(taskPayload) @workgroup_size(1) fn ts_main() -> @builtin(mesh_task_size) vec3 { workgroupData = 1.0; taskPayload.colorMask = vec4(1.0, 1.0, 0.0, 1.0); - taskPayload.visible = true; + helper_writer(true); + taskPayload.visible = helper_reader(); return vec3(1, 1, 1); } @@ -45,8 +53,8 @@ fn ts_main() -> @builtin(mesh_task_size) vec3 { @task @payload(taskPayload) @workgroup_size(2) -fn ts_divergent(@builtin(local_invocation_index) thread_id: u32) -> @builtin(mesh_task_size) vec3 { - if thread_id == 0 { +fn ts_divergent(@builtin(local_invocation_id) thread_id: vec3) -> @builtin(mesh_task_size) vec3 { + if thread_id.x == 0 { taskPayload.colorMask = vec4(1.0, 1.0, 0.0, 1.0); taskPayload.visible = true; return vec3(1, 1, 1); @@ -82,7 +90,7 @@ fn ms_main() { mesh_output.vertices[2].color = colors[2] * taskPayload.colorMask; mesh_output.primitives[0].indices = vec3(0, 1, 2); - mesh_output.primitives[0].cull = !taskPayload.visible; + mesh_output.primitives[0].cull = !helper_reader(); mesh_output.primitives[0].colorMask = vec4(1.0, 0.0, 1.0, 1.0); } @@ -109,9 +117,9 @@ fn ms_no_ts() { // See ts_divergent comment @mesh(mesh_output) -@workgroup_size(1) -fn ms_divergent(@builtin(local_invocation_index) thread_id: u32) { - if thread_id == 0 { +@workgroup_size(2) +fn ms_divergent(@builtin(local_invocation_id) thread_id: vec3) { + if thread_id.x == 0 { mesh_output.vertex_count = 3; mesh_output.primitive_count = 1; workgroupData = 2.0; diff --git a/naga/tests/naga/snapshots.rs b/naga/tests/naga/snapshots.rs index f203a884749..e8c8800e47e 100644 --- a/naga/tests/naga/snapshots.rs +++ b/naga/tests/naga/snapshots.rs @@ -335,7 +335,8 @@ fn write_output_hlsl( naga::ShaderStage::Vertex => &mut config.vertex, naga::ShaderStage::Fragment => &mut config.fragment, naga::ShaderStage::Compute => &mut config.compute, - naga::ShaderStage::Task | naga::ShaderStage::Mesh => unreachable!(), + naga::ShaderStage::Task => &mut config.task, + naga::ShaderStage::Mesh => &mut config.mesh, } .push(hlsl_snapshots::ConfigItem { entry_point: name.clone(), diff --git a/naga/tests/out/hlsl/spv-barrier.ron b/naga/tests/out/hlsl/spv-barrier.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/spv-barrier.ron +++ b/naga/tests/out/hlsl/spv-barrier.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/spv-do-while.ron b/naga/tests/out/hlsl/spv-do-while.ron index 341a4c528e3..403f6c3d24f 100644 --- a/naga/tests/out/hlsl/spv-do-while.ron +++ b/naga/tests/out/hlsl/spv-do-while.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/spv-empty-global-name.ron b/naga/tests/out/hlsl/spv-empty-global-name.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/spv-empty-global-name.ron +++ b/naga/tests/out/hlsl/spv-empty-global-name.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/spv-fetch_depth.ron b/naga/tests/out/hlsl/spv-fetch_depth.ron index 16eac451859..92f9edbb9cf 100644 --- a/naga/tests/out/hlsl/spv-fetch_depth.ron +++ b/naga/tests/out/hlsl/spv-fetch_depth.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/spv-inv-hyperbolic-trig-functions.ron b/naga/tests/out/hlsl/spv-inv-hyperbolic-trig-functions.ron index 341a4c528e3..403f6c3d24f 100644 --- a/naga/tests/out/hlsl/spv-inv-hyperbolic-trig-functions.ron +++ b/naga/tests/out/hlsl/spv-inv-hyperbolic-trig-functions.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/spv-quad-vert.ron b/naga/tests/out/hlsl/spv-quad-vert.ron index 8240856a5c7..8657dfe11d6 100644 --- a/naga/tests/out/hlsl/spv-quad-vert.ron +++ b/naga/tests/out/hlsl/spv-quad-vert.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/spv-subgroup-operations-s.ron b/naga/tests/out/hlsl/spv-subgroup-operations-s.ron index b973fe3da13..afc4b40f24d 100644 --- a/naga/tests/out/hlsl/spv-subgroup-operations-s.ron +++ b/naga/tests/out/hlsl/spv-subgroup-operations-s.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_0", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/spv-unnamed-gl-per-vertex.ron b/naga/tests/out/hlsl/spv-unnamed-gl-per-vertex.ron index 8240856a5c7..8657dfe11d6 100644 --- a/naga/tests/out/hlsl/spv-unnamed-gl-per-vertex.ron +++ b/naga/tests/out/hlsl/spv-unnamed-gl-per-vertex.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-6438-conflicting-idents.ron b/naga/tests/out/hlsl/wgsl-6438-conflicting-idents.ron index 393d3d67479..bb7c047d643 100644 --- a/naga/tests/out/hlsl/wgsl-6438-conflicting-idents.ron +++ b/naga/tests/out/hlsl/wgsl-6438-conflicting-idents.ron @@ -13,4 +13,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-6772-unpack-expr-accesses.ron b/naga/tests/out/hlsl/wgsl-6772-unpack-expr-accesses.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-6772-unpack-expr-accesses.ron +++ b/naga/tests/out/hlsl/wgsl-6772-unpack-expr-accesses.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-7995-unicode-idents.ron b/naga/tests/out/hlsl/wgsl-7995-unicode-idents.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-7995-unicode-idents.ron +++ b/naga/tests/out/hlsl/wgsl-7995-unicode-idents.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-abstract-types-return.ron b/naga/tests/out/hlsl/wgsl-abstract-types-return.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-abstract-types-return.ron +++ b/naga/tests/out/hlsl/wgsl-abstract-types-return.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-access.ron b/naga/tests/out/hlsl/wgsl-access.ron index d9ef3e5588b..ab50d868212 100644 --- a/naga/tests/out/hlsl/wgsl-access.ron +++ b/naga/tests/out/hlsl/wgsl-access.ron @@ -17,4 +17,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-aliased-ray-query.ron b/naga/tests/out/hlsl/wgsl-aliased-ray-query.ron index 7e97e82d38c..13a055d54fa 100644 --- a/naga/tests/out/hlsl/wgsl-aliased-ray-query.ron +++ b/naga/tests/out/hlsl/wgsl-aliased-ray-query.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_5", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-array-in-ctor.ron b/naga/tests/out/hlsl/wgsl-array-in-ctor.ron index 5c261e59b26..84bfcfec896 100644 --- a/naga/tests/out/hlsl/wgsl-array-in-ctor.ron +++ b/naga/tests/out/hlsl/wgsl-array-in-ctor.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-array-in-function-return-type.ron b/naga/tests/out/hlsl/wgsl-array-in-function-return-type.ron index 341a4c528e3..403f6c3d24f 100644 --- a/naga/tests/out/hlsl/wgsl-array-in-function-return-type.ron +++ b/naga/tests/out/hlsl/wgsl-array-in-function-return-type.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-atomicCompareExchange-int64.ron b/naga/tests/out/hlsl/wgsl-atomicCompareExchange-int64.ron index b7059590b48..430e723d08b 100644 --- a/naga/tests/out/hlsl/wgsl-atomicCompareExchange-int64.ron +++ b/naga/tests/out/hlsl/wgsl-atomicCompareExchange-int64.ron @@ -13,4 +13,8 @@ target_profile:"cs_6_6", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-atomicCompareExchange.ron b/naga/tests/out/hlsl/wgsl-atomicCompareExchange.ron index 70f4fcb3d14..e9785b7bd17 100644 --- a/naga/tests/out/hlsl/wgsl-atomicCompareExchange.ron +++ b/naga/tests/out/hlsl/wgsl-atomicCompareExchange.ron @@ -13,4 +13,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-atomicOps-int64-min-max.ron b/naga/tests/out/hlsl/wgsl-atomicOps-int64-min-max.ron index 67a90355123..e192e09a432 100644 --- a/naga/tests/out/hlsl/wgsl-atomicOps-int64-min-max.ron +++ b/naga/tests/out/hlsl/wgsl-atomicOps-int64-min-max.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_6", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-atomicOps-int64.hlsl b/naga/tests/out/hlsl/wgsl-atomicOps-int64.hlsl index eaebd0f591f..8e6692d972a 100644 --- a/naga/tests/out/hlsl/wgsl-atomicOps-int64.hlsl +++ b/naga/tests/out/hlsl/wgsl-atomicOps-int64.hlsl @@ -30,9 +30,9 @@ groupshared int64_t workgroup_atomic_arr[2]; groupshared Struct workgroup_struct; [numthreads(2, 1, 1)] -void cs_main(uint3 id : SV_GroupThreadID, uint3 __local_invocation_id : SV_GroupThreadID) +void cs_main(uint3 id : SV_GroupThreadID, uint __local_invocation_index : SV_GroupIndex) { - if (all(__local_invocation_id == uint3(0u, 0u, 0u))) { + if (all(__local_invocation_index == 0)) { workgroup_atomic_scalar = (uint64_t)0; workgroup_atomic_arr = (int64_t[2])0; workgroup_struct = (Struct)0; diff --git a/naga/tests/out/hlsl/wgsl-atomicOps-int64.ron b/naga/tests/out/hlsl/wgsl-atomicOps-int64.ron index 67a90355123..e192e09a432 100644 --- a/naga/tests/out/hlsl/wgsl-atomicOps-int64.ron +++ b/naga/tests/out/hlsl/wgsl-atomicOps-int64.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_6", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-atomicOps.hlsl b/naga/tests/out/hlsl/wgsl-atomicOps.hlsl index d32d953a18c..3378a0579de 100644 --- a/naga/tests/out/hlsl/wgsl-atomicOps.hlsl +++ b/naga/tests/out/hlsl/wgsl-atomicOps.hlsl @@ -21,9 +21,9 @@ groupshared int workgroup_atomic_arr[2]; groupshared Struct workgroup_struct; [numthreads(2, 1, 1)] -void cs_main(uint3 id : SV_GroupThreadID, uint3 __local_invocation_id : SV_GroupThreadID) +void cs_main(uint3 id : SV_GroupThreadID, uint __local_invocation_index : SV_GroupIndex) { - if (all(__local_invocation_id == uint3(0u, 0u, 0u))) { + if (all(__local_invocation_index == 0)) { workgroup_atomic_scalar = (uint)0; workgroup_atomic_arr = (int[2])0; workgroup_struct = (Struct)0; diff --git a/naga/tests/out/hlsl/wgsl-atomicOps.ron b/naga/tests/out/hlsl/wgsl-atomicOps.ron index 5c261e59b26..84bfcfec896 100644 --- a/naga/tests/out/hlsl/wgsl-atomicOps.ron +++ b/naga/tests/out/hlsl/wgsl-atomicOps.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-atomicTexture-int64.ron b/naga/tests/out/hlsl/wgsl-atomicTexture-int64.ron index 67a90355123..e192e09a432 100644 --- a/naga/tests/out/hlsl/wgsl-atomicTexture-int64.ron +++ b/naga/tests/out/hlsl/wgsl-atomicTexture-int64.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_6", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-atomicTexture.ron b/naga/tests/out/hlsl/wgsl-atomicTexture.ron index 5c261e59b26..84bfcfec896 100644 --- a/naga/tests/out/hlsl/wgsl-atomicTexture.ron +++ b/naga/tests/out/hlsl/wgsl-atomicTexture.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-barycentrics.ron b/naga/tests/out/hlsl/wgsl-barycentrics.ron index 9ed6bdee58d..5e303e721c8 100644 --- a/naga/tests/out/hlsl/wgsl-barycentrics.ron +++ b/naga/tests/out/hlsl/wgsl-barycentrics.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-binding-arrays.ron b/naga/tests/out/hlsl/wgsl-binding-arrays.ron index 341a4c528e3..403f6c3d24f 100644 --- a/naga/tests/out/hlsl/wgsl-binding-arrays.ron +++ b/naga/tests/out/hlsl/wgsl-binding-arrays.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-bitcast.ron b/naga/tests/out/hlsl/wgsl-bitcast.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-bitcast.ron +++ b/naga/tests/out/hlsl/wgsl-bitcast.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-bits.ron b/naga/tests/out/hlsl/wgsl-bits.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-bits.ron +++ b/naga/tests/out/hlsl/wgsl-bits.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-boids.ron b/naga/tests/out/hlsl/wgsl-boids.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-boids.ron +++ b/naga/tests/out/hlsl/wgsl-boids.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-bounds-check-dynamic-buffer.ron b/naga/tests/out/hlsl/wgsl-bounds-check-dynamic-buffer.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-bounds-check-dynamic-buffer.ron +++ b/naga/tests/out/hlsl/wgsl-bounds-check-dynamic-buffer.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-break-if.ron b/naga/tests/out/hlsl/wgsl-break-if.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-break-if.ron +++ b/naga/tests/out/hlsl/wgsl-break-if.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-collatz.ron b/naga/tests/out/hlsl/wgsl-collatz.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-collatz.ron +++ b/naga/tests/out/hlsl/wgsl-collatz.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-const-exprs.ron b/naga/tests/out/hlsl/wgsl-const-exprs.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-const-exprs.ron +++ b/naga/tests/out/hlsl/wgsl-const-exprs.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-constructors.ron b/naga/tests/out/hlsl/wgsl-constructors.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-constructors.ron +++ b/naga/tests/out/hlsl/wgsl-constructors.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-control-flow.ron b/naga/tests/out/hlsl/wgsl-control-flow.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-control-flow.ron +++ b/naga/tests/out/hlsl/wgsl-control-flow.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-conversion-float-to-int.ron b/naga/tests/out/hlsl/wgsl-conversion-float-to-int.ron index b973fe3da13..afc4b40f24d 100644 --- a/naga/tests/out/hlsl/wgsl-conversion-float-to-int.ron +++ b/naga/tests/out/hlsl/wgsl-conversion-float-to-int.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_0", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-conversions.ron b/naga/tests/out/hlsl/wgsl-conversions.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-conversions.ron +++ b/naga/tests/out/hlsl/wgsl-conversions.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-cross.ron b/naga/tests/out/hlsl/wgsl-cross.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-cross.ron +++ b/naga/tests/out/hlsl/wgsl-cross.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-dualsource.ron b/naga/tests/out/hlsl/wgsl-dualsource.ron index 341a4c528e3..403f6c3d24f 100644 --- a/naga/tests/out/hlsl/wgsl-dualsource.ron +++ b/naga/tests/out/hlsl/wgsl-dualsource.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-empty-if.ron b/naga/tests/out/hlsl/wgsl-empty-if.ron index 03fe98f84cd..f6df37629d6 100644 --- a/naga/tests/out/hlsl/wgsl-empty-if.ron +++ b/naga/tests/out/hlsl/wgsl-empty-if.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-empty.ron b/naga/tests/out/hlsl/wgsl-empty.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-empty.ron +++ b/naga/tests/out/hlsl/wgsl-empty.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-f16.ron b/naga/tests/out/hlsl/wgsl-f16.ron index b396a4626e3..ea04bf30313 100644 --- a/naga/tests/out/hlsl/wgsl-f16.ron +++ b/naga/tests/out/hlsl/wgsl-f16.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_2", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-f64.ron b/naga/tests/out/hlsl/wgsl-f64.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-f64.ron +++ b/naga/tests/out/hlsl/wgsl-f64.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-fragment-output.ron b/naga/tests/out/hlsl/wgsl-fragment-output.ron index 9dfaf7393b0..ab90a7a9891 100644 --- a/naga/tests/out/hlsl/wgsl-fragment-output.ron +++ b/naga/tests/out/hlsl/wgsl-fragment-output.ron @@ -13,4 +13,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-functions-optimized-by-version.ron b/naga/tests/out/hlsl/wgsl-functions-optimized-by-version.ron index 81f3e9b2950..81fdf5a31b9 100644 --- a/naga/tests/out/hlsl/wgsl-functions-optimized-by-version.ron +++ b/naga/tests/out/hlsl/wgsl-functions-optimized-by-version.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_4", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-functions-unoptimized.ron b/naga/tests/out/hlsl/wgsl-functions-unoptimized.ron index f1f510d2dca..d47996c692e 100644 --- a/naga/tests/out/hlsl/wgsl-functions-unoptimized.ron +++ b/naga/tests/out/hlsl/wgsl-functions-unoptimized.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_3", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-functions.ron b/naga/tests/out/hlsl/wgsl-functions.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-functions.ron +++ b/naga/tests/out/hlsl/wgsl-functions.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-globals.hlsl b/naga/tests/out/hlsl/wgsl-globals.hlsl index af2951a334a..8d7c3b6f363 100644 --- a/naga/tests/out/hlsl/wgsl-globals.hlsl +++ b/naga/tests/out/hlsl/wgsl-globals.hlsl @@ -110,9 +110,9 @@ uint NagaBufferLength(ByteAddressBuffer buffer) } [numthreads(1, 1, 1)] -void main(uint3 __local_invocation_id : SV_GroupThreadID) +void main(uint __local_invocation_index : SV_GroupIndex) { - if (all(__local_invocation_id == uint3(0u, 0u, 0u))) { + if (all(__local_invocation_index == 0)) { wg = (float[10])0; at_1 = (uint)0; } diff --git a/naga/tests/out/hlsl/wgsl-globals.ron b/naga/tests/out/hlsl/wgsl-globals.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-globals.ron +++ b/naga/tests/out/hlsl/wgsl-globals.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-hlsl-keyword.ron b/naga/tests/out/hlsl/wgsl-hlsl-keyword.ron index eac1b945d2b..a0b1fa2b7ea 100644 --- a/naga/tests/out/hlsl/wgsl-hlsl-keyword.ron +++ b/naga/tests/out/hlsl/wgsl-hlsl-keyword.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-hlsl_mat_cx2.ron b/naga/tests/out/hlsl/wgsl-hlsl_mat_cx2.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-hlsl_mat_cx2.ron +++ b/naga/tests/out/hlsl/wgsl-hlsl_mat_cx2.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-hlsl_mat_cx3.ron b/naga/tests/out/hlsl/wgsl-hlsl_mat_cx3.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-hlsl_mat_cx3.ron +++ b/naga/tests/out/hlsl/wgsl-hlsl_mat_cx3.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-image.ron b/naga/tests/out/hlsl/wgsl-image.ron index f5ca4931d46..aa50ddedb0b 100644 --- a/naga/tests/out/hlsl/wgsl-image.ron +++ b/naga/tests/out/hlsl/wgsl-image.ron @@ -37,4 +37,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-int64.ron b/naga/tests/out/hlsl/wgsl-int64.ron index b973fe3da13..afc4b40f24d 100644 --- a/naga/tests/out/hlsl/wgsl-int64.ron +++ b/naga/tests/out/hlsl/wgsl-int64.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_0", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-interface.hlsl b/naga/tests/out/hlsl/wgsl-interface.hlsl index 6187ca09748..6311b54d18f 100644 --- a/naga/tests/out/hlsl/wgsl-interface.hlsl +++ b/naga/tests/out/hlsl/wgsl-interface.hlsl @@ -75,9 +75,9 @@ FragmentOutput fragment(FragmentInput_fragment fragmentinput_fragment) } [numthreads(1, 1, 1)] -void compute(uint3 global_id : SV_DispatchThreadID, uint3 local_id : SV_GroupThreadID, uint local_index : SV_GroupIndex, uint3 wg_id : SV_GroupID, uint3 num_wgs : SV_GroupID, uint3 __local_invocation_id : SV_GroupThreadID) +void compute(uint3 global_id : SV_DispatchThreadID, uint3 local_id : SV_GroupThreadID, uint local_index : SV_GroupIndex, uint3 wg_id : SV_GroupID, uint3 num_wgs : SV_GroupID, uint __local_invocation_index : SV_GroupIndex) { - if (all(__local_invocation_id == uint3(0u, 0u, 0u))) { + if (all(__local_invocation_index == 0)) { output = (uint[1])0; } GroupMemoryBarrierWithGroupSync(); diff --git a/naga/tests/out/hlsl/wgsl-interface.ron b/naga/tests/out/hlsl/wgsl-interface.ron index 948962b9917..fa8774ba24c 100644 --- a/naga/tests/out/hlsl/wgsl-interface.ron +++ b/naga/tests/out/hlsl/wgsl-interface.ron @@ -21,4 +21,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-interpolate.ron b/naga/tests/out/hlsl/wgsl-interpolate.ron index d0046b04dd3..8c6fc532a04 100644 --- a/naga/tests/out/hlsl/wgsl-interpolate.ron +++ b/naga/tests/out/hlsl/wgsl-interpolate.ron @@ -13,4 +13,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-interpolate_compat.ron b/naga/tests/out/hlsl/wgsl-interpolate_compat.ron index d0046b04dd3..8c6fc532a04 100644 --- a/naga/tests/out/hlsl/wgsl-interpolate_compat.ron +++ b/naga/tests/out/hlsl/wgsl-interpolate_compat.ron @@ -13,4 +13,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-math-functions.ron b/naga/tests/out/hlsl/wgsl-math-functions.ron index 341a4c528e3..403f6c3d24f 100644 --- a/naga/tests/out/hlsl/wgsl-math-functions.ron +++ b/naga/tests/out/hlsl/wgsl-math-functions.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-mesh-shader-empty.hlsl b/naga/tests/out/hlsl/wgsl-mesh-shader-empty.hlsl new file mode 100644 index 00000000000..4325bdc6fae --- /dev/null +++ b/naga/tests/out/hlsl/wgsl-mesh-shader-empty.hlsl @@ -0,0 +1,71 @@ +struct TaskPayload { + uint dummy; +}; + +struct VertexOutput { + float4 position : SV_Position; +}; + +struct PrimitiveOutput { + uint3 indices_; +}; + +struct MeshOutput { + VertexOutput vertices_[3]; + PrimitiveOutput primitives_[1]; + uint vertex_count; + uint primitive_count; +}; + +static TaskPayload taskPayloadStatic; +groupshared TaskPayload taskPayloadShared; +static bool taskPayloadIsShared; +#define taskPayload (taskPayloadIsShared ? taskPayloadShared : taskPayloadStatic) +groupshared MeshOutput mesh_output; + +struct MeshVertexOutput_ms_main { + float4 position : SV_Position; +}; + +struct MeshPrimitiveOutput_ms_main { +}; + +uint3 _ts_main(uint __local_invocation_index) +{ + return uint3(1u, 1u, 1u); +} +[numthreads(1, 1, 1)] +void ts_main(uint __local_invocation_index : SV_GroupIndex) { + taskPayloadIsShared = true; + if (all(__local_invocation_index == 0)) { + taskPayloadShared = (TaskPayload)0; + } + GroupMemoryBarrierWithGroupSync(); + uint3 gridSize = _ts_main(__local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + DispatchMesh(gridSize.x, gridSize.y, gridSize.z, taskPayload); +} + +void _ms_main(uint __local_invocation_index) +{ + return; +} +[numthreads(1, 1, 1)] +[outputtopology("triangle")] +void ms_main(uint __local_invocation_index : SV_GroupIndex, out indices uint3 triangleIndices[1], out vertices MeshVertexOutput_ms_main vertices_[3], out primitives MeshPrimitiveOutput_ms_main primitives_[1], in payload TaskPayload _taskPayload) { + taskPayloadIsShared = false; + taskPayloadStatic = _taskPayload; + if (all(__local_invocation_index == 0)) { + mesh_output = (MeshOutput)0; + } + GroupMemoryBarrierWithGroupSync(); + _ms_main(__local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + SetMeshOutputCounts(mesh_output.vertex_count, mesh_output.primitive_count); + for (int vertIndex = __local_invocation_index; vertIndex < mesh_output.vertex_count; vertIndex += 1) { + vertices_[vertIndex].position = mesh_output.vertices_[vertIndex].position; + } + for (int primIndex = __local_invocation_index; primIndex < mesh_output.primitive_count; primIndex += 1) { + triangleIndices[primIndex] = mesh_output.primitives_[primIndex].indices_; + } +} diff --git a/naga/tests/out/hlsl/wgsl-mesh-shader-empty.ron b/naga/tests/out/hlsl/wgsl-mesh-shader-empty.ron new file mode 100644 index 00000000000..8156a7a68d2 --- /dev/null +++ b/naga/tests/out/hlsl/wgsl-mesh-shader-empty.ron @@ -0,0 +1,20 @@ +( + vertex:[ + ], + fragment:[ + ], + compute:[ + ], + task:[ + ( + entry_point:"ts_main", + target_profile:"as_6_5", + ), + ], + mesh:[ + ( + entry_point:"ms_main", + target_profile:"ms_6_5", + ), + ], +) diff --git a/naga/tests/out/hlsl/wgsl-mesh-shader-lines.hlsl b/naga/tests/out/hlsl/wgsl-mesh-shader-lines.hlsl new file mode 100644 index 00000000000..d476aa4e7d2 --- /dev/null +++ b/naga/tests/out/hlsl/wgsl-mesh-shader-lines.hlsl @@ -0,0 +1,71 @@ +struct TaskPayload { + uint dummy; +}; + +struct VertexOutput { + float4 position : SV_Position; +}; + +struct PrimitiveOutput { + uint2 indices_; +}; + +struct MeshOutput { + VertexOutput vertices_[2]; + PrimitiveOutput primitives_[1]; + uint vertex_count; + uint primitive_count; +}; + +static TaskPayload taskPayloadStatic; +groupshared TaskPayload taskPayloadShared; +static bool taskPayloadIsShared; +#define taskPayload (taskPayloadIsShared ? taskPayloadShared : taskPayloadStatic) +groupshared MeshOutput mesh_output; + +struct MeshVertexOutput_ms_main { + float4 position : SV_Position; +}; + +struct MeshPrimitiveOutput_ms_main { +}; + +uint3 _ts_main(uint __local_invocation_index) +{ + return uint3(1u, 1u, 1u); +} +[numthreads(1, 1, 1)] +void ts_main(uint __local_invocation_index : SV_GroupIndex) { + taskPayloadIsShared = true; + if (all(__local_invocation_index == 0)) { + taskPayloadShared = (TaskPayload)0; + } + GroupMemoryBarrierWithGroupSync(); + uint3 gridSize = _ts_main(__local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + DispatchMesh(gridSize.x, gridSize.y, gridSize.z, taskPayload); +} + +void _ms_main(uint __local_invocation_index) +{ + return; +} +[numthreads(1, 1, 1)] +[outputtopology("line")] +void ms_main(uint __local_invocation_index : SV_GroupIndex, out indices uint2 lineIndices[1], out vertices MeshVertexOutput_ms_main vertices_[2], out primitives MeshPrimitiveOutput_ms_main primitives_[1], in payload TaskPayload _taskPayload) { + taskPayloadIsShared = false; + taskPayloadStatic = _taskPayload; + if (all(__local_invocation_index == 0)) { + mesh_output = (MeshOutput)0; + } + GroupMemoryBarrierWithGroupSync(); + _ms_main(__local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + SetMeshOutputCounts(mesh_output.vertex_count, mesh_output.primitive_count); + for (int vertIndex = __local_invocation_index; vertIndex < mesh_output.vertex_count; vertIndex += 1) { + vertices_[vertIndex].position = mesh_output.vertices_[vertIndex].position; + } + for (int primIndex = __local_invocation_index; primIndex < mesh_output.primitive_count; primIndex += 1) { + lineIndices[primIndex] = mesh_output.primitives_[primIndex].indices_; + } +} diff --git a/naga/tests/out/hlsl/wgsl-mesh-shader-lines.ron b/naga/tests/out/hlsl/wgsl-mesh-shader-lines.ron new file mode 100644 index 00000000000..8156a7a68d2 --- /dev/null +++ b/naga/tests/out/hlsl/wgsl-mesh-shader-lines.ron @@ -0,0 +1,20 @@ +( + vertex:[ + ], + fragment:[ + ], + compute:[ + ], + task:[ + ( + entry_point:"ts_main", + target_profile:"as_6_5", + ), + ], + mesh:[ + ( + entry_point:"ms_main", + target_profile:"ms_6_5", + ), + ], +) diff --git a/naga/tests/out/hlsl/wgsl-mesh-shader.hlsl b/naga/tests/out/hlsl/wgsl-mesh-shader.hlsl new file mode 100644 index 00000000000..764b200ff95 --- /dev/null +++ b/naga/tests/out/hlsl/wgsl-mesh-shader.hlsl @@ -0,0 +1,258 @@ +struct TaskPayload { + float4 colorMask; + bool visible; + int _end_pad_0; + int _end_pad_1; + int _end_pad_2; +}; + +struct VertexOutput { + float4 position : SV_Position; + float4 color : LOC0; +}; + +struct PrimitiveOutput { + uint3 indices_; + bool cull : SV_CullPrimitive; + float4 colorMask : LOC1 : primitive; +}; + +struct PrimitiveInput { + float4 colorMask : LOC1 : primitive; +}; + +struct MeshOutput { + VertexOutput vertices_[3]; + PrimitiveOutput primitives_[1]; + uint vertex_count; + uint primitive_count; +}; + +static TaskPayload taskPayloadStatic; +groupshared TaskPayload taskPayloadShared; +static bool taskPayloadIsShared; +#define taskPayload (taskPayloadIsShared ? taskPayloadShared : taskPayloadStatic) +groupshared float workgroupData; +groupshared MeshOutput mesh_output; + +struct MeshVertexOutput_ms_main { + float4 color : LOC0; + float4 position : SV_Position; +}; + +struct MeshPrimitiveOutput_ms_main { + float4 colorMask : LOC1 : primitive; + bool cull : SV_CullPrimitive; +}; + +struct MeshVertexOutput_ms_no_ts { + float4 color_1 : LOC0; + float4 position_1 : SV_Position; +}; + +struct MeshPrimitiveOutput_ms_no_ts { + float4 colorMask_1 : LOC1 : primitive; + bool cull_1 : SV_CullPrimitive; +}; + +struct MeshVertexOutput_ms_divergent { + float4 color_2 : LOC0; + float4 position_2 : SV_Position; +}; + +struct MeshPrimitiveOutput_ms_divergent { + float4 colorMask_2 : LOC1 : primitive; + bool cull_2 : SV_CullPrimitive; +}; + +struct FragmentInput_fs_main { + float4 color_3 : LOC0; + float4 colorMask_3 : LOC1 : primitive; + float4 position_3 : SV_Position; +}; + +bool helper_reader() +{ + bool _e2 = taskPayload.visible; + return _e2; +} + +void helper_writer(bool value) +{ + taskPayloadShared.visible = value; + return; +} + +uint3 _ts_main(uint __local_invocation_index) +{ + workgroupData = 1.0; + taskPayloadShared.colorMask = float4(1.0, 1.0, 0.0, 1.0); + helper_writer(true); + const bool _e12 = helper_reader(); + taskPayloadShared.visible = _e12; + return uint3(1u, 1u, 1u); +} +[numthreads(1, 1, 1)] +void ts_main(uint __local_invocation_index : SV_GroupIndex) { + taskPayloadIsShared = true; + if (all(__local_invocation_index == 0)) { + taskPayloadShared = (TaskPayload)0; + workgroupData = (float)0; + } + GroupMemoryBarrierWithGroupSync(); + uint3 gridSize = _ts_main(__local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + DispatchMesh(gridSize.x, gridSize.y, gridSize.z, taskPayload); +} + +uint3 _ts_divergent(uint3 thread_id : SV_GroupThreadID, uint __local_invocation_index) +{ + if ((thread_id.x == 0u)) { + taskPayloadShared.colorMask = float4(1.0, 1.0, 0.0, 1.0); + taskPayloadShared.visible = true; + return uint3(1u, 1u, 1u); + } + return uint3(2u, 2u, 2u); +} +[numthreads(2, 1, 1)] +void ts_divergent(uint3 thread_id : SV_GroupThreadID, uint __local_invocation_index : SV_GroupIndex) { + taskPayloadIsShared = true; + if (all(__local_invocation_index == 0)) { + taskPayloadShared = (TaskPayload)0; + } + GroupMemoryBarrierWithGroupSync(); + uint3 gridSize_1 = _ts_divergent(thread_id, __local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + DispatchMesh(gridSize_1.x, gridSize_1.y, gridSize_1.z, taskPayload); +} + +void _ms_main(uint __local_invocation_index) +{ + mesh_output.vertex_count = 3u; + mesh_output.primitive_count = 1u; + workgroupData = 2.0; + mesh_output.vertices_[0].position = float4(0.0, 1.0, 0.0, 1.0); + float4 _e23 = taskPayload.colorMask; + mesh_output.vertices_[0].color = (float4(0.0, 1.0, 0.0, 1.0) * _e23); + mesh_output.vertices_[1].position = float4(-1.0, -1.0, 0.0, 1.0); + float4 _e45 = taskPayload.colorMask; + mesh_output.vertices_[1].color = (float4(0.0, 0.0, 1.0, 1.0) * _e45); + mesh_output.vertices_[2].position = float4(1.0, -1.0, 0.0, 1.0); + float4 _e67 = taskPayload.colorMask; + mesh_output.vertices_[2].color = (float4(1.0, 0.0, 0.0, 1.0) * _e67); + mesh_output.primitives_[0].indices_ = uint3(0u, 1u, 2u); + const bool _e86 = helper_reader(); + mesh_output.primitives_[0].cull = !(_e86); + mesh_output.primitives_[0].colorMask = float4(1.0, 0.0, 1.0, 1.0); + return; +} +[numthreads(1, 1, 1)] +[outputtopology("triangle")] +void ms_main(uint __local_invocation_index : SV_GroupIndex, out indices uint3 triangleIndices[1], out vertices MeshVertexOutput_ms_main vertices_[3], out primitives MeshPrimitiveOutput_ms_main primitives_[1], in payload TaskPayload _taskPayload) { + taskPayloadIsShared = false; + taskPayloadStatic = _taskPayload; + if (all(__local_invocation_index == 0)) { + workgroupData = (float)0; + mesh_output = (MeshOutput)0; + } + GroupMemoryBarrierWithGroupSync(); + _ms_main(__local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + SetMeshOutputCounts(mesh_output.vertex_count, mesh_output.primitive_count); + for (int vertIndex = __local_invocation_index; vertIndex < mesh_output.vertex_count; vertIndex += 1) { + vertices_[vertIndex].color = mesh_output.vertices_[vertIndex].color; + vertices_[vertIndex].position = mesh_output.vertices_[vertIndex].position; + } + for (int primIndex = __local_invocation_index; primIndex < mesh_output.primitive_count; primIndex += 1) { + triangleIndices[primIndex] = mesh_output.primitives_[primIndex].indices_; + primitives_[primIndex].colorMask = mesh_output.primitives_[primIndex].colorMask; + primitives_[primIndex].cull = mesh_output.primitives_[primIndex].cull; + } +} + +void _ms_no_ts(uint __local_invocation_index) +{ + mesh_output.vertex_count = 3u; + mesh_output.primitive_count = 1u; + workgroupData = 2.0; + mesh_output.vertices_[0].position = float4(0.0, 1.0, 0.0, 1.0); + mesh_output.vertices_[0].color = float4(0.0, 1.0, 0.0, 1.0); + mesh_output.vertices_[1].position = float4(-1.0, -1.0, 0.0, 1.0); + mesh_output.vertices_[1].color = float4(0.0, 0.0, 1.0, 1.0); + mesh_output.vertices_[2].position = float4(1.0, -1.0, 0.0, 1.0); + mesh_output.vertices_[2].color = float4(1.0, 0.0, 0.0, 1.0); + mesh_output.primitives_[0].indices_ = uint3(0u, 1u, 2u); + mesh_output.primitives_[0].cull = false; + mesh_output.primitives_[0].colorMask = float4(1.0, 0.0, 1.0, 1.0); + return; +} +[numthreads(1, 1, 1)] +[outputtopology("triangle")] +void ms_no_ts(uint __local_invocation_index : SV_GroupIndex, out indices uint3 triangleIndices_1[1], out vertices MeshVertexOutput_ms_no_ts vertices_1[3], out primitives MeshPrimitiveOutput_ms_no_ts primitives_1[1]) { + if (all(__local_invocation_index == 0)) { + workgroupData = (float)0; + mesh_output = (MeshOutput)0; + } + GroupMemoryBarrierWithGroupSync(); + _ms_no_ts(__local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + SetMeshOutputCounts(mesh_output.vertex_count, mesh_output.primitive_count); + for (int vertIndex_1 = __local_invocation_index; vertIndex_1 < mesh_output.vertex_count; vertIndex_1 += 1) { + vertices_1[vertIndex_1].color_1 = mesh_output.vertices_[vertIndex_1].color; + vertices_1[vertIndex_1].position_1 = mesh_output.vertices_[vertIndex_1].position; + } + for (int primIndex_1 = __local_invocation_index; primIndex_1 < mesh_output.primitive_count; primIndex_1 += 1) { + triangleIndices_1[primIndex_1] = mesh_output.primitives_[primIndex_1].indices_; + primitives_1[primIndex_1].colorMask_1 = mesh_output.primitives_[primIndex_1].colorMask; + primitives_1[primIndex_1].cull_1 = mesh_output.primitives_[primIndex_1].cull; + } +} + +void _ms_divergent(uint3 thread_id_1 : SV_GroupThreadID, uint __local_invocation_index) +{ + if ((thread_id_1.x == 0u)) { + mesh_output.vertex_count = 3u; + mesh_output.primitive_count = 1u; + workgroupData = 2.0; + mesh_output.vertices_[0].position = float4(0.0, 1.0, 0.0, 1.0); + mesh_output.vertices_[0].color = float4(0.0, 1.0, 0.0, 1.0); + mesh_output.vertices_[1].position = float4(-1.0, -1.0, 0.0, 1.0); + mesh_output.vertices_[1].color = float4(0.0, 0.0, 1.0, 1.0); + mesh_output.vertices_[2].position = float4(1.0, -1.0, 0.0, 1.0); + mesh_output.vertices_[2].color = float4(1.0, 0.0, 0.0, 1.0); + mesh_output.primitives_[0].indices_ = uint3(0u, 1u, 2u); + mesh_output.primitives_[0].cull = false; + mesh_output.primitives_[0].colorMask = float4(1.0, 0.0, 1.0, 1.0); + return; + } else { + return; + } +} +[numthreads(2, 1, 1)] +[outputtopology("triangle")] +void ms_divergent(uint3 thread_id_1 : SV_GroupThreadID, uint __local_invocation_index : SV_GroupIndex, out indices uint3 triangleIndices_2[1], out vertices MeshVertexOutput_ms_divergent vertices_2[3], out primitives MeshPrimitiveOutput_ms_divergent primitives_2[1]) { + if (all(__local_invocation_index == 0)) { + workgroupData = (float)0; + mesh_output = (MeshOutput)0; + } + GroupMemoryBarrierWithGroupSync(); + _ms_divergent(thread_id_1, __local_invocation_index); + GroupMemoryBarrierWithGroupSync(); + SetMeshOutputCounts(mesh_output.vertex_count, mesh_output.primitive_count); + for (int vertIndex_2 = __local_invocation_index; vertIndex_2 < mesh_output.vertex_count; vertIndex_2 += 2) { + vertices_2[vertIndex_2].color_2 = mesh_output.vertices_[vertIndex_2].color; + vertices_2[vertIndex_2].position_2 = mesh_output.vertices_[vertIndex_2].position; + } + for (int primIndex_2 = __local_invocation_index; primIndex_2 < mesh_output.primitive_count; primIndex_2 += 2) { + triangleIndices_2[primIndex_2] = mesh_output.primitives_[primIndex_2].indices_; + primitives_2[primIndex_2].colorMask_2 = mesh_output.primitives_[primIndex_2].colorMask; + primitives_2[primIndex_2].cull_2 = mesh_output.primitives_[primIndex_2].cull; + } +} + +float4 fs_main(FragmentInput_fs_main fragmentinput_fs_main) : SV_Target0 +{ + VertexOutput vertex = { fragmentinput_fs_main.position_3, fragmentinput_fs_main.color_3 }; + PrimitiveInput primitive = { fragmentinput_fs_main.colorMask_3 }; + return (vertex.color * primitive.colorMask); +} diff --git a/naga/tests/out/hlsl/wgsl-mesh-shader.ron b/naga/tests/out/hlsl/wgsl-mesh-shader.ron new file mode 100644 index 00000000000..0f1c159ff3b --- /dev/null +++ b/naga/tests/out/hlsl/wgsl-mesh-shader.ron @@ -0,0 +1,36 @@ +( + vertex:[ + ], + fragment:[ + ( + entry_point:"fs_main", + target_profile:"ps_6_5", + ), + ], + compute:[ + ], + task:[ + ( + entry_point:"ts_main", + target_profile:"as_6_5", + ), + ( + entry_point:"ts_divergent", + target_profile:"as_6_5", + ), + ], + mesh:[ + ( + entry_point:"ms_main", + target_profile:"ms_6_5", + ), + ( + entry_point:"ms_no_ts", + target_profile:"ms_6_5", + ), + ( + entry_point:"ms_divergent", + target_profile:"ms_6_5", + ), + ], +) diff --git a/naga/tests/out/hlsl/wgsl-multiview.ron b/naga/tests/out/hlsl/wgsl-multiview.ron index ff856788943..ea2a04cd8ff 100644 --- a/naga/tests/out/hlsl/wgsl-multiview.ron +++ b/naga/tests/out/hlsl/wgsl-multiview.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-operators.ron b/naga/tests/out/hlsl/wgsl-operators.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-operators.ron +++ b/naga/tests/out/hlsl/wgsl-operators.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-overrides.ron b/naga/tests/out/hlsl/wgsl-overrides.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-overrides.ron +++ b/naga/tests/out/hlsl/wgsl-overrides.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-padding.ron b/naga/tests/out/hlsl/wgsl-padding.ron index 46dfdd83e30..7a49d875af0 100644 --- a/naga/tests/out/hlsl/wgsl-padding.ron +++ b/naga/tests/out/hlsl/wgsl-padding.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-phony_assignment.ron b/naga/tests/out/hlsl/wgsl-phony_assignment.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-phony_assignment.ron +++ b/naga/tests/out/hlsl/wgsl-phony_assignment.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-pointer-function-arg.ron b/naga/tests/out/hlsl/wgsl-pointer-function-arg.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-pointer-function-arg.ron +++ b/naga/tests/out/hlsl/wgsl-pointer-function-arg.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-push-constants.ron b/naga/tests/out/hlsl/wgsl-push-constants.ron index e444486559d..73c10d5cd5e 100644 --- a/naga/tests/out/hlsl/wgsl-push-constants.ron +++ b/naga/tests/out/hlsl/wgsl-push-constants.ron @@ -13,4 +13,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-quad.ron b/naga/tests/out/hlsl/wgsl-quad.ron index de905523563..841c148dcbf 100644 --- a/naga/tests/out/hlsl/wgsl-quad.ron +++ b/naga/tests/out/hlsl/wgsl-quad.ron @@ -17,4 +17,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-ray-query-no-init-tracking.ron b/naga/tests/out/hlsl/wgsl-ray-query-no-init-tracking.ron index a31e1db125a..63c446e0605 100644 --- a/naga/tests/out/hlsl/wgsl-ray-query-no-init-tracking.ron +++ b/naga/tests/out/hlsl/wgsl-ray-query-no-init-tracking.ron @@ -13,4 +13,8 @@ target_profile:"cs_6_5", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-ray-query.ron b/naga/tests/out/hlsl/wgsl-ray-query.ron index a31e1db125a..63c446e0605 100644 --- a/naga/tests/out/hlsl/wgsl-ray-query.ron +++ b/naga/tests/out/hlsl/wgsl-ray-query.ron @@ -13,4 +13,8 @@ target_profile:"cs_6_5", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-select.ron b/naga/tests/out/hlsl/wgsl-select.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-select.ron +++ b/naga/tests/out/hlsl/wgsl-select.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-shadow.ron b/naga/tests/out/hlsl/wgsl-shadow.ron index 69be5b25e01..46e7fdbc4fe 100644 --- a/naga/tests/out/hlsl/wgsl-shadow.ron +++ b/naga/tests/out/hlsl/wgsl-shadow.ron @@ -17,4 +17,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-skybox.ron b/naga/tests/out/hlsl/wgsl-skybox.ron index 27b0c4af4da..11057f64012 100644 --- a/naga/tests/out/hlsl/wgsl-skybox.ron +++ b/naga/tests/out/hlsl/wgsl-skybox.ron @@ -13,4 +13,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-standard.ron b/naga/tests/out/hlsl/wgsl-standard.ron index 82373299d87..0ac408099a1 100644 --- a/naga/tests/out/hlsl/wgsl-standard.ron +++ b/naga/tests/out/hlsl/wgsl-standard.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-storage-textures.ron b/naga/tests/out/hlsl/wgsl-storage-textures.ron index b07b4fb7aad..b6ea267f85c 100644 --- a/naga/tests/out/hlsl/wgsl-storage-textures.ron +++ b/naga/tests/out/hlsl/wgsl-storage-textures.ron @@ -13,4 +13,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-struct-layout.ron b/naga/tests/out/hlsl/wgsl-struct-layout.ron index 04fe25e38a1..67ae82f4928 100644 --- a/naga/tests/out/hlsl/wgsl-struct-layout.ron +++ b/naga/tests/out/hlsl/wgsl-struct-layout.ron @@ -29,4 +29,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-subgroup-operations.ron b/naga/tests/out/hlsl/wgsl-subgroup-operations.ron index b973fe3da13..afc4b40f24d 100644 --- a/naga/tests/out/hlsl/wgsl-subgroup-operations.ron +++ b/naga/tests/out/hlsl/wgsl-subgroup-operations.ron @@ -9,4 +9,8 @@ target_profile:"cs_6_0", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-texture-arg.ron b/naga/tests/out/hlsl/wgsl-texture-arg.ron index 341a4c528e3..403f6c3d24f 100644 --- a/naga/tests/out/hlsl/wgsl-texture-arg.ron +++ b/naga/tests/out/hlsl/wgsl-texture-arg.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-texture-external.ron b/naga/tests/out/hlsl/wgsl-texture-external.ron index 23afa21e1f5..261c82f7d28 100644 --- a/naga/tests/out/hlsl/wgsl-texture-external.ron +++ b/naga/tests/out/hlsl/wgsl-texture-external.ron @@ -17,4 +17,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-type-inference.ron b/naga/tests/out/hlsl/wgsl-type-inference.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-type-inference.ron +++ b/naga/tests/out/hlsl/wgsl-type-inference.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-unconsumed_vertex_outputs_frag.ron b/naga/tests/out/hlsl/wgsl-unconsumed_vertex_outputs_frag.ron index eac1b945d2b..a0b1fa2b7ea 100644 --- a/naga/tests/out/hlsl/wgsl-unconsumed_vertex_outputs_frag.ron +++ b/naga/tests/out/hlsl/wgsl-unconsumed_vertex_outputs_frag.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-unconsumed_vertex_outputs_vert.ron b/naga/tests/out/hlsl/wgsl-unconsumed_vertex_outputs_vert.ron index a24f8d0eb8b..5a5236b3fda 100644 --- a/naga/tests/out/hlsl/wgsl-unconsumed_vertex_outputs_vert.ron +++ b/naga/tests/out/hlsl/wgsl-unconsumed_vertex_outputs_vert.ron @@ -9,4 +9,8 @@ ], compute:[ ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-workgroup-uniform-load.hlsl b/naga/tests/out/hlsl/wgsl-workgroup-uniform-load.hlsl index 0bfb55cb6cd..1a3d7228a0c 100644 --- a/naga/tests/out/hlsl/wgsl-workgroup-uniform-load.hlsl +++ b/naga/tests/out/hlsl/wgsl-workgroup-uniform-load.hlsl @@ -3,9 +3,9 @@ static const uint SIZE = 128u; groupshared int arr_i32_[128]; [numthreads(4, 1, 1)] -void test_workgroupUniformLoad(uint3 workgroup_id : SV_GroupID, uint3 __local_invocation_id : SV_GroupThreadID) +void test_workgroupUniformLoad(uint3 workgroup_id : SV_GroupID, uint __local_invocation_index : SV_GroupIndex) { - if (all(__local_invocation_id == uint3(0u, 0u, 0u))) { + if (all(__local_invocation_index == 0)) { arr_i32_ = (int[128])0; } GroupMemoryBarrierWithGroupSync(); diff --git a/naga/tests/out/hlsl/wgsl-workgroup-uniform-load.ron b/naga/tests/out/hlsl/wgsl-workgroup-uniform-load.ron index 17e926cdebd..e328c18589a 100644 --- a/naga/tests/out/hlsl/wgsl-workgroup-uniform-load.ron +++ b/naga/tests/out/hlsl/wgsl-workgroup-uniform-load.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/hlsl/wgsl-workgroup-var-init.hlsl b/naga/tests/out/hlsl/wgsl-workgroup-var-init.hlsl index 49b4fe621a5..8127f58449a 100644 --- a/naga/tests/out/hlsl/wgsl-workgroup-var-init.hlsl +++ b/naga/tests/out/hlsl/wgsl-workgroup-var-init.hlsl @@ -8,9 +8,9 @@ groupshared WStruct w_mem; RWByteAddressBuffer output : register(u0); [numthreads(1, 1, 1)] -void main(uint3 __local_invocation_id : SV_GroupThreadID) +void main(uint __local_invocation_index : SV_GroupIndex) { - if (all(__local_invocation_id == uint3(0u, 0u, 0u))) { + if (all(__local_invocation_index == 0)) { w_mem = (WStruct)0; } GroupMemoryBarrierWithGroupSync(); diff --git a/naga/tests/out/hlsl/wgsl-workgroup-var-init.ron b/naga/tests/out/hlsl/wgsl-workgroup-var-init.ron index a07b03300b1..f1edcbbbdd1 100644 --- a/naga/tests/out/hlsl/wgsl-workgroup-var-init.ron +++ b/naga/tests/out/hlsl/wgsl-workgroup-var-init.ron @@ -9,4 +9,8 @@ target_profile:"cs_5_1", ), ], + task:[ + ], + mesh:[ + ], ) diff --git a/naga/tests/out/spv/wgsl-mesh-shader.spvasm b/naga/tests/out/spv/wgsl-mesh-shader.spvasm index fde357c5c7d..e32904adccb 100644 --- a/naga/tests/out/spv/wgsl-mesh-shader.spvasm +++ b/naga/tests/out/spv/wgsl-mesh-shader.spvasm @@ -1,65 +1,66 @@ ; SPIR-V ; Version: 1.4 ; Generator: rspirv -; Bound: 384 +; Bound: 399 OpCapability Shader OpCapability MeshShadingEXT OpExtension "SPV_EXT_mesh_shader" %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint TaskEXT %24 "ts_main" %17 %19 %33 -OpEntryPoint TaskEXT %57 "ts_divergent" %54 %17 -OpEntryPoint MeshEXT %95 "ms_main" %17 %72 %81 %85 %88 %91 %94 %19 %21 %107 -OpEntryPoint MeshEXT %214 "ms_no_ts" %192 %200 %204 %207 %210 %213 %19 %21 %217 -OpEntryPoint MeshEXT %301 "ms_divergent" %279 %287 %291 %294 %297 %300 %19 %21 %303 -OpEntryPoint Fragment %379 "fs_main" %370 %373 %376 %378 -OpExecutionMode %24 LocalSize 1 1 1 -OpExecutionMode %57 LocalSize 2 1 1 -OpExecutionMode %95 LocalSize 1 1 1 -OpExecutionMode %95 OutputTrianglesNV -OpExecutionMode %95 OutputVertices 3 -OpExecutionMode %95 OutputPrimitivesNV 1 -OpExecutionMode %214 LocalSize 1 1 1 -OpExecutionMode %214 OutputTrianglesNV -OpExecutionMode %214 OutputVertices 3 -OpExecutionMode %214 OutputPrimitivesNV 1 -OpExecutionMode %301 LocalSize 1 1 1 -OpExecutionMode %301 OutputTrianglesNV -OpExecutionMode %301 OutputVertices 3 -OpExecutionMode %301 OutputPrimitivesNV 1 -OpExecutionMode %379 OriginUpperLeft -OpDecorate %72 BuiltIn LocalInvocationIndex -OpMemberDecorate %78 0 BuiltIn Position -OpDecorate %78 Block -OpMemberDecorate %82 0 BuiltIn CullPrimitiveEXT -OpMemberDecorate %82 0 PerPrimitiveNV -OpDecorate %82 Block -OpDecorate %85 PerPrimitiveNV -OpDecorate %88 Location 0 -OpDecorate %91 BuiltIn PrimitiveTriangleIndicesEXT -OpDecorate %94 Location 1 -OpDecorate %94 PerPrimitiveNV -OpDecorate %192 BuiltIn LocalInvocationIndex -OpMemberDecorate %197 0 BuiltIn Position -OpDecorate %197 Block -OpMemberDecorate %201 0 BuiltIn CullPrimitiveEXT -OpMemberDecorate %201 0 PerPrimitiveNV -OpDecorate %201 Block -OpDecorate %204 PerPrimitiveNV -OpDecorate %207 Location 0 -OpDecorate %210 BuiltIn PrimitiveTriangleIndicesEXT -OpDecorate %213 Location 1 -OpDecorate %213 PerPrimitiveNV -OpMemberDecorate %284 0 BuiltIn Position -OpDecorate %284 Block -OpMemberDecorate %288 0 BuiltIn CullPrimitiveEXT -OpMemberDecorate %288 0 PerPrimitiveNV -OpDecorate %288 Block -OpDecorate %291 PerPrimitiveNV -OpDecorate %294 Location 0 -OpDecorate %297 BuiltIn PrimitiveTriangleIndicesEXT -OpDecorate %300 Location 1 -OpDecorate %300 PerPrimitiveNV +OpEntryPoint TaskEXT %37 "ts_main" %17 %19 %46 +OpEntryPoint TaskEXT %70 "ts_divergent" %68 %17 +OpEntryPoint MeshEXT %110 "ms_main" %17 %86 %96 %100 %103 %106 %109 %19 %21 %122 +OpEntryPoint MeshEXT %228 "ms_no_ts" %206 %214 %218 %221 %224 %227 %19 %21 %231 +OpEntryPoint MeshEXT %317 "ms_divergent" %293 %295 %303 %307 %310 %313 %316 %19 %21 +OpEntryPoint Fragment %394 "fs_main" %385 %388 %391 %393 +OpExecutionMode %37 LocalSize 1 1 1 +OpExecutionMode %70 LocalSize 2 1 1 +OpExecutionMode %110 LocalSize 1 1 1 +OpExecutionMode %110 OutputTrianglesNV +OpExecutionMode %110 OutputVertices 3 +OpExecutionMode %110 OutputPrimitivesNV 1 +OpExecutionMode %228 LocalSize 1 1 1 +OpExecutionMode %228 OutputTrianglesNV +OpExecutionMode %228 OutputVertices 3 +OpExecutionMode %228 OutputPrimitivesNV 1 +OpExecutionMode %317 LocalSize 2 1 1 +OpExecutionMode %317 OutputTrianglesNV +OpExecutionMode %317 OutputVertices 3 +OpExecutionMode %317 OutputPrimitivesNV 1 +OpExecutionMode %394 OriginUpperLeft +OpDecorate %86 BuiltIn LocalInvocationIndex +OpMemberDecorate %93 0 BuiltIn Position +OpDecorate %93 Block +OpMemberDecorate %97 0 BuiltIn CullPrimitiveEXT +OpMemberDecorate %97 0 PerPrimitiveNV +OpDecorate %97 Block +OpDecorate %100 PerPrimitiveNV +OpDecorate %103 Location 0 +OpDecorate %106 BuiltIn PrimitiveTriangleIndicesEXT +OpDecorate %109 Location 1 +OpDecorate %109 PerPrimitiveNV +OpDecorate %206 BuiltIn LocalInvocationIndex +OpMemberDecorate %211 0 BuiltIn Position +OpDecorate %211 Block +OpMemberDecorate %215 0 BuiltIn CullPrimitiveEXT +OpMemberDecorate %215 0 PerPrimitiveNV +OpDecorate %215 Block +OpDecorate %218 PerPrimitiveNV +OpDecorate %221 Location 0 +OpDecorate %224 BuiltIn PrimitiveTriangleIndicesEXT +OpDecorate %227 Location 1 +OpDecorate %227 PerPrimitiveNV +OpDecorate %295 BuiltIn LocalInvocationIndex +OpMemberDecorate %300 0 BuiltIn Position +OpDecorate %300 Block +OpMemberDecorate %304 0 BuiltIn CullPrimitiveEXT +OpMemberDecorate %304 0 PerPrimitiveNV +OpDecorate %304 Block +OpDecorate %307 PerPrimitiveNV +OpDecorate %310 Location 0 +OpDecorate %313 BuiltIn PrimitiveTriangleIndicesEXT +OpDecorate %316 Location 1 +OpDecorate %316 PerPrimitiveNV OpMemberDecorate %6 0 Offset 0 OpMemberDecorate %6 1 Offset 16 OpMemberDecorate %7 0 Offset 0 @@ -74,17 +75,16 @@ OpMemberDecorate %16 0 Offset 0 OpMemberDecorate %16 1 Offset 96 OpMemberDecorate %16 2 Offset 128 OpMemberDecorate %16 3 Offset 132 -OpDecorate %33 BuiltIn LocalInvocationId -OpDecorate %54 BuiltIn LocalInvocationIndex -OpDecorate %107 BuiltIn LocalInvocationId -OpDecorate %217 BuiltIn LocalInvocationId -OpDecorate %279 BuiltIn LocalInvocationIndex -OpDecorate %303 BuiltIn LocalInvocationId -OpDecorate %370 BuiltIn FragCoord -OpDecorate %373 Location 0 -OpDecorate %376 Location 1 -OpDecorate %376 PerPrimitiveNV -OpDecorate %378 Location 0 +OpDecorate %46 BuiltIn LocalInvocationId +OpDecorate %68 BuiltIn LocalInvocationId +OpDecorate %122 BuiltIn LocalInvocationId +OpDecorate %231 BuiltIn LocalInvocationId +OpDecorate %293 BuiltIn LocalInvocationId +OpDecorate %385 BuiltIn FragCoord +OpDecorate %388 Location 0 +OpDecorate %391 Location 1 +OpDecorate %391 PerPrimitiveNV +OpDecorate %393 Location 0 %2 = OpTypeVoid %3 = OpTypeFloat 32 %4 = OpTypeVector %3 4 @@ -106,536 +106,558 @@ OpDecorate %378 Location 0 %19 = OpVariable %20 Workgroup %22 = OpTypePointer Workgroup %16 %21 = OpVariable %22 Workgroup -%25 = OpTypeFunction %2 -%26 = OpConstant %3 1 -%27 = OpConstant %3 0 -%28 = OpConstantComposite %4 %26 %26 %27 %26 -%29 = OpConstantTrue %5 -%30 = OpConstantComposite %9 %15 %15 %15 -%32 = OpConstantNull %3 -%34 = OpTypePointer Input %9 -%33 = OpVariable %34 Input -%36 = OpConstantNull %9 -%37 = OpTypeVector %5 3 -%42 = OpConstant %8 2 -%43 = OpConstant %8 264 -%45 = OpTypePointer TaskPayloadWorkgroupEXT %4 -%46 = OpConstant %8 0 -%48 = OpTypePointer TaskPayloadWorkgroupEXT %5 -%55 = OpTypePointer Input %8 -%54 = OpVariable %55 Input -%58 = OpConstantComposite %9 %42 %42 %42 -%72 = OpVariable %55 Input -%76 = OpTypePointer Function %8 -%78 = OpTypeStruct %4 -%79 = OpTypeArray %78 %13 -%80 = OpTypePointer Output %79 -%81 = OpVariable %80 Output -%82 = OpTypeStruct %5 -%83 = OpTypeArray %82 %15 -%84 = OpTypePointer Output %83 -%85 = OpVariable %84 Output -%86 = OpTypeArray %4 %13 -%87 = OpTypePointer Output %86 -%88 = OpVariable %87 Output -%89 = OpTypeArray %9 %15 -%90 = OpTypePointer Output %89 -%91 = OpVariable %90 Output -%92 = OpTypeArray %4 %15 -%93 = OpTypePointer Output %92 -%94 = OpVariable %93 Output -%96 = OpConstant %3 2 -%97 = OpConstantComposite %4 %27 %26 %27 %26 -%98 = OpConstant %3 -1 -%99 = OpConstantComposite %4 %98 %98 %27 %26 -%100 = OpConstantComposite %4 %27 %27 %26 %26 -%101 = OpConstantComposite %4 %26 %98 %27 %26 -%102 = OpConstantComposite %4 %26 %27 %27 %26 -%103 = OpConstantComposite %9 %46 %15 %42 -%104 = OpConstantComposite %4 %26 %27 %26 %26 -%106 = OpConstantNull %16 -%107 = OpVariable %34 Input -%114 = OpTypePointer Workgroup %8 -%117 = OpTypePointer Workgroup %12 -%118 = OpTypePointer Workgroup %7 -%119 = OpTypePointer Workgroup %4 -%135 = OpTypePointer Workgroup %14 -%136 = OpTypePointer Workgroup %10 -%137 = OpTypePointer Workgroup %9 -%139 = OpTypePointer Workgroup %5 -%161 = OpTypePointer Output %4 -%176 = OpTypePointer Output %9 -%180 = OpTypePointer Output %5 -%192 = OpVariable %55 Input -%197 = OpTypeStruct %4 -%198 = OpTypeArray %197 %13 -%199 = OpTypePointer Output %198 -%200 = OpVariable %199 Output -%201 = OpTypeStruct %5 -%202 = OpTypeArray %201 %15 -%203 = OpTypePointer Output %202 -%204 = OpVariable %203 Output -%205 = OpTypeArray %4 %13 -%206 = OpTypePointer Output %205 -%207 = OpVariable %206 Output -%208 = OpTypeArray %9 %15 -%209 = OpTypePointer Output %208 -%210 = OpVariable %209 Output -%211 = OpTypeArray %4 %15 -%212 = OpTypePointer Output %211 -%213 = OpVariable %212 Output -%215 = OpConstantFalse %5 -%217 = OpVariable %34 Input -%279 = OpVariable %55 Input -%284 = OpTypeStruct %4 -%285 = OpTypeArray %284 %13 -%286 = OpTypePointer Output %285 -%287 = OpVariable %286 Output -%288 = OpTypeStruct %5 -%289 = OpTypeArray %288 %15 -%290 = OpTypePointer Output %289 -%291 = OpVariable %290 Output -%292 = OpTypeArray %4 %13 -%293 = OpTypePointer Output %292 -%294 = OpVariable %293 Output -%295 = OpTypeArray %9 %15 -%296 = OpTypePointer Output %295 -%297 = OpVariable %296 Output -%298 = OpTypeArray %4 %15 -%299 = OpTypePointer Output %298 -%300 = OpVariable %299 Output -%303 = OpVariable %34 Input -%371 = OpTypePointer Input %4 -%370 = OpVariable %371 Input -%373 = OpVariable %371 Input -%376 = OpVariable %371 Input -%378 = OpVariable %161 Output -%24 = OpFunction %2 None %25 +%25 = OpTypeFunction %5 +%27 = OpTypePointer TaskPayloadWorkgroupEXT %5 +%33 = OpTypeFunction %2 %5 +%38 = OpTypeFunction %2 +%39 = OpConstant %3 1 +%40 = OpConstant %3 0 +%41 = OpConstantComposite %4 %39 %39 %40 %39 +%42 = OpConstantTrue %5 +%43 = OpConstantComposite %9 %15 %15 %15 +%45 = OpConstantNull %3 +%47 = OpTypePointer Input %9 +%46 = OpVariable %47 Input +%49 = OpConstantNull %9 +%50 = OpTypeVector %5 3 +%55 = OpConstant %8 2 +%56 = OpConstant %8 264 +%58 = OpTypePointer TaskPayloadWorkgroupEXT %4 +%59 = OpConstant %8 0 +%68 = OpVariable %47 Input +%71 = OpConstantComposite %9 %55 %55 %55 +%87 = OpTypePointer Input %8 +%86 = OpVariable %87 Input +%91 = OpTypePointer Function %8 +%93 = OpTypeStruct %4 +%94 = OpTypeArray %93 %13 +%95 = OpTypePointer Output %94 +%96 = OpVariable %95 Output +%97 = OpTypeStruct %5 +%98 = OpTypeArray %97 %15 +%99 = OpTypePointer Output %98 +%100 = OpVariable %99 Output +%101 = OpTypeArray %4 %13 +%102 = OpTypePointer Output %101 +%103 = OpVariable %102 Output +%104 = OpTypeArray %9 %15 +%105 = OpTypePointer Output %104 +%106 = OpVariable %105 Output +%107 = OpTypeArray %4 %15 +%108 = OpTypePointer Output %107 +%109 = OpVariable %108 Output +%111 = OpConstant %3 2 +%112 = OpConstantComposite %4 %40 %39 %40 %39 +%113 = OpConstant %3 -1 +%114 = OpConstantComposite %4 %113 %113 %40 %39 +%115 = OpConstantComposite %4 %40 %40 %39 %39 +%116 = OpConstantComposite %4 %39 %113 %40 %39 +%117 = OpConstantComposite %4 %39 %40 %40 %39 +%118 = OpConstantComposite %9 %59 %15 %55 +%119 = OpConstantComposite %4 %39 %40 %39 %39 +%121 = OpConstantNull %16 +%122 = OpVariable %47 Input +%129 = OpTypePointer Workgroup %8 +%132 = OpTypePointer Workgroup %12 +%133 = OpTypePointer Workgroup %7 +%134 = OpTypePointer Workgroup %4 +%150 = OpTypePointer Workgroup %14 +%151 = OpTypePointer Workgroup %10 +%152 = OpTypePointer Workgroup %9 +%154 = OpTypePointer Workgroup %5 +%175 = OpTypePointer Output %4 +%190 = OpTypePointer Output %9 +%194 = OpTypePointer Output %5 +%206 = OpVariable %87 Input +%211 = OpTypeStruct %4 +%212 = OpTypeArray %211 %13 +%213 = OpTypePointer Output %212 +%214 = OpVariable %213 Output +%215 = OpTypeStruct %5 +%216 = OpTypeArray %215 %15 +%217 = OpTypePointer Output %216 +%218 = OpVariable %217 Output +%219 = OpTypeArray %4 %13 +%220 = OpTypePointer Output %219 +%221 = OpVariable %220 Output +%222 = OpTypeArray %9 %15 +%223 = OpTypePointer Output %222 +%224 = OpVariable %223 Output +%225 = OpTypeArray %4 %15 +%226 = OpTypePointer Output %225 +%227 = OpVariable %226 Output +%229 = OpConstantFalse %5 +%231 = OpVariable %47 Input +%293 = OpVariable %47 Input +%295 = OpVariable %87 Input +%300 = OpTypeStruct %4 +%301 = OpTypeArray %300 %13 +%302 = OpTypePointer Output %301 +%303 = OpVariable %302 Output +%304 = OpTypeStruct %5 +%305 = OpTypeArray %304 %15 +%306 = OpTypePointer Output %305 +%307 = OpVariable %306 Output +%308 = OpTypeArray %4 %13 +%309 = OpTypePointer Output %308 +%310 = OpVariable %309 Output +%311 = OpTypeArray %9 %15 +%312 = OpTypePointer Output %311 +%313 = OpVariable %312 Output +%314 = OpTypeArray %4 %15 +%315 = OpTypePointer Output %314 +%316 = OpVariable %315 Output +%386 = OpTypePointer Input %4 +%385 = OpVariable %386 Input +%388 = OpVariable %386 Input +%391 = OpVariable %386 Input +%393 = OpVariable %175 Output +%24 = OpFunction %5 None %25 %23 = OpLabel -OpBranch %31 -%31 = OpLabel -%35 = OpLoad %9 %33 -%38 = OpIEqual %37 %35 %36 -%39 = OpAll %5 %38 -OpSelectionMerge %40 None -OpBranchConditional %39 %41 %40 -%41 = OpLabel -OpStore %19 %32 -OpBranch %40 -%40 = OpLabel -OpControlBarrier %42 %42 %43 +OpBranch %26 +%26 = OpLabel +%28 = OpAccessChain %27 %17 %15 +%29 = OpLoad %5 %28 +OpReturnValue %29 +OpFunctionEnd +%32 = OpFunction %2 None %33 +%31 = OpFunctionParameter %5 +%30 = OpLabel +OpBranch %34 +%34 = OpLabel +%35 = OpAccessChain %27 %17 %15 +OpStore %35 %31 +OpReturn +OpFunctionEnd +%37 = OpFunction %2 None %38 +%36 = OpLabel OpBranch %44 %44 = OpLabel -OpStore %19 %26 -%47 = OpAccessChain %45 %17 %46 -OpStore %47 %28 -%49 = OpAccessChain %48 %17 %15 -OpStore %49 %29 -OpControlBarrier %42 %42 %43 -%50 = OpCompositeExtract %8 %30 0 -%51 = OpCompositeExtract %8 %30 1 -%52 = OpCompositeExtract %8 %30 2 -OpEmitMeshTasksEXT %50 %51 %52 %17 -OpFunctionEnd -%57 = OpFunction %2 None %25 +%48 = OpLoad %9 %46 +%51 = OpIEqual %50 %48 %49 +%52 = OpAll %5 %51 +OpSelectionMerge %53 None +OpBranchConditional %52 %54 %53 +%54 = OpLabel +OpStore %19 %45 +OpBranch %53 %53 = OpLabel -%56 = OpLoad %8 %54 -OpBranch %59 -%59 = OpLabel -%60 = OpIEqual %5 %56 %46 -OpSelectionMerge %61 None -OpBranchConditional %60 %62 %61 -%62 = OpLabel -%63 = OpAccessChain %45 %17 %46 -OpStore %63 %28 -%64 = OpAccessChain %48 %17 %15 -OpStore %64 %29 -OpControlBarrier %42 %42 %43 -%65 = OpCompositeExtract %8 %30 0 -%66 = OpCompositeExtract %8 %30 1 -%67 = OpCompositeExtract %8 %30 2 -OpEmitMeshTasksEXT %65 %66 %67 %17 -%61 = OpLabel -OpControlBarrier %42 %42 %43 -%68 = OpCompositeExtract %8 %58 0 -%69 = OpCompositeExtract %8 %58 1 -%70 = OpCompositeExtract %8 %58 2 -OpEmitMeshTasksEXT %68 %69 %70 %17 +OpControlBarrier %55 %55 %56 +OpBranch %57 +%57 = OpLabel +OpStore %19 %39 +%60 = OpAccessChain %58 %17 %59 +OpStore %60 %41 +%61 = OpFunctionCall %2 %32 %42 +%62 = OpFunctionCall %5 %24 +%63 = OpAccessChain %27 %17 %15 +OpStore %63 %62 +OpControlBarrier %55 %55 %56 +%64 = OpCompositeExtract %8 %43 0 +%65 = OpCompositeExtract %8 %43 1 +%66 = OpCompositeExtract %8 %43 2 +OpEmitMeshTasksEXT %64 %65 %66 %17 +OpFunctionEnd +%70 = OpFunction %2 None %38 +%67 = OpLabel +%69 = OpLoad %9 %68 +OpBranch %72 +%72 = OpLabel +%73 = OpCompositeExtract %8 %69 0 +%74 = OpIEqual %5 %73 %59 +OpSelectionMerge %75 None +OpBranchConditional %74 %76 %75 +%76 = OpLabel +%77 = OpAccessChain %58 %17 %59 +OpStore %77 %41 +%78 = OpAccessChain %27 %17 %15 +OpStore %78 %42 +OpControlBarrier %55 %55 %56 +%79 = OpCompositeExtract %8 %43 0 +%80 = OpCompositeExtract %8 %43 1 +%81 = OpCompositeExtract %8 %43 2 +OpEmitMeshTasksEXT %79 %80 %81 %17 +%75 = OpLabel +OpControlBarrier %55 %55 %56 +%82 = OpCompositeExtract %8 %71 0 +%83 = OpCompositeExtract %8 %71 1 +%84 = OpCompositeExtract %8 %71 2 +OpEmitMeshTasksEXT %82 %83 %84 %17 OpFunctionEnd -%95 = OpFunction %2 None %25 -%71 = OpLabel -%74 = OpVariable %76 Function -%75 = OpVariable %76 Function -%73 = OpLoad %8 %72 -OpBranch %105 -%105 = OpLabel -%108 = OpLoad %9 %107 -%109 = OpIEqual %37 %108 %36 -%110 = OpAll %5 %109 -OpSelectionMerge %111 None -OpBranchConditional %110 %112 %111 -%112 = OpLabel -OpStore %19 %32 -OpStore %21 %106 -OpBranch %111 -%111 = OpLabel -OpControlBarrier %42 %42 %43 -OpBranch %113 -%113 = OpLabel -%115 = OpAccessChain %114 %21 %42 -OpStore %115 %13 -%116 = OpAccessChain %114 %21 %13 -OpStore %116 %15 -OpStore %19 %96 -%120 = OpAccessChain %119 %21 %46 %46 %46 -OpStore %120 %97 -%121 = OpAccessChain %45 %17 %46 -%122 = OpLoad %4 %121 -%123 = OpFMul %4 %97 %122 -%124 = OpAccessChain %119 %21 %46 %46 %15 -OpStore %124 %123 -%125 = OpAccessChain %119 %21 %46 %15 %46 -OpStore %125 %99 -%126 = OpAccessChain %45 %17 %46 -%127 = OpLoad %4 %126 -%128 = OpFMul %4 %100 %127 -%129 = OpAccessChain %119 %21 %46 %15 %15 -OpStore %129 %128 -%130 = OpAccessChain %119 %21 %46 %42 %46 -OpStore %130 %101 -%131 = OpAccessChain %45 %17 %46 -%132 = OpLoad %4 %131 -%133 = OpFMul %4 %102 %132 -%134 = OpAccessChain %119 %21 %46 %42 %15 -OpStore %134 %133 -%138 = OpAccessChain %137 %21 %15 %46 %46 -OpStore %138 %103 -%140 = OpAccessChain %48 %17 %15 -%141 = OpLoad %5 %140 -%142 = OpLogicalNot %5 %141 -%143 = OpAccessChain %139 %21 %15 %46 %15 -OpStore %143 %142 -%144 = OpAccessChain %119 %21 %15 %46 %42 -OpStore %144 %104 -OpBranch %77 -%77 = OpLabel -OpControlBarrier %42 %42 %43 -%145 = OpAccessChain %114 %21 %42 -%146 = OpLoad %8 %145 -%147 = OpExtInst %8 %1 UMin %146 %13 -%148 = OpAccessChain %114 %21 %13 -%149 = OpLoad %8 %148 -%150 = OpExtInst %8 %1 UMin %149 %15 -%151 = OpAccessChain %117 %21 %46 -%152 = OpAccessChain %135 %21 %15 -OpControlBarrier %42 %42 %43 -OpSetMeshOutputsEXT %147 %150 -OpStore %74 %73 -OpBranch %153 -%153 = OpLabel -OpLoopMerge %155 %166 None -OpBranch %165 -%165 = OpLabel -%168 = OpLoad %8 %74 -%169 = OpULessThan %5 %168 %147 -OpBranchConditional %169 %167 %155 +%110 = OpFunction %2 None %38 +%85 = OpLabel +%89 = OpVariable %91 Function +%90 = OpVariable %91 Function +%88 = OpLoad %8 %86 +OpBranch %120 +%120 = OpLabel +%123 = OpLoad %9 %122 +%124 = OpIEqual %50 %123 %49 +%125 = OpAll %5 %124 +OpSelectionMerge %126 None +OpBranchConditional %125 %127 %126 +%127 = OpLabel +OpStore %19 %45 +OpStore %21 %121 +OpBranch %126 +%126 = OpLabel +OpControlBarrier %55 %55 %56 +OpBranch %128 +%128 = OpLabel +%130 = OpAccessChain %129 %21 %55 +OpStore %130 %13 +%131 = OpAccessChain %129 %21 %13 +OpStore %131 %15 +OpStore %19 %111 +%135 = OpAccessChain %134 %21 %59 %59 %59 +OpStore %135 %112 +%136 = OpAccessChain %58 %17 %59 +%137 = OpLoad %4 %136 +%138 = OpFMul %4 %112 %137 +%139 = OpAccessChain %134 %21 %59 %59 %15 +OpStore %139 %138 +%140 = OpAccessChain %134 %21 %59 %15 %59 +OpStore %140 %114 +%141 = OpAccessChain %58 %17 %59 +%142 = OpLoad %4 %141 +%143 = OpFMul %4 %115 %142 +%144 = OpAccessChain %134 %21 %59 %15 %15 +OpStore %144 %143 +%145 = OpAccessChain %134 %21 %59 %55 %59 +OpStore %145 %116 +%146 = OpAccessChain %58 %17 %59 +%147 = OpLoad %4 %146 +%148 = OpFMul %4 %117 %147 +%149 = OpAccessChain %134 %21 %59 %55 %15 +OpStore %149 %148 +%153 = OpAccessChain %152 %21 %15 %59 %59 +OpStore %153 %118 +%155 = OpFunctionCall %5 %24 +%156 = OpLogicalNot %5 %155 +%157 = OpAccessChain %154 %21 %15 %59 %15 +OpStore %157 %156 +%158 = OpAccessChain %134 %21 %15 %59 %55 +OpStore %158 %119 +OpBranch %92 +%92 = OpLabel +OpControlBarrier %55 %55 %56 +%159 = OpAccessChain %129 %21 %55 +%160 = OpLoad %8 %159 +%161 = OpExtInst %8 %1 UMin %160 %13 +%162 = OpAccessChain %129 %21 %13 +%163 = OpLoad %8 %162 +%164 = OpExtInst %8 %1 UMin %163 %15 +%165 = OpAccessChain %132 %21 %59 +%166 = OpAccessChain %150 %21 %15 +OpControlBarrier %55 %55 %56 +OpSetMeshOutputsEXT %161 %164 +OpStore %89 %88 +OpBranch %167 %167 = OpLabel -%157 = OpLoad %8 %74 -%158 = OpAccessChain %119 %151 %157 %46 -%159 = OpLoad %4 %158 -%160 = OpAccessChain %161 %81 %157 %46 -OpStore %160 %159 -%162 = OpAccessChain %119 %151 %157 %15 -%163 = OpLoad %4 %162 -%164 = OpAccessChain %161 %88 %157 -OpStore %164 %163 -OpBranch %166 -%166 = OpLabel -%170 = OpLoad %8 %74 -%171 = OpIAdd %8 %170 %15 -OpStore %74 %171 -OpBranch %153 -%155 = OpLabel -OpStore %75 %73 -OpBranch %154 -%154 = OpLabel -OpLoopMerge %156 %185 None -OpBranch %184 -%184 = OpLabel -%187 = OpLoad %8 %75 -%188 = OpULessThan %5 %187 %150 -OpBranchConditional %188 %186 %156 -%186 = OpLabel -%172 = OpLoad %8 %75 -%173 = OpAccessChain %137 %152 %172 %46 -%174 = OpLoad %9 %173 -%175 = OpAccessChain %176 %91 %172 -OpStore %175 %174 -%177 = OpAccessChain %139 %152 %172 %15 -%178 = OpLoad %5 %177 -%179 = OpAccessChain %180 %85 %172 %46 -OpStore %179 %178 -%181 = OpAccessChain %119 %152 %172 %42 -%182 = OpLoad %4 %181 -%183 = OpAccessChain %161 %94 %172 -OpStore %183 %182 -OpBranch %185 -%185 = OpLabel -%189 = OpLoad %8 %75 -%190 = OpIAdd %8 %189 %15 -OpStore %75 %190 -OpBranch %154 -%156 = OpLabel +OpLoopMerge %169 %180 None +OpBranch %179 +%179 = OpLabel +%182 = OpLoad %8 %89 +%183 = OpULessThan %5 %182 %161 +OpBranchConditional %183 %181 %169 +%181 = OpLabel +%171 = OpLoad %8 %89 +%172 = OpAccessChain %134 %165 %171 %59 +%173 = OpLoad %4 %172 +%174 = OpAccessChain %175 %96 %171 %59 +OpStore %174 %173 +%176 = OpAccessChain %134 %165 %171 %15 +%177 = OpLoad %4 %176 +%178 = OpAccessChain %175 %103 %171 +OpStore %178 %177 +OpBranch %180 +%180 = OpLabel +%184 = OpLoad %8 %89 +%185 = OpIAdd %8 %184 %15 +OpStore %89 %185 +OpBranch %167 +%169 = OpLabel +OpStore %90 %88 +OpBranch %168 +%168 = OpLabel +OpLoopMerge %170 %199 None +OpBranch %198 +%198 = OpLabel +%201 = OpLoad %8 %90 +%202 = OpULessThan %5 %201 %164 +OpBranchConditional %202 %200 %170 +%200 = OpLabel +%186 = OpLoad %8 %90 +%187 = OpAccessChain %152 %166 %186 %59 +%188 = OpLoad %9 %187 +%189 = OpAccessChain %190 %106 %186 +OpStore %189 %188 +%191 = OpAccessChain %154 %166 %186 %15 +%192 = OpLoad %5 %191 +%193 = OpAccessChain %194 %100 %186 %59 +OpStore %193 %192 +%195 = OpAccessChain %134 %166 %186 %55 +%196 = OpLoad %4 %195 +%197 = OpAccessChain %175 %109 %186 +OpStore %197 %196 +OpBranch %199 +%199 = OpLabel +%203 = OpLoad %8 %90 +%204 = OpIAdd %8 %203 %15 +OpStore %90 %204 +OpBranch %168 +%170 = OpLabel OpReturn OpFunctionEnd -%214 = OpFunction %2 None %25 -%191 = OpLabel -%194 = OpVariable %76 Function -%195 = OpVariable %76 Function -%193 = OpLoad %8 %192 -OpBranch %216 -%216 = OpLabel -%218 = OpLoad %9 %217 -%219 = OpIEqual %37 %218 %36 -%220 = OpAll %5 %219 -OpSelectionMerge %221 None -OpBranchConditional %220 %222 %221 -%222 = OpLabel -OpStore %19 %32 -OpStore %21 %106 -OpBranch %221 -%221 = OpLabel -OpControlBarrier %42 %42 %43 -OpBranch %223 -%223 = OpLabel -%224 = OpAccessChain %114 %21 %42 -OpStore %224 %13 -%225 = OpAccessChain %114 %21 %13 -OpStore %225 %15 -OpStore %19 %96 -%226 = OpAccessChain %119 %21 %46 %46 %46 -OpStore %226 %97 -%227 = OpAccessChain %119 %21 %46 %46 %15 -OpStore %227 %97 -%228 = OpAccessChain %119 %21 %46 %15 %46 -OpStore %228 %99 -%229 = OpAccessChain %119 %21 %46 %15 %15 -OpStore %229 %100 -%230 = OpAccessChain %119 %21 %46 %42 %46 -OpStore %230 %101 -%231 = OpAccessChain %119 %21 %46 %42 %15 -OpStore %231 %102 -%232 = OpAccessChain %137 %21 %15 %46 %46 -OpStore %232 %103 -%233 = OpAccessChain %139 %21 %15 %46 %15 -OpStore %233 %215 -%234 = OpAccessChain %119 %21 %15 %46 %42 -OpStore %234 %104 -OpBranch %196 -%196 = OpLabel -OpControlBarrier %42 %42 %43 -%235 = OpAccessChain %114 %21 %42 -%236 = OpLoad %8 %235 -%237 = OpExtInst %8 %1 UMin %236 %13 -%238 = OpAccessChain %114 %21 %13 -%239 = OpLoad %8 %238 -%240 = OpExtInst %8 %1 UMin %239 %15 -%241 = OpAccessChain %117 %21 %46 -%242 = OpAccessChain %135 %21 %15 -OpControlBarrier %42 %42 %43 -OpSetMeshOutputsEXT %237 %240 -OpStore %194 %193 -OpBranch %243 -%243 = OpLabel -OpLoopMerge %245 %255 None -OpBranch %254 -%254 = OpLabel -%257 = OpLoad %8 %194 -%258 = OpULessThan %5 %257 %237 -OpBranchConditional %258 %256 %245 -%256 = OpLabel -%247 = OpLoad %8 %194 -%248 = OpAccessChain %119 %241 %247 %46 -%249 = OpLoad %4 %248 -%250 = OpAccessChain %161 %200 %247 %46 -OpStore %250 %249 -%251 = OpAccessChain %119 %241 %247 %15 -%252 = OpLoad %4 %251 -%253 = OpAccessChain %161 %207 %247 -OpStore %253 %252 -OpBranch %255 -%255 = OpLabel -%259 = OpLoad %8 %194 -%260 = OpIAdd %8 %259 %15 -OpStore %194 %260 -OpBranch %243 -%245 = OpLabel -OpStore %195 %193 -OpBranch %244 -%244 = OpLabel -OpLoopMerge %246 %272 None -OpBranch %271 -%271 = OpLabel -%274 = OpLoad %8 %195 -%275 = OpULessThan %5 %274 %240 -OpBranchConditional %275 %273 %246 -%273 = OpLabel -%261 = OpLoad %8 %195 -%262 = OpAccessChain %137 %242 %261 %46 -%263 = OpLoad %9 %262 -%264 = OpAccessChain %176 %210 %261 +%228 = OpFunction %2 None %38 +%205 = OpLabel +%208 = OpVariable %91 Function +%209 = OpVariable %91 Function +%207 = OpLoad %8 %206 +OpBranch %230 +%230 = OpLabel +%232 = OpLoad %9 %231 +%233 = OpIEqual %50 %232 %49 +%234 = OpAll %5 %233 +OpSelectionMerge %235 None +OpBranchConditional %234 %236 %235 +%236 = OpLabel +OpStore %19 %45 +OpStore %21 %121 +OpBranch %235 +%235 = OpLabel +OpControlBarrier %55 %55 %56 +OpBranch %237 +%237 = OpLabel +%238 = OpAccessChain %129 %21 %55 +OpStore %238 %13 +%239 = OpAccessChain %129 %21 %13 +OpStore %239 %15 +OpStore %19 %111 +%240 = OpAccessChain %134 %21 %59 %59 %59 +OpStore %240 %112 +%241 = OpAccessChain %134 %21 %59 %59 %15 +OpStore %241 %112 +%242 = OpAccessChain %134 %21 %59 %15 %59 +OpStore %242 %114 +%243 = OpAccessChain %134 %21 %59 %15 %15 +OpStore %243 %115 +%244 = OpAccessChain %134 %21 %59 %55 %59 +OpStore %244 %116 +%245 = OpAccessChain %134 %21 %59 %55 %15 +OpStore %245 %117 +%246 = OpAccessChain %152 %21 %15 %59 %59 +OpStore %246 %118 +%247 = OpAccessChain %154 %21 %15 %59 %15 +OpStore %247 %229 +%248 = OpAccessChain %134 %21 %15 %59 %55 +OpStore %248 %119 +OpBranch %210 +%210 = OpLabel +OpControlBarrier %55 %55 %56 +%249 = OpAccessChain %129 %21 %55 +%250 = OpLoad %8 %249 +%251 = OpExtInst %8 %1 UMin %250 %13 +%252 = OpAccessChain %129 %21 %13 +%253 = OpLoad %8 %252 +%254 = OpExtInst %8 %1 UMin %253 %15 +%255 = OpAccessChain %132 %21 %59 +%256 = OpAccessChain %150 %21 %15 +OpControlBarrier %55 %55 %56 +OpSetMeshOutputsEXT %251 %254 +OpStore %208 %207 +OpBranch %257 +%257 = OpLabel +OpLoopMerge %259 %269 None +OpBranch %268 +%268 = OpLabel +%271 = OpLoad %8 %208 +%272 = OpULessThan %5 %271 %251 +OpBranchConditional %272 %270 %259 +%270 = OpLabel +%261 = OpLoad %8 %208 +%262 = OpAccessChain %134 %255 %261 %59 +%263 = OpLoad %4 %262 +%264 = OpAccessChain %175 %214 %261 %59 OpStore %264 %263 -%265 = OpAccessChain %139 %242 %261 %15 -%266 = OpLoad %5 %265 -%267 = OpAccessChain %180 %204 %261 %46 +%265 = OpAccessChain %134 %255 %261 %15 +%266 = OpLoad %4 %265 +%267 = OpAccessChain %175 %221 %261 OpStore %267 %266 -%268 = OpAccessChain %119 %242 %261 %42 -%269 = OpLoad %4 %268 -%270 = OpAccessChain %161 %213 %261 -OpStore %270 %269 -OpBranch %272 -%272 = OpLabel -%276 = OpLoad %8 %195 -%277 = OpIAdd %8 %276 %15 -OpStore %195 %277 -OpBranch %244 -%246 = OpLabel +OpBranch %269 +%269 = OpLabel +%273 = OpLoad %8 %208 +%274 = OpIAdd %8 %273 %15 +OpStore %208 %274 +OpBranch %257 +%259 = OpLabel +OpStore %209 %207 +OpBranch %258 +%258 = OpLabel +OpLoopMerge %260 %286 None +OpBranch %285 +%285 = OpLabel +%288 = OpLoad %8 %209 +%289 = OpULessThan %5 %288 %254 +OpBranchConditional %289 %287 %260 +%287 = OpLabel +%275 = OpLoad %8 %209 +%276 = OpAccessChain %152 %256 %275 %59 +%277 = OpLoad %9 %276 +%278 = OpAccessChain %190 %224 %275 +OpStore %278 %277 +%279 = OpAccessChain %154 %256 %275 %15 +%280 = OpLoad %5 %279 +%281 = OpAccessChain %194 %218 %275 %59 +OpStore %281 %280 +%282 = OpAccessChain %134 %256 %275 %55 +%283 = OpLoad %4 %282 +%284 = OpAccessChain %175 %227 %275 +OpStore %284 %283 +OpBranch %286 +%286 = OpLabel +%290 = OpLoad %8 %209 +%291 = OpIAdd %8 %290 %15 +OpStore %209 %291 +OpBranch %258 +%260 = OpLabel OpReturn OpFunctionEnd -%301 = OpFunction %2 None %25 -%278 = OpLabel -%281 = OpVariable %76 Function -%282 = OpVariable %76 Function -%280 = OpLoad %8 %279 -OpBranch %302 -%302 = OpLabel -%304 = OpLoad %9 %303 -%305 = OpIEqual %37 %304 %36 -%306 = OpAll %5 %305 -OpSelectionMerge %307 None -OpBranchConditional %306 %308 %307 -%308 = OpLabel -OpStore %19 %32 -OpStore %21 %106 -OpBranch %307 -%307 = OpLabel -OpControlBarrier %42 %42 %43 -OpBranch %309 -%309 = OpLabel -%310 = OpIEqual %5 %280 %46 -OpSelectionMerge %311 None -OpBranchConditional %310 %312 %313 -%312 = OpLabel -%314 = OpAccessChain %114 %21 %42 -OpStore %314 %13 -%315 = OpAccessChain %114 %21 %13 -OpStore %315 %15 -OpStore %19 %96 -%316 = OpAccessChain %119 %21 %46 %46 %46 -OpStore %316 %97 -%317 = OpAccessChain %119 %21 %46 %46 %15 -OpStore %317 %97 -%318 = OpAccessChain %119 %21 %46 %15 %46 -OpStore %318 %99 -%319 = OpAccessChain %119 %21 %46 %15 %15 -OpStore %319 %100 -%320 = OpAccessChain %119 %21 %46 %42 %46 -OpStore %320 %101 -%321 = OpAccessChain %119 %21 %46 %42 %15 -OpStore %321 %102 -%322 = OpAccessChain %137 %21 %15 %46 %46 -OpStore %322 %103 -%323 = OpAccessChain %139 %21 %15 %46 %15 -OpStore %323 %215 -%324 = OpAccessChain %119 %21 %15 %46 %42 -OpStore %324 %104 -OpBranch %283 -%313 = OpLabel -OpBranch %283 -%311 = OpLabel +%317 = OpFunction %2 None %38 +%292 = OpLabel +%297 = OpVariable %91 Function +%298 = OpVariable %91 Function +%294 = OpLoad %9 %293 +%296 = OpLoad %8 %295 +OpBranch %318 +%318 = OpLabel +%319 = OpIEqual %50 %294 %49 +%320 = OpAll %5 %319 +OpSelectionMerge %321 None +OpBranchConditional %320 %322 %321 +%322 = OpLabel +OpStore %19 %45 +OpStore %21 %121 +OpBranch %321 +%321 = OpLabel +OpControlBarrier %55 %55 %56 +OpBranch %323 +%323 = OpLabel +%324 = OpCompositeExtract %8 %294 0 +%325 = OpIEqual %5 %324 %59 +OpSelectionMerge %326 None +OpBranchConditional %325 %327 %328 +%327 = OpLabel +%329 = OpAccessChain %129 %21 %55 +OpStore %329 %13 +%330 = OpAccessChain %129 %21 %13 +OpStore %330 %15 +OpStore %19 %111 +%331 = OpAccessChain %134 %21 %59 %59 %59 +OpStore %331 %112 +%332 = OpAccessChain %134 %21 %59 %59 %15 +OpStore %332 %112 +%333 = OpAccessChain %134 %21 %59 %15 %59 +OpStore %333 %114 +%334 = OpAccessChain %134 %21 %59 %15 %15 +OpStore %334 %115 +%335 = OpAccessChain %134 %21 %59 %55 %59 +OpStore %335 %116 +%336 = OpAccessChain %134 %21 %59 %55 %15 +OpStore %336 %117 +%337 = OpAccessChain %152 %21 %15 %59 %59 +OpStore %337 %118 +%338 = OpAccessChain %154 %21 %15 %59 %15 +OpStore %338 %229 +%339 = OpAccessChain %134 %21 %15 %59 %55 +OpStore %339 %119 +OpBranch %299 +%328 = OpLabel +OpBranch %299 +%326 = OpLabel OpReturn -%283 = OpLabel -OpControlBarrier %42 %42 %43 -%325 = OpAccessChain %114 %21 %42 -%326 = OpLoad %8 %325 -%327 = OpExtInst %8 %1 UMin %326 %13 -%328 = OpAccessChain %114 %21 %13 -%329 = OpLoad %8 %328 -%330 = OpExtInst %8 %1 UMin %329 %15 -%331 = OpAccessChain %117 %21 %46 -%332 = OpAccessChain %135 %21 %15 -OpControlBarrier %42 %42 %43 -OpSetMeshOutputsEXT %327 %330 -OpStore %281 %280 -OpBranch %333 -%333 = OpLabel -OpLoopMerge %335 %345 None -OpBranch %344 -%344 = OpLabel -%347 = OpLoad %8 %281 -%348 = OpULessThan %5 %347 %327 -OpBranchConditional %348 %346 %335 -%346 = OpLabel -%337 = OpLoad %8 %281 -%338 = OpAccessChain %119 %331 %337 %46 -%339 = OpLoad %4 %338 -%340 = OpAccessChain %161 %287 %337 %46 -OpStore %340 %339 -%341 = OpAccessChain %119 %331 %337 %15 -%342 = OpLoad %4 %341 -%343 = OpAccessChain %161 %294 %337 -OpStore %343 %342 -OpBranch %345 -%345 = OpLabel -%349 = OpLoad %8 %281 -%350 = OpIAdd %8 %349 %15 -OpStore %281 %350 -OpBranch %333 -%335 = OpLabel -OpStore %282 %280 -OpBranch %334 -%334 = OpLabel -OpLoopMerge %336 %362 None -OpBranch %361 +%299 = OpLabel +OpControlBarrier %55 %55 %56 +%340 = OpAccessChain %129 %21 %55 +%341 = OpLoad %8 %340 +%342 = OpExtInst %8 %1 UMin %341 %13 +%343 = OpAccessChain %129 %21 %13 +%344 = OpLoad %8 %343 +%345 = OpExtInst %8 %1 UMin %344 %15 +%346 = OpAccessChain %132 %21 %59 +%347 = OpAccessChain %150 %21 %15 +OpControlBarrier %55 %55 %56 +OpSetMeshOutputsEXT %342 %345 +OpStore %297 %296 +OpBranch %348 +%348 = OpLabel +OpLoopMerge %350 %360 None +OpBranch %359 +%359 = OpLabel +%362 = OpLoad %8 %297 +%363 = OpULessThan %5 %362 %342 +OpBranchConditional %363 %361 %350 %361 = OpLabel -%364 = OpLoad %8 %282 -%365 = OpULessThan %5 %364 %330 -OpBranchConditional %365 %363 %336 -%363 = OpLabel -%351 = OpLoad %8 %282 -%352 = OpAccessChain %137 %332 %351 %46 -%353 = OpLoad %9 %352 -%354 = OpAccessChain %176 %297 %351 -OpStore %354 %353 -%355 = OpAccessChain %139 %332 %351 %15 -%356 = OpLoad %5 %355 -%357 = OpAccessChain %180 %291 %351 %46 -OpStore %357 %356 -%358 = OpAccessChain %119 %332 %351 %42 -%359 = OpLoad %4 %358 -%360 = OpAccessChain %161 %300 %351 -OpStore %360 %359 -OpBranch %362 -%362 = OpLabel -%366 = OpLoad %8 %282 -%367 = OpIAdd %8 %366 %15 -OpStore %282 %367 -OpBranch %334 -%336 = OpLabel +%352 = OpLoad %8 %297 +%353 = OpAccessChain %134 %346 %352 %59 +%354 = OpLoad %4 %353 +%355 = OpAccessChain %175 %303 %352 %59 +OpStore %355 %354 +%356 = OpAccessChain %134 %346 %352 %15 +%357 = OpLoad %4 %356 +%358 = OpAccessChain %175 %310 %352 +OpStore %358 %357 +OpBranch %360 +%360 = OpLabel +%364 = OpLoad %8 %297 +%365 = OpIAdd %8 %364 %55 +OpStore %297 %365 +OpBranch %348 +%350 = OpLabel +OpStore %298 %296 +OpBranch %349 +%349 = OpLabel +OpLoopMerge %351 %377 None +OpBranch %376 +%376 = OpLabel +%379 = OpLoad %8 %298 +%380 = OpULessThan %5 %379 %345 +OpBranchConditional %380 %378 %351 +%378 = OpLabel +%366 = OpLoad %8 %298 +%367 = OpAccessChain %152 %347 %366 %59 +%368 = OpLoad %9 %367 +%369 = OpAccessChain %190 %313 %366 +OpStore %369 %368 +%370 = OpAccessChain %154 %347 %366 %15 +%371 = OpLoad %5 %370 +%372 = OpAccessChain %194 %307 %366 %59 +OpStore %372 %371 +%373 = OpAccessChain %134 %347 %366 %55 +%374 = OpLoad %4 %373 +%375 = OpAccessChain %175 %316 %366 +OpStore %375 %374 +OpBranch %377 +%377 = OpLabel +%381 = OpLoad %8 %298 +%382 = OpIAdd %8 %381 %55 +OpStore %298 %382 +OpBranch %349 +%351 = OpLabel OpReturn OpFunctionEnd -%379 = OpFunction %2 None %25 -%368 = OpLabel -%372 = OpLoad %4 %370 -%374 = OpLoad %4 %373 -%369 = OpCompositeConstruct %7 %372 %374 -%377 = OpLoad %4 %376 -%375 = OpCompositeConstruct %11 %377 -OpBranch %380 -%380 = OpLabel -%381 = OpCompositeExtract %4 %369 1 -%382 = OpCompositeExtract %4 %375 0 -%383 = OpFMul %4 %381 %382 -OpStore %378 %383 +%394 = OpFunction %2 None %38 +%383 = OpLabel +%387 = OpLoad %4 %385 +%389 = OpLoad %4 %388 +%384 = OpCompositeConstruct %7 %387 %389 +%392 = OpLoad %4 %391 +%390 = OpCompositeConstruct %11 %392 +OpBranch %395 +%395 = OpLabel +%396 = OpCompositeExtract %4 %384 1 +%397 = OpCompositeExtract %4 %390 0 +%398 = OpFMul %4 %396 %397 +OpStore %393 %398 OpReturn OpFunctionEnd \ No newline at end of file diff --git a/naga/tests/out/wgsl/wgsl-mesh-shader.wgsl b/naga/tests/out/wgsl/wgsl-mesh-shader.wgsl index 974027fdbb4..93372453ce5 100644 --- a/naga/tests/out/wgsl/wgsl-mesh-shader.wgsl +++ b/naga/tests/out/wgsl/wgsl-mesh-shader.wgsl @@ -31,17 +31,29 @@ var taskPayload: TaskPayload; var workgroupData: f32; var mesh_output: MeshOutput; +fn helper_reader() -> bool { + let _e2 = taskPayload.visible; + return _e2; +} + +fn helper_writer(value: bool) { + taskPayload.visible = value; + return; +} + @task @payload(taskPayload) @workgroup_size(1, 1, 1) fn ts_main() -> @builtin(mesh_task_size) vec3 { workgroupData = 1f; taskPayload.colorMask = vec4(1f, 1f, 0f, 1f); - taskPayload.visible = true; + helper_writer(true); + let _e12 = helper_reader(); + taskPayload.visible = _e12; return vec3(1u, 1u, 1u); } @task @payload(taskPayload) @workgroup_size(2, 1, 1) -fn ts_divergent(@builtin(local_invocation_index) thread_id: u32) -> @builtin(mesh_task_size) vec3 { - if (thread_id == 0u) { +fn ts_divergent(@builtin(local_invocation_id) thread_id: vec3) -> @builtin(mesh_task_size) vec3 { + if (thread_id.x == 0u) { taskPayload.colorMask = vec4(1f, 1f, 0f, 1f); taskPayload.visible = true; return vec3(1u, 1u, 1u); @@ -64,8 +76,8 @@ fn ms_main() { let _e67 = taskPayload.colorMask; mesh_output.vertices[2].color = (vec4(1f, 0f, 0f, 1f) * _e67); mesh_output.primitives[0].indices = vec3(0u, 1u, 2u); - let _e88 = taskPayload.visible; - mesh_output.primitives[0].cull = !(_e88); + let _e86 = helper_reader(); + mesh_output.primitives[0].cull = !(_e86); mesh_output.primitives[0].colorMask = vec4(1f, 0f, 1f, 1f); return; } @@ -87,9 +99,9 @@ fn ms_no_ts() { return; } -@mesh(mesh_output) @workgroup_size(1, 1, 1) -fn ms_divergent(@builtin(local_invocation_index) thread_id_1: u32) { - if (thread_id_1 == 0u) { +@mesh(mesh_output) @workgroup_size(2, 1, 1) +fn ms_divergent(@builtin(local_invocation_id) thread_id_1: vec3) { + if (thread_id_1.x == 0u) { mesh_output.vertex_count = 3u; mesh_output.primitive_count = 1u; workgroupData = 2f; diff --git a/naga/xtask/src/validate.rs b/naga/xtask/src/validate.rs index 44728584810..3ac912c9f85 100644 --- a/naga/xtask/src/validate.rs +++ b/naga/xtask/src/validate.rs @@ -327,8 +327,13 @@ fn push_job_for_each_hlsl_config_item( vertex, fragment, compute, + task, + mesh, } = hlsl_snapshots::Config::from_path(path.with_extension("ron"))?; - for shader in [vertex, fragment, compute].into_iter().flatten() { + for shader in [vertex, fragment, compute, task, mesh] + .into_iter() + .flatten() + { // Let each job closure stand on its own. let mut validator = validator.clone(); let path = path.to_owned(); diff --git a/tests/tests/wgpu-gpu/mesh_shader/basic.hlsl b/tests/tests/wgpu-gpu/mesh_shader/basic.hlsl deleted file mode 100644 index dc587df737d..00000000000 --- a/tests/tests/wgpu-gpu/mesh_shader/basic.hlsl +++ /dev/null @@ -1,63 +0,0 @@ -struct OutVertex -{ - float4 Position : SV_POSITION; - float4 Color : COLOR; -}; -struct InVertex -{ - float4 Color : COLOR; -}; - -static const float4 positions[3] = { float4(0., 1.0, 0., 1.0), float4(-1.0, -1.0, 0., 1.0), float4(1.0, -1.0, 0., 1.0) }; -static const float4 colors[3] = { float4(0., 1., 0., 1.), float4(0., 0., 1., 1.), float4(1., 0., 0., 1.) }; - -struct EmptyPayload -{ - uint _nullField; -}; -groupshared EmptyPayload _emptyPayload; - -[numthreads(1, 1, 1)] -void Task() -{ - DispatchMesh(1, 1, 1, _emptyPayload); -} - -[outputtopology("triangle")] -[numthreads(1, 1, 1)] -void Mesh(out indices uint3 triangles[1], out vertices OutVertex vertices[3], in payload EmptyPayload _emptyPayload) -{ - SetMeshOutputCounts(3, 1); - - vertices[0].Position = positions[0]; - vertices[1].Position = positions[1]; - vertices[2].Position = positions[2]; - - vertices[0].Color = colors[0]; - vertices[1].Color = colors[1]; - vertices[2].Color = colors[2]; - - triangles[0] = uint3(0, 1, 2); -} - -[outputtopology("triangle")] -[numthreads(1, 1, 1)] -void MeshNoTask(out indices uint3 triangles[1], out vertices OutVertex vertices[3]) -{ - SetMeshOutputCounts(3, 1); - - vertices[0].Position = positions[0]; - vertices[1].Position = positions[1]; - vertices[2].Position = positions[2]; - - vertices[0].Color = colors[0]; - vertices[1].Color = colors[1]; - vertices[2].Color = colors[2]; - - triangles[0] = uint3(0, 1, 2); -} - -float4 Frag(InVertex vertex) : SV_Target -{ - return vertex.Color; -} diff --git a/tests/tests/wgpu-gpu/mesh_shader/mod.rs b/tests/tests/wgpu-gpu/mesh_shader/mod.rs index f188e742db8..b53460d6863 100644 --- a/tests/tests/wgpu-gpu/mesh_shader/mod.rs +++ b/tests/tests/wgpu-gpu/mesh_shader/mod.rs @@ -1,5 +1,3 @@ -use std::hash::{DefaultHasher, Hash, Hasher}; - use wgpu::util::DeviceExt; use wgpu_test::{ gpu_test, GpuTestConfiguration, GpuTestInitializer, TestParameters, TestingContext, @@ -29,47 +27,6 @@ fn compile_wgsl(device: &wgpu::Device) -> wgpu::ShaderModule { source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), }) } -fn compile_hlsl( - device: &wgpu::Device, - entry: &str, - stage_str: &str, - test_name: &str, -) -> wgpu::ShaderModule { - // Each test needs its own files - let out_path = format!( - "{}/tests/wgpu-gpu/mesh_shader/{test_name}.{stage_str}.cso", - env!("CARGO_MANIFEST_DIR") - ); - let cmd = std::process::Command::new("dxc") - .args([ - "-T", - &format!("{stage_str}_6_5"), - "-E", - entry, - &format!( - "{}/tests/wgpu-gpu/mesh_shader/basic.hlsl", - env!("CARGO_MANIFEST_DIR") - ), - "-Fo", - &out_path, - ]) - .output() - .unwrap(); - if !cmd.status.success() { - panic!("DXC failed:\n{}", String::from_utf8(cmd.stderr).unwrap()); - } - let file = std::fs::read(&out_path).unwrap(); - std::fs::remove_file(out_path).unwrap(); - unsafe { - device.create_shader_module_passthrough(wgpu::ShaderModuleDescriptorPassthrough { - entry_point: entry.to_owned(), - label: None, - num_workgroups: (1, 1, 1), - dxil: Some(std::borrow::Cow::Owned(file)), - ..Default::default() - }) - } -} fn compile_msl(device: &wgpu::Device, entry: &str) -> wgpu::ShaderModule { unsafe { @@ -86,7 +43,6 @@ fn compile_msl(device: &wgpu::Device, entry: &str) -> wgpu::ShaderModule { fn get_shaders( device: &wgpu::Device, backend: wgpu::Backend, - test_name: &str, info: &MeshPipelineTestInfo, ) -> ( Option, @@ -102,7 +58,7 @@ fn get_shaders( // In the case that the platform does support mesh shaders, the dummy // shader is used to avoid requiring EXPERIMENTAL_PASSTHROUGH_SHADERS. match backend { - wgpu::Backend::Vulkan => ( + wgpu::Backend::Vulkan | wgpu::Backend::Dx12 => ( info.use_task.then(|| compile_wgsl(device)), compile_wgsl(device), info.use_frag.then(|| compile_wgsl(device)), @@ -116,21 +72,6 @@ fn get_shaders( }, "fs_main", ), - wgpu::Backend::Dx12 => ( - info.use_task - .then(|| compile_hlsl(device, "Task", "as", test_name)), - compile_hlsl( - device, - if info.use_task { "Mesh" } else { "MeshNoTask" }, - "ms", - test_name, - ), - info.use_frag - .then(|| compile_hlsl(device, "Frag", "ps", test_name)), - "main", - "main", - "main", - ), wgpu::Backend::Metal => ( info.use_task.then(|| compile_msl(device, "taskShader")), compile_msl( @@ -186,20 +127,12 @@ struct MeshPipelineTestInfo { divergent: bool, } -fn hash_testing_context(ctx: &TestingContext) -> u64 { - let mut hasher = DefaultHasher::new(); - ctx.hash(&mut hasher); - hasher.finish() -} - fn mesh_pipeline_build(ctx: &TestingContext, info: MeshPipelineTestInfo) { let backend = ctx.adapter.get_info().backend; let device = &ctx.device; let (_depth_image, depth_view, depth_state) = create_depth(device); - let test_hash = hash_testing_context(ctx).to_string(); - let (task, mesh, frag, ts_name, ms_name, fs_name) = - get_shaders(device, backend, &test_hash, &info); + let (task, mesh, frag, ts_name, ms_name, fs_name) = get_shaders(device, backend, &info); let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, bind_group_layouts: &[], @@ -275,10 +208,8 @@ fn mesh_draw(ctx: &TestingContext, draw_type: DrawType, info: MeshPipelineTestIn let backend = ctx.adapter.get_info().backend; let device = &ctx.device; let (_depth_image, depth_view, depth_state) = create_depth(device); - let test_hash = hash_testing_context(ctx).to_string(); - let (task, mesh, frag, ts_name, ms_name, fs_name) = - get_shaders(device, backend, &test_hash, &info); + let (task, mesh, frag, ts_name, ms_name, fs_name) = get_shaders(device, backend, &info); let frag = frag.unwrap(); let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, diff --git a/tests/tests/wgpu-gpu/mesh_shader/shader.wgsl b/tests/tests/wgpu-gpu/mesh_shader/shader.wgsl index 13f6c225e46..8a8d6de1195 100644 --- a/tests/tests/wgpu-gpu/mesh_shader/shader.wgsl +++ b/tests/tests/wgpu-gpu/mesh_shader/shader.wgsl @@ -96,9 +96,9 @@ fn ms_no_ts() { @mesh(mesh_output) @workgroup_size(2) -fn ms_divergent(@builtin(local_invocation_index) index: u32) { +fn ms_divergent(@builtin(local_invocation_id) thread_id: vec3) { // Workgroup with 2 threads. They return at different points. - if index == 0 { + if thread_id.x == 0 { mesh_output.vertex_count = 3; mesh_output.primitive_count = 1; workgroupData = 2.0;