Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debug printf in shaders #4297

Open
wants to merge 17 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions naga/hlsl-snapshots/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,5 @@ pub struct ConfigItem {
/// See also
/// <https://learn.microsoft.com/en-us/windows/win32/direct3dtools/dx-graphics-tools-fxc-using>.
pub target_profile: String,
pub debug_printf: bool,
}
6 changes: 6 additions & 0 deletions naga/src/back/dot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,12 @@ impl StatementGraph {
crate::RayQueryFunction::Terminate => "RayQueryTerminate",
}
}
S::DebugPrintf { ref arguments, .. } => {
for &arg in arguments {
self.dependencies.push((id, arg, "arg"));
}
"DebugPrintf"
}
};
// Set the last node to the merge node
last_node = merge_id;
Expand Down
22 changes: 22 additions & 0 deletions naga/src/back/glsl/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ bitflags::bitflags! {
///
/// We can always support this, either through the language or a polyfill
const INSTANCE_INDEX = 1 << 22;
/// Debug Printf
const DEBUG_PRINTF = 1 << 23;
}
}

Expand Down Expand Up @@ -243,6 +245,10 @@ impl FeaturesManager {
// https://registry.khronos.org/OpenGL/extensions/EXT/EXT_blend_func_extended.txt
writeln!(out, "#extension GL_EXT_blend_func_extended : require")?;
}
if self.0.contains(Features::DEBUG_PRINTF) {
// https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GLSL_EXT_debug_printf.txt
writeln!(out, "#extension GL_EXT_debug_printf : enable")?;
}

if self.0.contains(Features::INSTANCE_INDEX) {
if options.writer_flags.contains(WriterFlags::DRAW_PARAMETERS) {
Expand Down Expand Up @@ -420,6 +426,22 @@ impl<'a, W> Writer<'a, W> {
..
} = self;

for block in module
.functions
.iter()
.map(|(_, f)| &f.body)
.chain(std::iter::once(&entry_point.function.body))
{
for statement in block.iter() {
match *statement {
crate::Statement::DebugPrintf { .. } => {
features.request(Features::DEBUG_PRINTF)
}
_ => {}
}
}
}

// Loop trough all expressions in both functions and the entry point
// to check for needed features
for (expressions, info) in module
Expand Down
17 changes: 17 additions & 0 deletions naga/src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,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 = 0x20;
/// Emit debug printf statements
const EMIT_DEBUG_PRINTF = 0x40;
}
}

Expand Down Expand Up @@ -2379,6 +2381,21 @@ impl<'a, W: Write> Writer<'a, W> {
writeln!(self.out, ");")?;
}
Statement::RayQuery { .. } => unreachable!(),
Statement::DebugPrintf {
ref format,
ref arguments,
} => {
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, ");")?
}
}
}

Ok(())
Expand Down
13 changes: 13 additions & 0 deletions naga/src/back/hlsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand Down
18 changes: 17 additions & 1 deletion naga/src/back/hlsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -2000,6 +2000,22 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
writeln!(self.out, "{level}}}")?
}
Statement::RayQuery { .. } => unreachable!(),
Statement::DebugPrintf {
ref format,
ref arguments,
} => {
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)?;
}
writeln!(self.out, ");")?
}
}
}

Ok(())
Expand Down
3 changes: 3 additions & 0 deletions naga/src/back/msl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3040,6 +3040,9 @@ impl<W: Write> Writer<W> {
}
}
}
crate::Statement::DebugPrintf { .. } => {
// metal doesn't provide a debug printf implementation
}
}
}

Expand Down
57 changes: 43 additions & 14 deletions naga/src/back/spv/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,9 @@ impl Writer {
));

let clamp_id = self.id_gen.next();
body.push(Instruction::ext_inst(
self.gl450_ext_inst_id,

body.push(Instruction::ext_inst_glsl_std(
self.extension_inst_import("GLSL.std.450"),
spirv::GLOp::FClamp,
float_type_id,
clamp_id,
Expand Down Expand Up @@ -765,8 +766,8 @@ impl<'w> BlockContext<'w> {
arg2_id = self.writer.get_constant_composite(ty, &self.temp_list);
}

MathOp::Custom(Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
MathOp::Custom(Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
spirv::GLOp::FClamp,
result_type_id,
id,
Expand Down Expand Up @@ -884,8 +885,8 @@ impl<'w> BlockContext<'w> {
&self.temp_list,
));

MathOp::Custom(Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
MathOp::Custom(Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
spirv::GLOp::FMix,
result_type_id,
id,
Expand Down Expand Up @@ -940,16 +941,16 @@ impl<'w> BlockContext<'w> {
};

let lsb_id = self.gen_id();
block.body.push(Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
block.body.push(Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
spirv::GLOp::FindILsb,
result_type_id,
lsb_id,
&[arg0_id],
));

MathOp::Custom(Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
MathOp::Custom(Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
spirv::GLOp::UMin,
result_type_id,
id,
Expand Down Expand Up @@ -993,8 +994,8 @@ impl<'w> BlockContext<'w> {
};

let msb_id = self.gen_id();
block.body.push(Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
block.body.push(Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
spirv::GLOp::FindUMsb,
int_type_id,
msb_id,
Expand Down Expand Up @@ -1058,8 +1059,8 @@ impl<'w> BlockContext<'w> {
};

block.body.push(match math_op {
MathOp::Ext(op) => Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
MathOp::Ext(op) => Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
op,
result_type_id,
id,
Expand Down Expand Up @@ -2333,6 +2334,34 @@ impl<'w> BlockContext<'w> {
crate::Statement::RayQuery { query, ref fun } => {
self.write_ray_query_function(query, fun, &mut block);
}
crate::Statement::DebugPrintf {
ref format,
ref arguments,
} => {
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]);
}

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,
));
}
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions naga/src/back/spv/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,8 @@ impl<'w> BlockContext<'w> {
// and negative values in a single instruction: negative values of
// `input_id` get treated as very large positive values.
let restricted_id = self.gen_id();
block.body.push(Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
block.body.push(Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
spirv::GLOp::UMin,
type_id,
restricted_id,
Expand Down Expand Up @@ -590,8 +590,8 @@ impl<'w> BlockContext<'w> {
// and negative values in a single instruction: negative values of
// `coordinates` get treated as very large positive values.
let restricted_coordinates_id = self.gen_id();
block.body.push(Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
block.body.push(Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
spirv::GLOp::UMin,
coordinates.type_id,
restricted_coordinates_id,
Expand Down
4 changes: 2 additions & 2 deletions naga/src/back/spv/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ impl<'w> BlockContext<'w> {
// One or the other of the index or length is dynamic, so emit code for
// BoundsCheckPolicy::Restrict.
let restricted_index_id = self.gen_id();
block.body.push(Instruction::ext_inst(
self.writer.gl450_ext_inst_id,
block.body.push(Instruction::ext_inst_glsl_std(
self.writer.extension_inst_import("GLSL.std.450"),
spirv::GLOp::UMin,
self.writer.get_uint_type_id(),
restricted_index_id,
Expand Down
14 changes: 12 additions & 2 deletions naga/src/back/spv/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,28 @@ impl super::Instruction {
instruction
}

pub(super) fn ext_inst(
pub(super) fn ext_inst_glsl_std(
set_id: Word,
op: spirv::GLOp,
result_type_id: Word,
id: Word,
operands: &[Word],
) -> Self {
Self::ext_inst(set_id, op as Word, result_type_id, id, operands)
}

pub(super) fn ext_inst(
set_id: Word,
op: Word,
result_type_id: Word,
id: Word,
operands: &[Word],
) -> Self {
let mut instruction = Self::new(Op::ExtInst);
instruction.set_type(result_type_id);
instruction.set_result(id);
instruction.add_operand(set_id);
instruction.add_operand(op as u32);
instruction.add_operand(op);
for operand in operands {
instruction.add_operand(*operand)
}
Expand Down
9 changes: 7 additions & 2 deletions naga/src/back/spv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ pub struct Writer {
/// The set of spirv extensions used.
extensions_used: crate::FastIndexSet<&'static str>,

strings: Vec<Instruction>,
debugs: Vec<Instruction>,
annotations: Vec<Instruction>,
flags: WriterFlags,
Expand All @@ -623,14 +624,16 @@ pub struct Writer {
// retain the table here between functions to save heap allocations.
saved_cached: CachedExpressions,

gl450_ext_inst_id: Word,
ext_inst_ids: crate::FastHashMap<&'static str, Word>,

// Just a temporary list of SPIR-V ids
temp_list: Vec<Word>,
}

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;
Expand All @@ -645,6 +648,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;
}
}

Expand Down
Loading
Loading