diff --git a/naga/src/back/glsl/mod.rs b/naga/src/back/glsl/mod.rs index 89343687de8..e96b86541da 100644 --- a/naga/src/back/glsl/mod.rs +++ b/naga/src/back/glsl/mod.rs @@ -246,6 +246,8 @@ bitflags::bitflags! { /// The variable gl_PointSize is intended for a shader to write the size of the point to be rasterized. It is measured in pixels. /// If gl_PointSize is not written to, its value is undefined in subsequent pipe stages. const FORCE_POINT_SIZE = 0x10; + /// Emit debug printf statements + const EMIT_DEBUG_PRINTF = 0x20; } } @@ -2298,10 +2300,16 @@ impl<'a, W: Write> Writer<'a, W> { ref format, ref arguments, } => { - write!(self.out, "{level}")?; - write!(self.out, "debugPrintfEXT(\"{format}\",")?; - self.write_slice(arguments, |this, _, arg| this.write_expr(*arg, ctx))?; - writeln!(self.out, ");")? + if self + .options + .writer_flags + .contains(WriterFlags::EMIT_DEBUG_PRINTF) + { + write!(self.out, "{level}")?; + write!(self.out, "debugPrintfEXT(\"{format}\",")?; + self.write_slice(arguments, |this, _, arg| this.write_expr(*arg, ctx))?; + writeln!(self.out, ");")? + } } } diff --git a/naga/src/back/hlsl/mod.rs b/naga/src/back/hlsl/mod.rs index f3a6f9106c2..b3b0ee6222d 100644 --- a/naga/src/back/hlsl/mod.rs +++ b/naga/src/back/hlsl/mod.rs @@ -175,11 +175,23 @@ pub enum EntryPointError { MissingBinding(crate::ResourceBinding), } +bitflags::bitflags! { + #[cfg_attr(feature = "serialize", derive(serde::Serialize))] + #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] + #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Default)] + pub struct WriterFlags: u32 { + /// Emit debug printf statements + const EMIT_DEBUG_PRINTF = 0x1; + } +} + /// Configuration used in the [`Writer`]. #[derive(Clone, Debug, Hash, PartialEq, Eq)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] pub struct Options { + /// Configuration flags for the writer. + pub flags: WriterFlags, /// The hlsl shader model to be used pub shader_model: ShaderModel, /// Map of resources association to binding locations. @@ -198,6 +210,7 @@ pub struct Options { impl Default for Options { fn default() -> Self { Options { + flags: WriterFlags::empty(), shader_model: ShaderModel::V5_1, binding_map: BindingMap::default(), fake_missing_bindings: true, diff --git a/naga/src/back/hlsl/writer.rs b/naga/src/back/hlsl/writer.rs index 21c1dc1fbc3..08bfb872e61 100644 --- a/naga/src/back/hlsl/writer.rs +++ b/naga/src/back/hlsl/writer.rs @@ -4,7 +4,7 @@ use super::{ BackendResult, Error, Options, }; use crate::{ - back, + back::{self, hlsl::WriterFlags}, proc::{self, NameKey}, valid, Handle, Module, ScalarKind, ShaderStage, TypeInner, }; @@ -2008,15 +2008,17 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { ref format, ref arguments, } => { - write!(self.out, "{level}")?; - write!(self.out, "printf(\"{format}\",")?; - for (index, argument) in arguments.iter().enumerate() { - if index != 0 { - write!(self.out, ", ")?; + if self.options.flags.contains(WriterFlags::EMIT_DEBUG_PRINTF) { + write!(self.out, "{level}")?; + write!(self.out, "printf(\"{format}\",")?; + for (index, argument) in arguments.iter().enumerate() { + if index != 0 { + write!(self.out, ", ")?; + } + self.write_expr(module, *argument, func_ctx)?; } - self.write_expr(module, *argument, func_ctx)?; + writeln!(self.out, ");")? } - writeln!(self.out, ");")? } } diff --git a/naga/src/back/msl/writer.rs b/naga/src/back/msl/writer.rs index 52ed1fe2ab2..419ee09a73d 100644 --- a/naga/src/back/msl/writer.rs +++ b/naga/src/back/msl/writer.rs @@ -3011,7 +3011,7 @@ impl Writer { } } crate::Statement::DebugPrintf { .. } => { - return Err(Error::FeatureNotImplemented("debug printf".to_string())); + // metal doesn't provide a debug printf implementation } } } diff --git a/naga/src/back/spv/block.rs b/naga/src/back/spv/block.rs index abfcdad9cd2..519e38ef428 100644 --- a/naga/src/back/spv/block.rs +++ b/naga/src/back/spv/block.rs @@ -2343,27 +2343,29 @@ impl<'w> BlockContext<'w> { ref format, ref arguments, } => { - self.writer.use_extension("SPV_KHR_non_semantic_info"); - let format_id = self.gen_id(); - self.writer - .strings - .push(Instruction::string(format, format_id)); - let id = self.gen_id(); + if self.writer.flags.contains(WriterFlags::EMIT_DEBUG_PRINTF) { + self.writer.use_extension("SPV_KHR_non_semantic_info"); + let format_id = self.gen_id(); + self.writer + .strings + .push(Instruction::string(format, format_id)); + let id = self.gen_id(); - self.temp_list.clear(); - self.temp_list.push(format_id); - for &argument in arguments { - self.temp_list.push(self.cached[argument]); - } + self.temp_list.clear(); + self.temp_list.push(format_id); + for &argument in arguments { + self.temp_list.push(self.cached[argument]); + } - let set_id = self.writer.extension_inst_import("NonSemantic.DebugPrintf"); - block.body.push(Instruction::ext_inst( - set_id, - 1, - self.writer.void_type, - id, - &self.temp_list, - )); + let set_id = self.writer.extension_inst_import("NonSemantic.DebugPrintf"); + block.body.push(Instruction::ext_inst( + set_id, + 1, + self.writer.void_type, + id, + &self.temp_list, + )); + } } } } diff --git a/naga/src/back/spv/mod.rs b/naga/src/back/spv/mod.rs index 0c44195ed8a..beea5226f31 100644 --- a/naga/src/back/spv/mod.rs +++ b/naga/src/back/spv/mod.rs @@ -638,7 +638,9 @@ pub struct Writer { } bitflags::bitflags! { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[cfg_attr(feature = "serialize", derive(serde::Serialize))] + #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] + #[derive(Clone, Copy, Debug, Eq, PartialEq, Default)] pub struct WriterFlags: u32 { /// Include debug labels for everything. const DEBUG = 0x1; @@ -653,6 +655,8 @@ bitflags::bitflags! { const FORCE_POINT_SIZE = 0x8; /// Clamp `BuiltIn::FragDepth` output between 0 and 1. const CLAMP_FRAG_DEPTH = 0x10; + /// Emit debug printf statements + const EMIT_DEBUG_PRINTF = 0x20; } } diff --git a/naga/src/back/wgsl/writer.rs b/naga/src/back/wgsl/writer.rs index 45fc0de62c8..9a21d36edea 100644 --- a/naga/src/back/wgsl/writer.rs +++ b/naga/src/back/wgsl/writer.rs @@ -54,10 +54,12 @@ enum Indirection { bitflags::bitflags! { #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] - #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, Default)] pub struct WriterFlags: u32 { /// Always annotate the type information instead of inferring. const EXPLICIT_TYPES = 0x1; + /// Emit debug printf statements + const EMIT_DEBUG_PRINTF = 0x2; } } @@ -925,15 +927,17 @@ impl Writer { ref format, ref arguments, } => { - write!(self.out, "{level}")?; - write!(self.out, "debugPrintf(\"{format}\",")?; - for (index, &argument) in arguments.iter().enumerate() { - if index != 0 { - write!(self.out, ", ")?; + if self.flags.contains(WriterFlags::EMIT_DEBUG_PRINTF) { + write!(self.out, "{level}")?; + write!(self.out, "debugPrintf(\"{format}\",")?; + for (index, &argument) in arguments.iter().enumerate() { + if index != 0 { + write!(self.out, ", ")?; + } + self.write_expr(module, argument, func_ctx)?; } - self.write_expr(module, argument, func_ctx)?; + writeln!(self.out, ");")? } - writeln!(self.out, ");")? } } diff --git a/naga/tests/in/binding-arrays.param.ron b/naga/tests/in/binding-arrays.param.ron index 39d6c03664e..652bebdf241 100644 --- a/naga/tests/in/binding-arrays.param.ron +++ b/naga/tests/in/binding-arrays.param.ron @@ -2,6 +2,7 @@ god_mode: true, hlsl: ( shader_model: V5_1, + flags: (""), binding_map: { (group: 0, binding: 0): (space: 0, register: 0, binding_array_size: Some(10)), (group: 0, binding: 1): (space: 1, register: 0), diff --git a/naga/tests/in/debug-printf.param.ron b/naga/tests/in/debug-printf.param.ron index a0f37d53254..6167f322a41 100644 --- a/naga/tests/in/debug-printf.param.ron +++ b/naga/tests/in/debug-printf.param.ron @@ -1,3 +1,16 @@ ( god_mode: true, + spv: ( + version: (1, 1), + emit_debug_printf: true, + ), + wgsl: ( + emit_debug_printf: true, + ), + glsl: ( + version: Desktop(450), + writer_flags: ("EMIT_DEBUG_PRINTF"), + binding_map: {}, + zero_initialize_workgroup_memory: true, + ), ) diff --git a/naga/tests/in/interface.param.ron b/naga/tests/in/interface.param.ron index 4d85661767b..75adcc8e2e1 100644 --- a/naga/tests/in/interface.param.ron +++ b/naga/tests/in/interface.param.ron @@ -9,6 +9,7 @@ ), hlsl: ( shader_model: V5_1, + flags: (""), binding_map: {}, fake_missing_bindings: false, special_constants_binding: Some((space: 1, register: 0)), diff --git a/naga/tests/in/push-constants.param.ron b/naga/tests/in/push-constants.param.ron index 083d028bbfa..8f893610127 100644 --- a/naga/tests/in/push-constants.param.ron +++ b/naga/tests/in/push-constants.param.ron @@ -11,6 +11,7 @@ ), hlsl: ( shader_model: V5_1, + flags: (""), binding_map: {}, fake_missing_bindings: true, special_constants_binding: Some((space: 1, register: 0)), diff --git a/naga/tests/in/skybox.param.ron b/naga/tests/in/skybox.param.ron index 4d7fdf73478..a9e8a2ccee9 100644 --- a/naga/tests/in/skybox.param.ron +++ b/naga/tests/in/skybox.param.ron @@ -51,6 +51,7 @@ ), hlsl: ( shader_model: V5_1, + flags: (""), binding_map: { (group: 0, binding: 0): (space: 0, register: 0), (group: 0, binding: 1): (space: 0, register: 0), diff --git a/naga/tests/in/spv/debug-printf-s.param.ron b/naga/tests/in/spv/debug-printf-s.param.ron index a0f37d53254..6167f322a41 100644 --- a/naga/tests/in/spv/debug-printf-s.param.ron +++ b/naga/tests/in/spv/debug-printf-s.param.ron @@ -1,3 +1,16 @@ ( god_mode: true, + spv: ( + version: (1, 1), + emit_debug_printf: true, + ), + wgsl: ( + emit_debug_printf: true, + ), + glsl: ( + version: Desktop(450), + writer_flags: ("EMIT_DEBUG_PRINTF"), + binding_map: {}, + zero_initialize_workgroup_memory: true, + ), ) diff --git a/naga/tests/out/glsl/debug-printf-s.main.Compute.glsl b/naga/tests/out/glsl/debug-printf-s.main.Compute.glsl index 2cd87e2b25d..6c2103fd2dc 100644 --- a/naga/tests/out/glsl/debug-printf-s.main.Compute.glsl +++ b/naga/tests/out/glsl/debug-printf-s.main.Compute.glsl @@ -8,7 +8,6 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main_1() { - debugPrintfEXT("%d",42); return; } diff --git a/naga/tests/out/glsl/debug-printf.main.Compute.glsl b/naga/tests/out/glsl/debug-printf.main.Compute.glsl index 0923ee6cdc2..58abf6dd16a 100644 --- a/naga/tests/out/glsl/debug-printf.main.Compute.glsl +++ b/naga/tests/out/glsl/debug-printf.main.Compute.glsl @@ -1,9 +1,6 @@ -#version 310 es +#version 450 core +#extension GL_ARB_compute_shader : require #extension GL_EXT_debug_printf : enable - -precision highp float; -precision highp int; - layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; diff --git a/naga/tests/out/wgsl/debug-printf-s.wgsl b/naga/tests/out/wgsl/debug-printf-s.wgsl index b99f6522c9e..beb39cf5054 100644 --- a/naga/tests/out/wgsl/debug-printf-s.wgsl +++ b/naga/tests/out/wgsl/debug-printf-s.wgsl @@ -1,5 +1,4 @@ fn main_1() { - debugPrintf("%d",42); return; } diff --git a/naga/tests/snapshots.rs b/naga/tests/snapshots.rs index 4144c9c9377..3a2bb7fbd61 100644 --- a/naga/tests/snapshots.rs +++ b/naga/tests/snapshots.rs @@ -49,6 +49,8 @@ struct SpirvOutParameters { #[serde(default)] separate_entry_points: bool, #[serde(default)] + emit_debug_printf: bool, + #[serde(default)] #[cfg(all(feature = "deserialize", feature = "spv-out"))] binding_map: naga::back::spv::BindingMap, } @@ -57,6 +59,8 @@ struct SpirvOutParameters { struct WgslOutParameters { #[serde(default)] explicit_types: bool, + #[serde(default)] + emit_debug_printf: bool, } #[derive(Default, serde::Deserialize)] @@ -405,6 +409,10 @@ fn write_output_spv( ); flags.set(spv::WriterFlags::FORCE_POINT_SIZE, params.force_point_size); flags.set(spv::WriterFlags::CLAMP_FRAG_DEPTH, params.clamp_frag_depth); + flags.set( + spv::WriterFlags::EMIT_DEBUG_PRINTF, + params.emit_debug_printf, + ); let options = spv::Options { lang_version: (params.version.0, params.version.1), @@ -589,6 +597,10 @@ fn write_output_wgsl( let mut flags = wgsl::WriterFlags::empty(); flags.set(wgsl::WriterFlags::EXPLICIT_TYPES, params.explicit_types); + flags.set( + wgsl::WriterFlags::EMIT_DEBUG_PRINTF, + params.emit_debug_printf, + ); let string = wgsl::write_string(module, info, flags).expect("WGSL write failed"); diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 84146a006b2..7b449fbe7bf 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -1052,6 +1052,7 @@ impl crate::Device for super::Device { // FXC doesn't support SM 6.0 None => hlsl::ShaderModel::V5_1, }, + flags: hlsl::WriterFlags::default(), binding_map, fake_missing_bindings: false, special_constants_binding, diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index e17be43d5ea..c30f23be291 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -1288,6 +1288,10 @@ impl super::Adapter { // But this requires cloning the `spv::Options` struct, which has heap allocations. true, // could check `super::Workarounds::SEPARATE_ENTRY_POINTS` ); + flags.set( + spv::WriterFlags::EMIT_DEBUG_PRINTF, + features.contains(wgt::Features::DEBUG_PRINTF), + ); spv::Options { lang_version: (1, 0), flags,