diff --git a/naga/src/arena.rs b/naga/src/arena.rs index 740df85b86..f401468dac 100644 --- a/naga/src/arena.rs +++ b/naga/src/arena.rs @@ -112,6 +112,16 @@ impl Handle { const unsafe fn from_usize_unchecked(index: usize) -> Self { Handle::new(Index::new_unchecked((index + 1) as u32)) } + + /// Write this handle's index to `formatter`, preceded by `prefix`. + pub fn write_prefixed( + &self, + formatter: &mut std::fmt::Formatter, + prefix: &'static str, + ) -> std::fmt::Result { + formatter.write_str(prefix)?; + ::fmt(&self.index(), formatter) + } } /// A strongly typed range of handles. diff --git a/naga/src/back/glsl/mod.rs b/naga/src/back/glsl/mod.rs index caca38254f..bc2d2a90d8 100644 --- a/naga/src/back/glsl/mod.rs +++ b/naga/src/back/glsl/mod.rs @@ -46,7 +46,7 @@ to output a [`Module`](crate::Module) into glsl pub use features::Features; use crate::{ - back, + back::{self, Baked}, proc::{self, NameKey}, valid, Handle, ShaderStage, TypeInner, }; @@ -1982,7 +1982,7 @@ impl<'a, W: Write> Writer<'a, W> { // Also, we use sanitized names! It defense backend from generating variable with name from reserved keywords. Some(self.namer.call(name)) } else if self.need_bake_expressions.contains(&handle) { - Some(format!("{}{}", back::BAKE_PREFIX, handle.index())) + Some(Baked(handle).to_string()) } else { None }; @@ -2310,7 +2310,7 @@ impl<'a, W: Write> Writer<'a, W> { // This is done in `Emit` by never emitting a variable name for pointer variables self.write_barrier(crate::Barrier::WORK_GROUP, level)?; - let result_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let result_name = Baked(result).to_string(); write!(self.out, "{level}")?; // Expressions cannot have side effects, so just writing the expression here is fine. self.write_named_expr(pointer, result_name, result, ctx)?; @@ -2335,7 +2335,7 @@ impl<'a, W: Write> Writer<'a, W> { } => { write!(self.out, "{level}")?; if let Some(expr) = result { - let name = format!("{}{}", back::BAKE_PREFIX, expr.index()); + let name = Baked(expr).to_string(); let result = self.module.functions[function].result.as_ref().unwrap(); self.write_type(result.ty)?; write!(self.out, " {name}")?; @@ -2369,7 +2369,7 @@ impl<'a, W: Write> Writer<'a, W> { } => { write!(self.out, "{level}")?; if let Some(result) = result { - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); let res_ty = ctx.resolve_type(result, &self.module.types); self.write_value_type(res_ty)?; write!(self.out, " {res_name} = ")?; @@ -2399,7 +2399,7 @@ impl<'a, W: Write> Writer<'a, W> { Statement::RayQuery { .. } => unreachable!(), Statement::SubgroupBallot { result, predicate } => { write!(self.out, "{level}")?; - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); let res_ty = ctx.info[result].ty.inner_with(&self.module.types); self.write_value_type(res_ty)?; write!(self.out, " {res_name} = ")?; @@ -2419,7 +2419,7 @@ impl<'a, W: Write> Writer<'a, W> { result, } => { write!(self.out, "{level}")?; - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); let res_ty = ctx.info[result].ty.inner_with(&self.module.types); self.write_value_type(res_ty)?; write!(self.out, " {res_name} = ")?; @@ -2476,7 +2476,7 @@ impl<'a, W: Write> Writer<'a, W> { result, } => { write!(self.out, "{level}")?; - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); let res_ty = ctx.info[result].ty.inner_with(&self.module.types); self.write_value_type(res_ty)?; write!(self.out, " {res_name} = ")?; @@ -3865,9 +3865,8 @@ impl<'a, W: Write> Writer<'a, W> { // Define our local and start a call to `clamp` write!( self.out, - "int {}{}{} = clamp(", - back::BAKE_PREFIX, - expr.index(), + "int {}{} = clamp(", + Baked(expr), CLAMPED_LOD_SUFFIX )?; // Write the lod that will be clamped @@ -4205,13 +4204,7 @@ impl<'a, W: Write> Writer<'a, W> { // `textureSize` call, but this needs to be the clamped lod, this should // have been generated earlier and put in a local. if class.is_mipmapped() { - write!( - self.out, - ", {}{}{}", - back::BAKE_PREFIX, - handle.index(), - CLAMPED_LOD_SUFFIX - )?; + write!(self.out, ", {}{}", Baked(handle), CLAMPED_LOD_SUFFIX)?; } // Close the `textureSize` call write!(self.out, ")")?; @@ -4229,13 +4222,7 @@ impl<'a, W: Write> Writer<'a, W> { // Add the clamped lod (if present) as the second argument to the // image load function. if level.is_some() { - write!( - self.out, - ", {}{}{}", - back::BAKE_PREFIX, - handle.index(), - CLAMPED_LOD_SUFFIX - )?; + write!(self.out, ", {}{}", Baked(handle), CLAMPED_LOD_SUFFIX)?; } // If a sample argument is needed we need to clamp it between 0 and diff --git a/naga/src/back/hlsl/writer.rs b/naga/src/back/hlsl/writer.rs index dea37b6b2e..58fe333ad9 100644 --- a/naga/src/back/hlsl/writer.rs +++ b/naga/src/back/hlsl/writer.rs @@ -7,7 +7,7 @@ use super::{ BackendResult, Error, Options, }; use crate::{ - back, + back::{self, Baked}, proc::{self, NameKey}, valid, Handle, Module, ScalarKind, ShaderStage, TypeInner, }; @@ -1891,7 +1891,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { write!(self.out, "{level}")?; if let Some(expr) = result { write!(self.out, "const ")?; - let name = format!("{}{}", back::BAKE_PREFIX, expr.index()); + let name = Baked(expr).to_string(); let expr_ty = &func_ctx.info[expr].ty; match *expr_ty { proc::TypeResolution::Handle(handle) => self.write_type(module, handle)?, @@ -1922,7 +1922,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { let res_name = match result { None => None, Some(result) => { - let name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let name = Baked(result).to_string(); match func_ctx.info[result].ty { proc::TypeResolution::Handle(handle) => { self.write_type(module, handle)? @@ -2099,7 +2099,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { Statement::RayQuery { .. } => unreachable!(), Statement::SubgroupBallot { result, predicate } => { write!(self.out, "{level}")?; - let name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let name = Baked(result).to_string(); write!(self.out, "const uint4 {name} = ")?; self.named_expressions.insert(result, name); @@ -2118,7 +2118,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { } => { write!(self.out, "{level}")?; write!(self.out, "const ")?; - let name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let name = Baked(result).to_string(); match func_ctx.info[result].ty { proc::TypeResolution::Handle(handle) => self.write_type(module, handle)?, proc::TypeResolution::Value(ref value) => { @@ -2182,7 +2182,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { } => { write!(self.out, "{level}")?; write!(self.out, "const ")?; - let name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let name = Baked(result).to_string(); match func_ctx.info[result].ty { proc::TypeResolution::Handle(handle) => self.write_type(module, handle)?, proc::TypeResolution::Value(ref value) => { diff --git a/naga/src/back/mod.rs b/naga/src/back/mod.rs index 72c301d47b..28a726155a 100644 --- a/naga/src/back/mod.rs +++ b/naga/src/back/mod.rs @@ -28,12 +28,26 @@ pub mod pipeline_constants; pub const COMPONENTS: &[char] = &['x', 'y', 'z', 'w']; /// Indent for backends. pub const INDENT: &str = " "; -/// Prefix used for baking. -pub const BAKE_PREFIX: &str = "_e"; /// Expressions that need baking. pub type NeedBakeExpressions = crate::FastHashSet>; +/// A type for displaying expression handles as baking identifiers. +/// +/// Given an [`Expression`] [`Handle`] `h`, `Baked(h)` implements +/// [`std::fmt::Display`], showing the handle's index prefixed by +/// [`BAKE_PREFIX`]. +/// +/// [`Expression`]: crate::Expression +/// [`Handle`]: crate::Handle +struct Baked(crate::Handle); + +impl std::fmt::Display for Baked { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.write_prefixed(f, "_e") + } +} + /// Specifies the values of pipeline-overridable constants in the shader module. /// /// If an `@id` attribute was specified on the declaration, diff --git a/naga/src/back/msl/writer.rs b/naga/src/back/msl/writer.rs index ca5dfbd3c8..62e1b986a6 100644 --- a/naga/src/back/msl/writer.rs +++ b/naga/src/back/msl/writer.rs @@ -1,7 +1,7 @@ use super::{sampler as sm, Error, LocationMode, Options, PipelineOptions, TranslationInfo}; use crate::{ arena::Handle, - back, + back::{self, Baked}, proc::index, proc::{self, NameKey, TypeResolution}, valid, FastHashMap, FastHashSet, @@ -2854,7 +2854,7 @@ impl Writer { }; if bake { - Some(format!("{}{}", back::BAKE_PREFIX, handle.index())) + Some(Baked(handle).to_string()) } else { None } @@ -3009,7 +3009,7 @@ impl Writer { } => { write!(self.out, "{level}")?; if let Some(expr) = result { - let name = format!("{}{}", back::BAKE_PREFIX, expr.index()); + let name = Baked(expr).to_string(); self.start_baking_expression(expr, &context.expression, &name)?; self.named_expressions.insert(expr, name); } @@ -3064,7 +3064,7 @@ impl Writer { // operating on a 64-bit value, `result` is `None`. write!(self.out, "{level}")?; let fun_str = if let Some(result) = result { - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); self.start_baking_expression(result, &context.expression, &res_name)?; self.named_expressions.insert(result, res_name); fun.to_msl()? @@ -3170,7 +3170,7 @@ impl Writer { } crate::RayQueryFunction::Proceed { result } => { write!(self.out, "{level}")?; - let name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let name = Baked(result).to_string(); self.start_baking_expression(result, &context.expression, &name)?; self.named_expressions.insert(result, name); self.put_expression(query, &context.expression, true)?; diff --git a/naga/src/back/wgsl/writer.rs b/naga/src/back/wgsl/writer.rs index 8b61dbd2c5..8cd37830ec 100644 --- a/naga/src/back/wgsl/writer.rs +++ b/naga/src/back/wgsl/writer.rs @@ -1,6 +1,6 @@ use super::Error; use crate::{ - back, + back::{self, Baked}, proc::{self, NameKey}, valid, Handle, Module, ShaderStage, TypeInner, }; @@ -641,7 +641,7 @@ impl Writer { _ => false, }; if min_ref_count <= info.ref_count || required_baking_expr { - Some(format!("{}{}", back::BAKE_PREFIX, handle.index())) + Some(Baked(handle).to_string()) } else { None } @@ -733,7 +733,7 @@ impl Writer { } => { write!(self.out, "{level}")?; if let Some(expr) = result { - let name = format!("{}{}", back::BAKE_PREFIX, expr.index()); + let name = Baked(expr).to_string(); self.start_named_expr(module, expr, func_ctx, &name)?; self.named_expressions.insert(expr, name); } @@ -755,7 +755,7 @@ impl Writer { } => { write!(self.out, "{level}")?; if let Some(result) = result { - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); self.start_named_expr(module, result, func_ctx, &res_name)?; self.named_expressions.insert(result, res_name); } @@ -774,7 +774,7 @@ impl Writer { Statement::WorkGroupUniformLoad { pointer, result } => { write!(self.out, "{level}")?; // TODO: Obey named expressions here. - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); self.start_named_expr(module, result, func_ctx, &res_name)?; self.named_expressions.insert(result, res_name); write!(self.out, "workgroupUniformLoad(")?; @@ -934,7 +934,7 @@ impl Writer { Statement::RayQuery { .. } => unreachable!(), Statement::SubgroupBallot { result, predicate } => { write!(self.out, "{level}")?; - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); self.start_named_expr(module, result, func_ctx, &res_name)?; self.named_expressions.insert(result, res_name); @@ -951,7 +951,7 @@ impl Writer { result, } => { write!(self.out, "{level}")?; - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); self.start_named_expr(module, result, func_ctx, &res_name)?; self.named_expressions.insert(result, res_name); @@ -1006,7 +1006,7 @@ impl Writer { result, } => { write!(self.out, "{level}")?; - let res_name = format!("{}{}", back::BAKE_PREFIX, result.index()); + let res_name = Baked(result).to_string(); self.start_named_expr(module, result, func_ctx, &res_name)?; self.named_expressions.insert(result, res_name);