impl NestedEntryPointArgs { pubfn write_call_args(&self, out: &mutimpl fmt::Write) -> fmt::Result { let all_args = self
.user_args
.iter()
.map(String::as_str)
.chain(self.task_payload.as_deref())
.chain(core::iter::once(self.local_invocation_index.as_str())); for (i, arg) in all_args.enumerate() { if i != 0 {
write!(out, ", ")?;
}
write!(out, "{arg}")?;
}
Ok(())
}
}
impl<W: fmt::Write> super::Writer<'_, W> { #[expect(clippy::too_many_arguments)] fn write_mesh_shader_wrapper(
&mutself,
module: &Module,
func_ctx: &back::FunctionCtx,
need_workgroup_variables_initialization: bool,
nested_name: &str,
entry_point: &crate::EntryPoint,
args: NestedEntryPointArgs, mut separator_if_needed: impl FnMut() -> &'static str,
) -> BackendResult { let Some(ref mesh_info) = entry_point.mesh_info else {
unreachable!()
}; let back::FunctionType::EntryPoint(ep_index) = func_ctx.ty else {
unreachable!()
}; // Mesh shader wrapper 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 something of the form `out indices uint3 indices_var[num_primitives]`
write!( self.out, "{}out indices {} {}[{}]",
separator_if_needed(),
indices_info.ty_name,
indices_info.arg_name,
mesh_info.max_primitives
)?; // Write something of the form `out vertices VertexType vertices_var[num_vertices]`
write!( self.out, ", out vertices {} {}[{}]",
vert_info.ty_name, vert_info.arg_name, mesh_info.max_vertices
)?; // Write something of the form `out primitives PrimitiveType} primitives_var[num_primitives]`
write!( self.out, ", out primitives {} {}[{}]",
prim_info.ty_name, prim_info.arg_name, mesh_info.max_primitives
)?; iflet Some(task_payload) = entry_point.task_payload { // Write the outer-function `in payload` arg. The name is already in // args.task_payload, having been collected when the inner function // signature was written in write_function (writer.rs).
write!(self.out, ", in payload ")?; let var = &module.global_variables[task_payload]; self.write_type(module, var.ty)?; let name = &self.names[&NameKey::GlobalVariable(task_payload)];
write!(self.out, " {name}")?; iflet TypeInner::Array { base, size, .. } = module.types[var.ty].inner { self.write_array_size(module, base, size)?;
}
}
writeln!(self.out, ") {{")?; if need_workgroup_variables_initialization {
writeln!( self.out, "{}if ({} == 0) {{",
back::INDENT,
args.local_invocation_index,
)?; 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)?;
args.write_call_args(&mutself.out)?;
writeln!(self.out, ");")?;
writeln!( self.out, "{}GroupMemoryBarrierWithGroupSync();",
back::INDENT
)?;
let ep = &module.entry_points[ep_index as usize]; let mesh_info = ep.mesh_info.as_ref().unwrap(); let io = self.entry_point_io.get(&(ep_index 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| { // The mesh shader output type must be a struct with exactly 4 members. 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),
);
writeln!(self.out, "{}) {{", back::INDENT)?;
writeln!(self.out, "{level}{grid_size} = uint3(0, 0, 0);")?;
writeln!(self.out, "{}}}", back::INDENT)?;
}
writeln!( self.out, "{}DispatchMesh({grid_size}.x, {grid_size}.y, {grid_size}.z, {});",
back::INDENT, self.names[&NameKey::GlobalVariable(entry_point.task_payload.unwrap())]
)?;
Ok(())
} /// Mesh and task entry points must all return at the same `return` statement, /// so we have a nested function that can return wherever. This writes the caller, /// or the actual entry point. #[expect(clippy::too_many_arguments)] pub(super) fn write_nested_function_outer(
&mutself,
module: &Module,
func_ctx: &back::FunctionCtx,
header: &str,
name: &str,
need_workgroup_variables_initialization: bool,
nested_name: &str,
entry_point: &crate::EntryPoint, // Built in write_function alongside the inner function signature, so the // call-site argument order is guaranteed to match the declaration order.
args: NestedEntryPointArgs,
) -> BackendResult { letmut any_args_written = false; letmut separator_if_needed = || { 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}(")?; // Write the outer function's argument list with full type annotations and // semantics. Arg names come from self.names and are the same names that // were collected into `args` when writing the inner function signature. iflet 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)?;
} else { for (index, arg) in entry_point.function.arguments.iter().enumerate() {
write!(self.out, "{}", separator_if_needed())?; self.write_type(module, arg.ty)?;
let argument_name =
&self.names[&NameKey::EntryPointArgument(ep_index, index as u32)];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.