Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fe68bf2
Features and draw commands added
SupaMaggie70Incorporated Aug 15, 2025
7558c76
Tried to implement the pipeline creation (completely untested)
SupaMaggie70Incorporated Aug 15, 2025
302d3c4
Fixed clippy issues
SupaMaggie70Incorporated Aug 15, 2025
794fa2a
Fixed something I think
SupaMaggie70Incorporated Aug 16, 2025
be5ccb0
A little bit of work on the mesh shader example (currently doesn't wo…
SupaMaggie70Incorporated Aug 16, 2025
e5bd6b2
Reached a new kind of error state
SupaMaggie70Incorporated Aug 16, 2025
50a80f4
Fixed an alignment issue
SupaMaggie70Incorporated Aug 16, 2025
01dca60
DirectX 12 mesh shaders working :party:
SupaMaggie70Incorporated Aug 16, 2025
ef36e29
Removed stupid change and updated changelog
SupaMaggie70Incorporated Aug 16, 2025
4e83a8c
Fixed typo
SupaMaggie70Incorporated Aug 16, 2025
99e4fd9
Added backends option to example framework
SupaMaggie70Incorporated Aug 16, 2025
c941407
Removed silly no write fragment shader from tests to see if anything …
SupaMaggie70Incorporated Aug 16, 2025
2a52d6e
Tried to make mesh shader tests run elsewhere too
SupaMaggie70Incorporated Aug 16, 2025
313c270
Removed printlns and checked that dx12 mesh shader tests run
SupaMaggie70Incorporated Aug 16, 2025
d93830c
Documented very strange issue
SupaMaggie70Incorporated Aug 16, 2025
bfbf6ee
I'm so lost
SupaMaggie70Incorporated Aug 16, 2025
62b582e
Fixed stupid typos
SupaMaggie70Incorporated Aug 16, 2025
684ef2c
Fixed all issues
SupaMaggie70Incorporated Aug 16, 2025
35f422d
Removed unnecessary example stuff, updated tests
SupaMaggie70Incorporated Aug 16, 2025
0d800b0
Updated typos.toml
SupaMaggie70Incorporated Aug 16, 2025
fafa2c8
Updated limits
SupaMaggie70Incorporated Aug 16, 2025
5d18b20
Merge branch 'trunk' into mesh-shading/dx12-backend
SupaMaggie70Incorporated Aug 17, 2025
f3c4c85
Merge branch 'trunk' into mesh-shading/dx12-backend
SupaMaggie70Incorporated Aug 20, 2025
3ff325a
Merge branch 'trunk' into mesh-shading/dx12-backend
SupaMaggie70Incorporated Aug 24, 2025
7f5839a
Apply suggestion from @cwfitzgerald
SupaMaggie70Incorporated Aug 28, 2025
5414538
Apply suggestion from @cwfitzgerald
SupaMaggie70Incorporated Aug 28, 2025
fafac8c
Removed supported backends, made example & tests always pass the file…
SupaMaggie70Incorporated Aug 28, 2025
8f53f75
Merge branch 'mesh-shading/dx12-backend' of https://github.com/supama…
SupaMaggie70Incorporated Aug 28, 2025
2ea5c1a
Removed excessive bools in test params
SupaMaggie70Incorporated Aug 28, 2025
9054c63
Added new tests to the list
SupaMaggie70Incorporated Aug 28, 2025
2e96f2d
Merge branch 'trunk' into mesh-shading/dx12-backend
SupaMaggie70Incorporated Aug 28, 2025
d3473d2
I'm a sinner for this one (unused import)
SupaMaggie70Incorporated Aug 28, 2025
ccd58bb
Replaced random stuff with test params hashing
SupaMaggie70Incorporated Aug 30, 2025
01277ee
Merge branch 'trunk' into mesh-shading/dx12-backend
SupaMaggie70Incorporated Aug 30, 2025
c5a92ae
Merge branch 'trunk' into mesh-shading/dx12-backend
SupaMaggie70Incorporated Sep 1, 2025
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ By @cwfitzgerald in [#8162](https://github.com/gfx-rs/wgpu/pull/8162).
#### DX12

- Allow disabling waiting for latency waitable object. By @marcpabst in [#7400](https://github.com/gfx-rs/wgpu/pull/7400)
- Add mesh shader support, including to the example. By @SupaMaggie70Incorporated in [#8110](https://github.com/gfx-rs/wgpu/issues/7219)

### Bug Fixes

Expand Down
4 changes: 2 additions & 2 deletions examples/features/src/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,9 @@ impl ExampleContext {
async fn init_async<E: Example>(surface: &mut SurfaceWrapper, window: Arc<Window>) -> Self {
log::info!("Initializing wgpu...");

let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::from_env_or_default());
let instance_descriptor = wgpu::InstanceDescriptor::from_env_or_default();
let instance = wgpu::Instance::new(&instance_descriptor);
surface.pre_adapter(&instance, window);

let adapter = get_adapter_with_capabilities_or_from_env(
&instance,
&E::required_features(),
Expand Down
72 changes: 56 additions & 16 deletions examples/features/src/mesh_shader/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
use std::{io::Write, process::Stdio};
use std::process::Stdio;

// Same as in mesh shader tests
fn compile_glsl(
device: &wgpu::Device,
data: &[u8],
shader_stage: &'static str,
) -> wgpu::ShaderModule {
fn compile_glsl(device: &wgpu::Device, shader_stage: &'static str) -> wgpu::ShaderModule {
let cmd = std::process::Command::new("glslc")
.args([
&format!("-fshader-stage={shader_stage}"),
"-",
&format!(
"{}/src/mesh_shader/shader.{shader_stage}",
env!("CARGO_MANIFEST_DIR")
),
"-o",
"-",
"--target-env=vulkan1.2",
Expand All @@ -19,8 +17,6 @@ fn compile_glsl(
.stdout(Stdio::piped())
.spawn()
.expect("Failed to call glslc");
cmd.stdin.as_ref().unwrap().write_all(data).unwrap();
println!("{shader_stage}");
let output = cmd.wait_with_output().expect("Error waiting for glslc");
assert!(output.status.success());
unsafe {
Expand All @@ -32,27 +28,71 @@ fn compile_glsl(
})
}
}
fn compile_hlsl(device: &wgpu::Device, entry: &str, stage_str: &str) -> wgpu::ShaderModule {
let out_path = format!(
"{}/src/mesh_shader/shader.{stage_str}.cso",
env!("CARGO_MANIFEST_DIR")
);
let cmd = std::process::Command::new("dxc")
.args([
"-T",
&format!("{stage_str}_6_5"),
"-E",
entry,
&format!("{}/src/mesh_shader/shader.hlsl", env!("CARGO_MANIFEST_DIR")),
"-Fo",
&out_path,
])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.output()
.unwrap();
if !cmd.status.success() {
panic!("DXC failed:\n{}", String::from_utf8(cmd.stderr).unwrap());
}
let file = std::fs::read(&out_path).unwrap();
std::fs::remove_file(out_path).unwrap();
unsafe {
device.create_shader_module_passthrough(wgpu::ShaderModuleDescriptorPassthrough {
entry_point: entry.to_owned(),
label: None,
num_workgroups: (1, 1, 1),
dxil: Some(std::borrow::Cow::Owned(file)),
..Default::default()
})
}
}

pub struct Example {
pipeline: wgpu::RenderPipeline,
}
impl crate::framework::Example for Example {
fn init(
config: &wgpu::SurfaceConfiguration,
_adapter: &wgpu::Adapter,
adapter: &wgpu::Adapter,
device: &wgpu::Device,
_queue: &wgpu::Queue,
) -> Self {
let (ts, ms, fs) = if adapter.get_info().backend == wgpu::Backend::Vulkan {
(
compile_glsl(device, "task"),
compile_glsl(device, "mesh"),
compile_glsl(device, "frag"),
)
} else if adapter.get_info().backend == wgpu::Backend::Dx12 {
(
compile_hlsl(device, "Task", "as"),
compile_hlsl(device, "Mesh", "ms"),
compile_hlsl(device, "Frag", "ps"),
)
} else {
panic!("Example can only run on vulkan or dx12");
};
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[],
push_constant_ranges: &[],
});
let (ts, ms, fs) = (
compile_glsl(device, include_bytes!("shader.task"), "task"),
compile_glsl(device, include_bytes!("shader.mesh"), "mesh"),
compile_glsl(device, include_bytes!("shader.frag"), "frag"),
);
let pipeline = device.create_mesh_pipeline(&wgpu::MeshPipelineDescriptor {
label: None,
layout: Some(&pipeline_layout),
Expand Down
53 changes: 53 additions & 0 deletions examples/features/src/mesh_shader/shader.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
struct OutVertex {
float4 Position : SV_POSITION;
float4 Color: COLOR;
};
struct OutPrimitive {
float4 ColorMask : COLOR_MASK : PRIMITIVE;
bool CullPrimitive: SV_CullPrimitive;
};
struct InVertex {
float4 Color: COLOR;
};
struct InPrimitive {
float4 ColorMask : COLOR_MASK : PRIMITIVE;
};
struct PayloadData {
float4 ColorMask;
bool Visible;
};


static const float4 positions[3] = {float4(0., 1.0, 0., 1.0), float4(-1.0, -1.0, 0., 1.0), float4(1.0, -1.0, 0., 1.0)};
static const float4 colors[3] = {float4(0., 1., 0., 1.), float4(0., 0., 1., 1.), float4(1., 0., 0., 1.)};

groupshared PayloadData outPayload;

[numthreads(1, 1, 1)]
void Task() {
outPayload.ColorMask = float4(1.0, 1.0, 0.0, 1.0);
outPayload.Visible = true;
DispatchMesh(3, 1, 1, outPayload);
}

[outputtopology("triangle")]
[numthreads(1, 1, 1)]
void Mesh(out indices uint3 triangles[1], out vertices OutVertex vertices[3], out primitives OutPrimitive primitives[1], in payload PayloadData payload) {
SetMeshOutputCounts(3, 1);

vertices[0].Position = positions[0];
vertices[1].Position = positions[1];
vertices[2].Position = positions[2];

vertices[0].Color = colors[0] * payload.ColorMask;
vertices[1].Color = colors[1] * payload.ColorMask;
vertices[2].Color = colors[2] * payload.ColorMask;

triangles[0] = uint3(0, 1, 2);
primitives[0].ColorMask = float4(1.0, 0.0, 0.0, 1.0);
primitives[0].CullPrimitive = !payload.Visible;
}

float4 Frag(InVertex vertex, InPrimitive primitive) : SV_Target {
return vertex.Color * primitive.ColorMask;
}
6 changes: 3 additions & 3 deletions examples/features/src/mesh_shader/shader.mesh
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ vertexOutput[];
layout(location = 1) perprimitiveEXT out PrimitiveOutput { vec4 colorMask; }
primitiveOutput[];

shared uint sharedData;

layout(triangles, max_vertices = 3, max_primitives = 1) out;
void main() {
sharedData = 5;
SetMeshOutputsEXT(3, 1);

gl_MeshVerticesEXT[0].gl_Position = positions[0];
gl_MeshVerticesEXT[1].gl_Position = positions[1];
gl_MeshVerticesEXT[2].gl_Position = positions[2];

vertexOutput[0].color = colors[0] * payloadData.colorMask;
vertexOutput[1].color = colors[1] * payloadData.colorMask;
vertexOutput[2].color = colors[2] * payloadData.colorMask;

gl_PrimitiveTriangleIndicesEXT[gl_LocalInvocationIndex] = uvec3(0, 1, 2);
primitiveOutput[0].colorMask = vec4(1.0, 0.0, 1.0, 1.0);
gl_MeshPrimitivesEXT[0].gl_CullPrimitiveEXT = !payloadData.visible;
Expand Down
2 changes: 1 addition & 1 deletion examples/features/src/mesh_shader/shader.task
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#version 450
#extension GL_EXT_mesh_shader : require

layout(local_size_x = 4, local_size_y = 1, local_size_z = 1) in;
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;

struct TaskPayload {
vec4 colorMask;
Expand Down
3 changes: 2 additions & 1 deletion naga/src/back/hlsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ impl crate::ShaderStage {
Self::Vertex => "vs",
Self::Fragment => "ps",
Self::Compute => "cs",
Self::Task | Self::Mesh => unreachable!(),
Self::Task => "as",
Self::Mesh => "ms",
}
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
GpuTestConfiguration,
};

#[derive(Hash)]
/// Parameters and resources handed to the test function.
pub struct TestingContext {
pub instance: Instance,
Expand Down
41 changes: 41 additions & 0 deletions tests/tests/wgpu-gpu/mesh_shader/basic.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
struct OutVertex {
float4 Position : SV_POSITION;
float4 Color: COLOR;
};
struct InVertex {
float4 Color: COLOR;
};


static const float4 positions[3] = {float4(0., 1.0, 0., 1.0), float4(-1.0, -1.0, 0., 1.0), float4(1.0, -1.0, 0., 1.0)};
static const float4 colors[3] = {float4(0., 1., 0., 1.), float4(0., 0., 1., 1.), float4(1., 0., 0., 1.)};

struct EmptyPayload {
uint _nullField;
};
groupshared EmptyPayload _emptyPayload;

[numthreads(4, 1, 1)]
void Task() {
DispatchMesh(1, 1, 1, _emptyPayload);
}

[outputtopology("triangle")]
[numthreads(1, 1, 1)]
void Mesh(out indices uint3 triangles[1], out vertices OutVertex vertices[3], in payload EmptyPayload _emptyPayload) {
SetMeshOutputCounts(3, 1);

vertices[0].Position = positions[0];
vertices[1].Position = positions[1];
vertices[2].Position = positions[2];

vertices[0].Color = colors[0];
vertices[1].Color = colors[1];
vertices[2].Color = colors[2];

triangles[0] = uint3(0, 1, 2);
}

float4 Frag(InVertex vertex) : SV_Target {
return vertex.Color;
}
Loading
Loading