Skip to content
Draft
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ By @cwfitzgerald in [#8162](https://github.com/gfx-rs/wgpu/pull/8162).

- Allow disabling waiting for latency waitable object. By @marcpabst in [#7400](https://github.com/gfx-rs/wgpu/pull/7400)

#### Metal
- Add support for mesh shaders. By @SupaMaggie70Incorporated in [#8139](https://github.com/gfx-rs/wgpu/pull/8139)

### Bug Fixes

#### General
Expand Down
32 changes: 26 additions & 6 deletions examples/features/src/mesh_shader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,25 @@ fn compile_glsl(
}
}

fn compile_msl(device: &wgpu::Device, entry: &str) -> wgpu::ShaderModule {
unsafe {
device.create_shader_module_passthrough(wgpu::ShaderModuleDescriptorPassthrough {
entry_point: entry.to_owned(),
label: None,
msl: Some(std::borrow::Cow::Borrowed(include_str!("shader.metal"))),
num_workgroups: (1, 1, 1),
..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 {
Expand All @@ -48,11 +60,19 @@ impl crate::framework::Example for Example {
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 (ts, ms, fs) = if adapter.get_info().backend == wgpu::Backend::Metal {
(
compile_msl(device, "taskShader"),
compile_msl(device, "meshShader"),
compile_msl(device, "fragShader"),
)
} else {
(
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
77 changes: 77 additions & 0 deletions examples/features/src/mesh_shader/shader.metal
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using namespace metal;

struct OutVertex {
float4 Position [[position]];
float4 Color [[user(locn0)]];
};

struct OutPrimitive {
float4 ColorMask [[flat]] [[user(locn1)]];
bool CullPrimitive [[primitive_culled]];
};

struct InVertex {
};

struct InPrimitive {
float4 ColorMask [[flat]] [[user(locn1)]];
};

struct FragmentIn {
float4 Color [[user(locn0)]];
float4 ColorMask [[flat]] [[user(locn1)]];
};

struct PayloadData {
float4 ColorMask;
bool Visible;
};

using Meshlet = metal::mesh<OutVertex, OutPrimitive, 3, 1, topology::triangle>;


constant float4 positions[3] = {
float4(0.0, 1.0, 0.0, 1.0),
float4(-1.0, -1.0, 0.0, 1.0),
float4(1.0, -1.0, 0.0, 1.0)
};

constant float4 colors[3] = {
float4(0.0, 1.0, 0.0, 1.0),
float4(0.0, 0.0, 1.0, 1.0),
float4(1.0, 0.0, 0.0, 1.0)
};


[[object]]
void taskShader(uint3 tid [[thread_position_in_grid]], object_data PayloadData &outPayload [[payload]], mesh_grid_properties grid) {
outPayload.ColorMask = float4(1.0, 1.0, 0.0, 1.0);
outPayload.Visible = true;
grid.set_threadgroups_per_grid(uint3(3, 1, 1));
}

[[mesh]]
void meshShader(
object_data PayloadData const& payload [[payload]],
Meshlet out
)
{
out.set_primitive_count(1);

for(int i = 0;i < 3;i++) {
OutVertex vert;
vert.Position = positions[i];
vert.Color = colors[i] * payload.ColorMask;
out.set_vertex(i, vert);
out.set_index(i, i);
}

OutPrimitive prim;
prim.ColorMask = float4(1.0, 0.0, 0.0, 1.0);
prim.CullPrimitive = !payload.Visible;
out.set_primitive(0, prim);
}

fragment float4 fragShader(FragmentIn data [[stage_in]]) {
return data.Color * data.ColorMask;
}
6 changes: 6 additions & 0 deletions tests/tests/wgpu-gpu/mesh_shader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ fn mesh_pipeline_build(
frag: Option<&[u8]>,
draw: bool,
) {
if ctx.adapter.get_info().backend != wgpu::Backend::Vulkan {
return;
}
let device = &ctx.device;
let (_depth_image, depth_view, depth_state) = create_depth(device);
let task = task.map(|t| compile_glsl(device, t, "task"));
Expand Down Expand Up @@ -160,6 +163,9 @@ pub enum DrawType {
}

fn mesh_draw(ctx: &TestingContext, draw_type: DrawType) {
if ctx.adapter.get_info().backend != wgpu::Backend::Vulkan {
return;
}
let device = &ctx.device;
let (_depth_image, depth_view, depth_state) = create_depth(device);
let task = compile_glsl(device, BASIC_TASK, "task");
Expand Down
11 changes: 8 additions & 3 deletions wgpu-hal/src/metal/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,8 @@ impl super::PrivateCapabilities {
&& (device.supports_family(MTLGPUFamily::Apple7)
|| device.supports_family(MTLGPUFamily::Mac2)),
supports_shared_event: version.at_least((10, 14), (12, 0), os_is_mac),
mesh_shaders: device.supports_family(MTLGPUFamily::Apple7)
|| device.supports_family(MTLGPUFamily::Mac2),
}
}

Expand Down Expand Up @@ -1001,6 +1003,8 @@ impl super::PrivateCapabilities {
features.insert(F::SUBGROUP | F::SUBGROUP_BARRIER);
}

features.set(F::EXPERIMENTAL_MESH_SHADER, self.mesh_shaders);

features
}

Expand Down Expand Up @@ -1077,10 +1081,11 @@ impl super::PrivateCapabilities {
max_buffer_size: self.max_buffer_size,
max_non_sampler_bindings: u32::MAX,

max_task_workgroup_total_count: 0,
max_task_workgroups_per_dimension: 0,
// See https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf, Maximum threadgroups per mesh shader grid
max_task_workgroup_total_count: 1024,
max_task_workgroups_per_dimension: 1024,
max_mesh_multiview_count: 0,
max_mesh_output_layers: 0,
max_mesh_output_layers: self.max_texture_layers as u32,

max_blas_primitive_count: 0, // When added: 2^28 from https://developer.apple.com/documentation/metal/mtlaccelerationstructureusage/extendedlimits
max_blas_geometry_count: 0, // When added: 2^24
Expand Down
Loading
Loading