Skip to content

Commit a6109bf

Browse files
Mesh shaders - initial wgpu hal changes (#7089)
* Initial(untested commit), vulkan and gles only supported * Maybe fixed compiles for metal and dx12 * Hopefully fixed compiles for other backends and updated to functional(?) vulkan thing * Fixed the clippy warning * Fixed silly documentation mistake * Fixed issue with multiview feature * Dummy commit for dummy CI The CI pooped itself, hopefully this fixes that. Will probably be undone either way. * Re trigger CI checks, to avoid #7126 * Changes based on code review * Fixed clippy warning, broken cargo.lock * Unfucked cargo.lock for real this time * Switched match to if-let in accordance with review * Updated changelog * Fix CI error Done from web out of impatience * CI is very angry 😡 Made CI less angry by fixing formatting(hopefully). This commit was also done from GitHub web. * Removed comment in following request * Update wgpu-hal/src/vulkan/adapter.rs --------- Co-authored-by: Connor Fitzgerald <[email protected]>
1 parent 8394b10 commit a6109bf

File tree

17 files changed

+696
-11
lines changed

17 files changed

+696
-11
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ By @jamienicol in [#6929](https://github.com/gfx-rs/wgpu/pull/6929) and [#7080](
130130
131131
### New Features
132132
133+
- Added mesh shader support to `wgpu_hal`. By @SupaMaggie70Incorporated in [#7089](https://github.com/gfx-rs/wgpu/pull/7089)
134+
133135
#### General
134136
135137
- It is now possible to create a dummy `wgpu` device even when no GPU is available. This may be useful for testing of code which manages graphics resources. Currently, it supports reading and writing buffers, and other resource types can be created but do nothing.

wgpu-hal/src/dx12/command.rs

+26
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,14 @@ impl crate::CommandEncoder for super::CommandEncoder {
11791179
)
11801180
}
11811181
}
1182+
unsafe fn draw_mesh_tasks(
1183+
&mut self,
1184+
_group_count_x: u32,
1185+
_group_count_y: u32,
1186+
_group_count_z: u32,
1187+
) {
1188+
unreachable!()
1189+
}
11821190
unsafe fn draw_indirect(
11831191
&mut self,
11841192
buffer: &super::Buffer,
@@ -1215,6 +1223,14 @@ impl crate::CommandEncoder for super::CommandEncoder {
12151223
)
12161224
}
12171225
}
1226+
unsafe fn draw_mesh_tasks_indirect(
1227+
&mut self,
1228+
_buffer: &<Self::A as crate::Api>::Buffer,
1229+
_offset: wgt::BufferAddress,
1230+
_draw_count: u32,
1231+
) {
1232+
unreachable!()
1233+
}
12181234
unsafe fn draw_indirect_count(
12191235
&mut self,
12201236
buffer: &super::Buffer,
@@ -1255,6 +1271,16 @@ impl crate::CommandEncoder for super::CommandEncoder {
12551271
)
12561272
}
12571273
}
1274+
unsafe fn draw_mesh_tasks_indirect_count(
1275+
&mut self,
1276+
_buffer: &<Self::A as crate::Api>::Buffer,
1277+
_offset: wgt::BufferAddress,
1278+
_count_buffer: &<Self::A as crate::Api>::Buffer,
1279+
_count_offset: wgt::BufferAddress,
1280+
_max_count: u32,
1281+
) {
1282+
unreachable!()
1283+
}
12581284

12591285
// compute
12601286

wgpu-hal/src/dx12/device.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1883,6 +1883,18 @@ impl crate::Device for super::Device {
18831883
vertex_strides,
18841884
})
18851885
}
1886+
1887+
unsafe fn create_mesh_pipeline(
1888+
&self,
1889+
_desc: &crate::MeshPipelineDescriptor<
1890+
<Self::A as crate::Api>::PipelineLayout,
1891+
<Self::A as crate::Api>::ShaderModule,
1892+
<Self::A as crate::Api>::PipelineCache,
1893+
>,
1894+
) -> Result<<Self::A as crate::Api>::RenderPipeline, crate::PipelineError> {
1895+
unreachable!()
1896+
}
1897+
18861898
unsafe fn destroy_render_pipeline(&self, _pipeline: super::RenderPipeline) {
18871899
self.counters.render_pipelines.sub(1);
18881900
}

wgpu-hal/src/dynamic/command.rs

+61
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ pub trait DynCommandEncoder: DynResource + core::fmt::Debug {
130130
first_instance: u32,
131131
instance_count: u32,
132132
);
133+
unsafe fn draw_mesh_tasks(
134+
&mut self,
135+
group_count_x: u32,
136+
group_count_y: u32,
137+
group_count_z: u32,
138+
);
133139
unsafe fn draw_indirect(
134140
&mut self,
135141
buffer: &dyn DynBuffer,
@@ -142,6 +148,12 @@ pub trait DynCommandEncoder: DynResource + core::fmt::Debug {
142148
offset: wgt::BufferAddress,
143149
draw_count: u32,
144150
);
151+
unsafe fn draw_mesh_tasks_indirect(
152+
&mut self,
153+
buffer: &dyn DynBuffer,
154+
offset: wgt::BufferAddress,
155+
draw_count: u32,
156+
);
145157
unsafe fn draw_indirect_count(
146158
&mut self,
147159
buffer: &dyn DynBuffer,
@@ -158,6 +170,14 @@ pub trait DynCommandEncoder: DynResource + core::fmt::Debug {
158170
count_offset: wgt::BufferAddress,
159171
max_count: u32,
160172
);
173+
unsafe fn draw_mesh_tasks_indirect_count(
174+
&mut self,
175+
buffer: &dyn DynBuffer,
176+
offset: wgt::BufferAddress,
177+
count_buffer: &dyn DynBuffer,
178+
count_offset: wgt::BufferAddress,
179+
max_count: u32,
180+
);
161181

162182
unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<dyn DynQuerySet>);
163183
unsafe fn end_compute_pass(&mut self);
@@ -473,6 +493,15 @@ impl<C: CommandEncoder + DynResource> DynCommandEncoder for C {
473493
};
474494
}
475495

496+
unsafe fn draw_mesh_tasks(
497+
&mut self,
498+
group_count_x: u32,
499+
group_count_y: u32,
500+
group_count_z: u32,
501+
) {
502+
unsafe { C::draw_mesh_tasks(self, group_count_x, group_count_y, group_count_z) };
503+
}
504+
476505
unsafe fn draw_indirect(
477506
&mut self,
478507
buffer: &dyn DynBuffer,
@@ -493,6 +522,16 @@ impl<C: CommandEncoder + DynResource> DynCommandEncoder for C {
493522
unsafe { C::draw_indexed_indirect(self, buffer, offset, draw_count) };
494523
}
495524

525+
unsafe fn draw_mesh_tasks_indirect(
526+
&mut self,
527+
buffer: &dyn DynBuffer,
528+
offset: wgt::BufferAddress,
529+
draw_count: u32,
530+
) {
531+
let buffer = buffer.expect_downcast_ref();
532+
unsafe { C::draw_mesh_tasks_indirect(self, buffer, offset, draw_count) };
533+
}
534+
496535
unsafe fn draw_indirect_count(
497536
&mut self,
498537
buffer: &dyn DynBuffer,
@@ -530,6 +569,28 @@ impl<C: CommandEncoder + DynResource> DynCommandEncoder for C {
530569
};
531570
}
532571

572+
unsafe fn draw_mesh_tasks_indirect_count(
573+
&mut self,
574+
buffer: &dyn DynBuffer,
575+
offset: wgt::BufferAddress,
576+
count_buffer: &dyn DynBuffer,
577+
count_offset: wgt::BufferAddress,
578+
max_count: u32,
579+
) {
580+
let buffer = buffer.expect_downcast_ref();
581+
let count_buffer = count_buffer.expect_downcast_ref();
582+
unsafe {
583+
C::draw_mesh_tasks_indirect_count(
584+
self,
585+
buffer,
586+
offset,
587+
count_buffer,
588+
count_offset,
589+
max_count,
590+
)
591+
};
592+
}
593+
533594
unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<dyn DynQuerySet>) {
534595
let desc = ComputePassDescriptor {
535596
label: desc.label,

wgpu-hal/src/dynamic/device.rs

+38-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use crate::{
44
AccelerationStructureBuildSizes, AccelerationStructureDescriptor, Api, BindGroupDescriptor,
55
BindGroupLayoutDescriptor, BufferDescriptor, BufferMapping, CommandEncoderDescriptor,
66
ComputePipelineDescriptor, Device, DeviceError, FenceValue,
7-
GetAccelerationStructureBuildSizesDescriptor, Label, MemoryRange, PipelineCacheDescriptor,
8-
PipelineCacheError, PipelineError, PipelineLayoutDescriptor, RenderPipelineDescriptor,
9-
SamplerDescriptor, ShaderError, ShaderInput, ShaderModuleDescriptor, TextureDescriptor,
10-
TextureViewDescriptor, TlasInstance,
7+
GetAccelerationStructureBuildSizesDescriptor, Label, MemoryRange, MeshPipelineDescriptor,
8+
PipelineCacheDescriptor, PipelineCacheError, PipelineError, PipelineLayoutDescriptor,
9+
RenderPipelineDescriptor, SamplerDescriptor, ShaderError, ShaderInput, ShaderModuleDescriptor,
10+
TextureDescriptor, TextureViewDescriptor, TlasInstance,
1111
};
1212

1313
use super::{
@@ -100,6 +100,14 @@ pub trait DynDevice: DynResource {
100100
dyn DynPipelineCache,
101101
>,
102102
) -> Result<Box<dyn DynRenderPipeline>, PipelineError>;
103+
unsafe fn create_mesh_pipeline(
104+
&self,
105+
desc: &MeshPipelineDescriptor<
106+
dyn DynPipelineLayout,
107+
dyn DynShaderModule,
108+
dyn DynPipelineCache,
109+
>,
110+
) -> Result<Box<dyn DynRenderPipeline>, PipelineError>;
103111
unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>);
104112

105113
unsafe fn create_compute_pipeline(
@@ -393,6 +401,32 @@ impl<D: Device + DynResource> DynDevice for D {
393401
.map(|b| -> Box<dyn DynRenderPipeline> { Box::new(b) })
394402
}
395403

404+
unsafe fn create_mesh_pipeline(
405+
&self,
406+
desc: &MeshPipelineDescriptor<
407+
dyn DynPipelineLayout,
408+
dyn DynShaderModule,
409+
dyn DynPipelineCache,
410+
>,
411+
) -> Result<Box<dyn DynRenderPipeline>, PipelineError> {
412+
let desc = MeshPipelineDescriptor {
413+
label: desc.label,
414+
layout: desc.layout.expect_downcast_ref(),
415+
task_stage: desc.task_stage.clone().map(|f| f.expect_downcast()),
416+
mesh_stage: desc.mesh_stage.clone().expect_downcast(),
417+
primitive: desc.primitive,
418+
depth_stencil: desc.depth_stencil.clone(),
419+
multisample: desc.multisample,
420+
fragment_stage: desc.fragment_stage.clone().map(|f| f.expect_downcast()),
421+
color_targets: desc.color_targets,
422+
multiview: desc.multiview,
423+
cache: desc.cache.map(|c| c.expect_downcast_ref()),
424+
};
425+
426+
unsafe { D::create_mesh_pipeline(self, &desc) }
427+
.map(|b| -> Box<dyn DynRenderPipeline> { Box::new(b) })
428+
}
429+
396430
unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>) {
397431
unsafe { D::destroy_render_pipeline(self, pipeline.unbox()) };
398432
}

wgpu-hal/src/gles/command.rs

+26
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,14 @@ impl crate::CommandEncoder for super::CommandEncoder {
10731073
first_instance_location: self.state.first_instance_location.clone(),
10741074
});
10751075
}
1076+
unsafe fn draw_mesh_tasks(
1077+
&mut self,
1078+
_group_count_x: u32,
1079+
_group_count_y: u32,
1080+
_group_count_z: u32,
1081+
) {
1082+
unreachable!()
1083+
}
10761084
unsafe fn draw_indirect(
10771085
&mut self,
10781086
buffer: &super::Buffer,
@@ -1116,6 +1124,14 @@ impl crate::CommandEncoder for super::CommandEncoder {
11161124
});
11171125
}
11181126
}
1127+
unsafe fn draw_mesh_tasks_indirect(
1128+
&mut self,
1129+
_buffer: &<Self::A as crate::Api>::Buffer,
1130+
_offset: wgt::BufferAddress,
1131+
_draw_count: u32,
1132+
) {
1133+
unreachable!()
1134+
}
11191135
unsafe fn draw_indirect_count(
11201136
&mut self,
11211137
_buffer: &super::Buffer,
@@ -1136,6 +1152,16 @@ impl crate::CommandEncoder for super::CommandEncoder {
11361152
) {
11371153
unreachable!()
11381154
}
1155+
unsafe fn draw_mesh_tasks_indirect_count(
1156+
&mut self,
1157+
_buffer: &<Self::A as crate::Api>::Buffer,
1158+
_offset: wgt::BufferAddress,
1159+
_count_buffer: &<Self::A as crate::Api>::Buffer,
1160+
_count_offset: wgt::BufferAddress,
1161+
_max_count: u32,
1162+
) {
1163+
unreachable!()
1164+
}
11391165

11401166
// compute
11411167

wgpu-hal/src/gles/device.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,16 @@ impl crate::Device for super::Device {
14151415
alpha_to_coverage_enabled: desc.multisample.alpha_to_coverage_enabled,
14161416
})
14171417
}
1418+
unsafe fn create_mesh_pipeline(
1419+
&self,
1420+
_desc: &crate::MeshPipelineDescriptor<
1421+
<Self::A as crate::Api>::PipelineLayout,
1422+
<Self::A as crate::Api>::ShaderModule,
1423+
<Self::A as crate::Api>::PipelineCache,
1424+
>,
1425+
) -> Result<<Self::A as crate::Api>::RenderPipeline, crate::PipelineError> {
1426+
unreachable!()
1427+
}
14181428

14191429
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
14201430
// If the pipeline only has 2 strong references remaining, they're `pipeline` and `program_cache`

wgpu-hal/src/lib.rs

+58-1
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,8 @@ use wgt::WasmNotSendSync;
305305

306306
// - Vertex + Fragment
307307
// - Compute
308-
pub const MAX_CONCURRENT_SHADER_STAGES: usize = 2;
308+
// Task + Mesh + Fragment
309+
pub const MAX_CONCURRENT_SHADER_STAGES: usize = 3;
309310
pub const MAX_ANISOTROPY: u8 = 16;
310311
pub const MAX_BIND_GROUPS: usize = 8;
311312
pub const MAX_VERTEX_BUFFERS: usize = 16;
@@ -901,6 +902,15 @@ pub trait Device: WasmNotSendSync {
901902
<Self::A as Api>::PipelineCache,
902903
>,
903904
) -> Result<<Self::A as Api>::RenderPipeline, PipelineError>;
905+
#[allow(clippy::type_complexity)]
906+
unsafe fn create_mesh_pipeline(
907+
&self,
908+
desc: &MeshPipelineDescriptor<
909+
<Self::A as Api>::PipelineLayout,
910+
<Self::A as Api>::ShaderModule,
911+
<Self::A as Api>::PipelineCache,
912+
>,
913+
) -> Result<<Self::A as Api>::RenderPipeline, PipelineError>;
904914
unsafe fn destroy_render_pipeline(&self, pipeline: <Self::A as Api>::RenderPipeline);
905915

906916
#[allow(clippy::type_complexity)]
@@ -1458,6 +1468,26 @@ pub trait CommandEncoder: WasmNotSendSync + fmt::Debug {
14581468
count_offset: wgt::BufferAddress,
14591469
max_count: u32,
14601470
);
1471+
unsafe fn draw_mesh_tasks(
1472+
&mut self,
1473+
group_count_x: u32,
1474+
group_count_y: u32,
1475+
group_count_z: u32,
1476+
);
1477+
unsafe fn draw_mesh_tasks_indirect(
1478+
&mut self,
1479+
buffer: &<Self::A as Api>::Buffer,
1480+
offset: wgt::BufferAddress,
1481+
draw_count: u32,
1482+
);
1483+
unsafe fn draw_mesh_tasks_indirect_count(
1484+
&mut self,
1485+
buffer: &<Self::A as Api>::Buffer,
1486+
offset: wgt::BufferAddress,
1487+
count_buffer: &<Self::A as Api>::Buffer,
1488+
count_offset: wgt::BufferAddress,
1489+
max_count: u32,
1490+
);
14611491

14621492
// compute passes
14631493

@@ -2158,6 +2188,33 @@ pub struct RenderPipelineDescriptor<
21582188
/// The cache which will be used and filled when compiling this pipeline
21592189
pub cache: Option<&'a Pc>,
21602190
}
2191+
pub struct MeshPipelineDescriptor<
2192+
'a,
2193+
Pl: DynPipelineLayout + ?Sized,
2194+
M: DynShaderModule + ?Sized,
2195+
Pc: DynPipelineCache + ?Sized,
2196+
> {
2197+
pub label: Label<'a>,
2198+
/// The layout of bind groups for this pipeline.
2199+
pub layout: &'a Pl,
2200+
pub task_stage: Option<ProgrammableStage<'a, M>>,
2201+
pub mesh_stage: ProgrammableStage<'a, M>,
2202+
/// The properties of the pipeline at the primitive assembly and rasterization level.
2203+
pub primitive: wgt::PrimitiveState,
2204+
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
2205+
pub depth_stencil: Option<wgt::DepthStencilState>,
2206+
/// The multi-sampling properties of the pipeline.
2207+
pub multisample: wgt::MultisampleState,
2208+
/// The fragment stage for this pipeline.
2209+
pub fragment_stage: Option<ProgrammableStage<'a, M>>,
2210+
/// The effect of draw calls on the color aspect of the output target.
2211+
pub color_targets: &'a [Option<wgt::ColorTargetState>],
2212+
/// If the pipeline will be used with a multiview render pass, this indicates how many array
2213+
/// layers the attachments will have.
2214+
pub multiview: Option<NonZeroU32>,
2215+
/// The cache which will be used and filled when compiling this pipeline
2216+
pub cache: Option<&'a Pc>,
2217+
}
21612218

21622219
#[derive(Debug, Clone)]
21632220
pub struct SurfaceConfiguration {

0 commit comments

Comments
 (0)