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

feat(spv): shader debug option #4028

Merged
merged 4 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 deno_webgpu/shader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub fn op_webgpu_create_shader_module(
let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor {
label: label.map(Cow::from),
shader_bound_checks: wgpu_types::ShaderBoundChecks::default(),
debug: false,
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
};

gfx_put!(device => instance.device_create_shader_module(
Expand Down
2 changes: 2 additions & 0 deletions examples/boids/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ impl wgpu_example::framework::Example for Example {
let compute_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("compute.wgsl"))),
debug: false,
});
let draw_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("draw.wgsl"))),
debug: false,
});

// buffer for simulation parameters uniform
Expand Down
1 change: 1 addition & 0 deletions examples/bunnymark/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl wgpu_example::framework::Example for Example {
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!(
"../../../wgpu-hal/examples/halmark/shader.wgsl"
))),
debug: false,
});

let global_bind_group_layout =
Expand Down
2 changes: 2 additions & 0 deletions examples/conservative-raster/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ impl wgpu_example::framework::Example for Example {
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!(
"triangle_and_lines.wgsl"
))),
debug: false,
});

let pipeline_triangle_conservative =
Expand Down Expand Up @@ -197,6 +198,7 @@ impl wgpu_example::framework::Example for Example {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("upscale.wgsl"))),
debug: false,
});
(
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
Expand Down
1 change: 1 addition & 0 deletions examples/cube/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ impl wgpu_example::framework::Example for Example {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

let vertex_buffers = [wgpu::VertexBufferLayout {
Expand Down
1 change: 1 addition & 0 deletions examples/hello-compute/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ async fn execute_gpu_inner(
let cs_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

// Gets the size in bytes of the buffer.
Expand Down
1 change: 1 addition & 0 deletions examples/hello-triangle/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
Expand Down
2 changes: 2 additions & 0 deletions examples/mipmap/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ impl Example {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("blit.wgsl"))),
debug: false,
});

let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
Expand Down Expand Up @@ -282,6 +283,7 @@ impl wgpu_example::framework::Example for Example {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("draw.wgsl"))),
debug: false,
});

let draw_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
Expand Down
1 change: 1 addition & 0 deletions examples/msaa-line/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ impl wgpu_example::framework::Example for Example {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
Expand Down
1 change: 1 addition & 0 deletions examples/shadow/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ impl wgpu_example::framework::Example for Example {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

let shadow_pass = {
Expand Down
1 change: 1 addition & 0 deletions examples/skybox/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ impl wgpu_example::framework::Example for Skybox {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

let camera = Camera {
Expand Down
1 change: 1 addition & 0 deletions examples/stencil-triangles/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl wgpu_example::framework::Example for Triangles {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

let vertex_buffers = [wgpu::VertexBufferLayout {
Expand Down
1 change: 1 addition & 0 deletions examples/timestamp-queries/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ fn submit_render_and_compute_pass_with_queries(
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

encoder.write_timestamp(&queries.set, queries.next_unused_query);
Expand Down
2 changes: 2 additions & 0 deletions examples/water/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,10 +496,12 @@ impl wgpu_example::framework::Example for Example {
let terrain_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("terrain"),
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("terrain.wgsl"))),
debug: false,
});
let water_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("water"),
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("water.wgsl"))),
debug: false,
});

// Create the render pipelines. These describe how the data will flow through the GPU, and what
Expand Down
1 change: 1 addition & 0 deletions player/tests/data/bind-group.ron
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
desc: (
label: None,
flags: (bits: 3),
debug: false,
),
data: "empty.wgsl",
),
Expand Down
1 change: 1 addition & 0 deletions player/tests/data/pipeline-statistics-query.ron
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
desc: (
label: None,
flags: (bits: 3),
debug: false,
),
data: "empty.wgsl",
),
Expand Down
1 change: 1 addition & 0 deletions player/tests/data/quad.ron
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
desc: (
label: None,
flags: (bits: 3),
debug: false,
),
data: "quad.wgsl",
),
Expand Down
1 change: 1 addition & 0 deletions player/tests/data/zero-init-buffer.ron
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
desc: (
label: None,
flags: (bits: 3),
debug: false,
),
data: "zero-init-buffer-for-binding.wgsl",
),
Expand Down
1 change: 1 addition & 0 deletions player/tests/data/zero-init-texture-binding.ron
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
desc: (
label: None,
flags: (bits: 3),
debug: false,
),
data: "zero-init-texture-binding.wgsl",
),
Expand Down
1 change: 1 addition & 0 deletions tests/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ fn copy_via_compute(
let sm = device.create_shader_module(ShaderModuleDescriptor {
label: Some("shader copy_texture_to_buffer.wgsl"),
source: ShaderSource::Wgsl(Cow::Borrowed(&processed_source)),
debug: false,
});

let pipeline_copy = device.create_compute_pipeline(&ComputePipelineDescriptor {
Expand Down
1 change: 1 addition & 0 deletions tests/tests/occlusion_query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ fn occlusion_query() {
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("Shader module"),
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});
let pipeline = ctx
.device
Expand Down
1 change: 1 addition & 0 deletions tests/tests/partially_bounded_arrays/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ fn partially_bounded_array() {
let cs_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
debug: false,
});

let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
Expand Down
1 change: 1 addition & 0 deletions tests/tests/shader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ fn shader_input_output_test(
let sm = ctx.device.create_shader_module(ShaderModuleDescriptor {
label: Some(&format!("shader {test_name}")),
source: ShaderSource::Wgsl(Cow::Borrowed(&processed)),
debug: false,
});

let pipeline = ctx
Expand Down
20 changes: 19 additions & 1 deletion wgpu-core/src/device/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,19 @@ impl<A: HalApi> Device<A> {
.contains(wgt::DownlevelFlags::MULTISAMPLED_SHADING),
);

let debug_source = if desc.debug {
Some(hal::DebugSource {
file_name: Cow::Owned(
desc.label
.as_ref()
.map_or("shader".to_string(), |l| l.to_string()),
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
),
source_code: Cow::Owned(source.clone()),
})
} else {
None
};

let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
.validate(&module)
.map_err(|inner| {
Expand All @@ -1286,7 +1299,12 @@ impl<A: HalApi> Device<A> {
})
})?;
let interface = validation::Interface::new(&module, &info, self.limits.clone());
let hal_shader = hal::ShaderInput::Naga(hal::NagaShader { module, info });

let hal_shader = hal::ShaderInput::Naga(hal::NagaShader {
module,
info,
debug_source,
});

let hal_desc = hal::ShaderModuleDescriptor {
label: desc.label.borrow_option(),
Expand Down
1 change: 1 addition & 0 deletions wgpu-core/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub struct ShaderModuleDescriptor<'a> {
pub label: Label<'a>,
#[cfg_attr(feature = "serde", serde(default))]
pub shader_bound_checks: wgt::ShaderBoundChecks,
pub debug: bool,
}

#[derive(Debug)]
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/examples/halmark/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ impl<A: hal::Api> Example<A> {
hal::NagaShader {
module: Cow::Owned(module),
info,
debug_source: None,
}
};
let shader_desc = hal::ShaderModuleDescriptor {
Expand Down
8 changes: 8 additions & 0 deletions wgpu-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,8 @@ pub struct NagaShader {
pub module: Cow<'static, naga::Module>,
/// Analysis information of the module.
pub info: naga::valid::ModuleInfo,
/// Source codes for debug
pub debug_source: Option<DebugSource>,
}

// Custom implementation avoids the need to generate Debug impl code
Expand All @@ -1080,6 +1082,12 @@ pub struct ShaderModuleDescriptor<'a> {
pub runtime_checks: bool,
}

#[derive(Debug, Clone)]
pub struct DebugSource {
pub file_name: Cow<'static, str>,
pub source_code: Cow<'static, str>,
}

/// Describes a programmable pipeline stage.
#[derive(Debug)]
pub struct ProgrammableStage<'a, A: Api> {
Expand Down
20 changes: 19 additions & 1 deletion wgpu-hal/src/vulkan/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,9 @@ impl super::Device {
entry_point: stage.entry_point.to_string(),
shader_stage: naga_stage,
};
let needs_temp_options = !runtime_checks || !binding_map.is_empty();
let needs_temp_options = !runtime_checks
|| !binding_map.is_empty()
|| naga_shader.debug_source.is_some();
let mut temp_options;
let options = if needs_temp_options {
temp_options = self.naga_options.clone();
Expand All @@ -739,6 +741,14 @@ impl super::Device {
if !binding_map.is_empty() {
temp_options.binding_map = binding_map.clone();
}

if let Some(ref debug) = naga_shader.debug_source {
temp_options.debug_info = Some(naga::back::spv::DebugInfo {
source_code: &debug.source_code,
file_name: &debug.file_name,
})
}

&temp_options
} else {
&self.naga_options
Expand Down Expand Up @@ -1523,6 +1533,14 @@ impl crate::Device<super::Api> for super::Device {
});
}
let mut naga_options = self.naga_options.clone();
naga_options.debug_info =
naga_shader
.debug_source
.as_ref()
.map(|d| naga::back::spv::DebugInfo {
source_code: d.source_code.as_ref(),
file_name: d.file_name.as_ref(),
});
if !desc.runtime_checks {
naga_options.bounds_check_policies = naga::proc::BoundsCheckPolicies {
index: naga::proc::BoundsCheckPolicy::Unchecked,
Expand Down
2 changes: 2 additions & 0 deletions wgpu/src/backend/direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,7 @@ impl crate::Context for Context {
let descriptor = wgc::pipeline::ShaderModuleDescriptor {
label: desc.label.map(Borrowed),
shader_bound_checks,
debug: desc.debug,
};
let source = match desc.source {
#[cfg(feature = "spirv")]
Expand Down Expand Up @@ -951,6 +952,7 @@ impl crate::Context for Context {
// Doesn't matter the value since spirv shaders aren't mutated to include
// runtime checks
shader_bound_checks: unsafe { wgt::ShaderBoundChecks::unchecked() },
debug: false,
};
let (id, error) = wgc::gfx_select!(
device => global.device_create_shader_module_spirv(*device, &descriptor, Borrowed(&desc.source), ())
Expand Down
2 changes: 2 additions & 0 deletions wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,8 @@ pub struct ShaderModuleDescriptor<'a> {
pub label: Label<'a>,
/// Source code for the shader.
pub source: ShaderSource<'a>,
/// Generate debug symbols, only available in spv-out
pub debug: bool,
}
static_assertions::assert_impl_all!(ShaderModuleDescriptor: Send, Sync);

Expand Down
23 changes: 15 additions & 8 deletions wgpu/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,20 @@ macro_rules! include_spirv_raw {
/// Macro to load a WGSL module statically.
#[macro_export]
macro_rules! include_wgsl {
($($token:tt)*) => {
{
//log::info!("including '{}'", $($token)*);
$crate::ShaderModuleDescriptor {
label: Some($($token)*),
source: $crate::ShaderSource::Wgsl(include_str!($($token)*).into()),
}
($name:tt) => {{
// log::info!("including '{}'", $name);
$crate::ShaderModuleDescriptor {
label: Some($name),
source: $crate::ShaderSource::Wgsl(include_str!($name).into()),
debug: false,
}
};
}};
($name:tt, $debug:tt) => {{
// log::info!("including '{}', '{}'", $name, $debug);
$crate::ShaderModuleDescriptor {
label: Some($name),
source: $crate::ShaderSource::Wgsl(include_str!($name).into()),
debug: $debug,
}
}};
}