From 6ee00ab401d248cdbb0784b65bfeac18c118f7e1 Mon Sep 17 00:00:00 2001 From: 0x182d4454fb211940 Date: Thu, 24 Dec 2020 17:37:06 +0000 Subject: [PATCH 1/4] [rs] Add `RenderEncoder` --- wgpu/CHANGELOG.md | 1 + wgpu/src/lib.rs | 177 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/wgpu/CHANGELOG.md b/wgpu/CHANGELOG.md index 964ef9581b..0e2b840bfd 100644 --- a/wgpu/CHANGELOG.md +++ b/wgpu/CHANGELOG.md @@ -2,6 +2,7 @@ ### unreleased - introduce `ShaderModuleDescriptor` +- introduce `RenderEncoder` ### v0.6.2 (2020-11-24) - don't panic in the staging belt if the channel is dropped diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 7fe3d51434..ff7e167469 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -2575,6 +2575,183 @@ impl<'a> RenderBundleEncoder<'a> { } } +/// Methods shared by `RenderPass` and `RenderBundleEncoder` +pub trait RenderEncoder<'a> { + /// Sets the active bind group for a given bind group index. The bind group layout + /// in the active pipeline when any `draw()` function is called must match the layout of this bind group. + /// + /// If the bind group have dynamic offsets, provide them in order of their declaration. + fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]); + + /// Sets the active render pipeline. + /// + /// Subsequent draw calls will exhibit the behavior defined by `pipeline`. + fn set_pipeline(&mut self, pipeline: &'a RenderPipeline); + + /// Sets the active index buffer. + /// + /// Subsequent calls to [`draw_indexed`](RenderBundleEncoder::draw_indexed) on this [`RenderBundleEncoder`] will + /// use `buffer` as the source index buffer. + fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat); + + /// Assign a vertex buffer to a slot. + /// + /// Subsequent calls to [`draw`] and [`draw_indexed`] on this + /// [`RenderBundleEncoder`] will use `buffer` as one of the source vertex buffers. + /// + /// The `slot` refers to the index of the matching descriptor in + /// [`VertexStateDescriptor::vertex_buffers`]. + /// + /// [`draw`]: RenderBundleEncoder::draw + /// [`draw_indexed`]: RenderBundleEncoder::draw_indexed + fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>); + + /// Draws primitives from the active vertex buffer(s). + /// + /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. + fn draw(&mut self, vertices: Range, instances: Range); + + /// Draws indexed primitives using the active index buffer and the active vertex buffers. + /// + /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active + /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. + fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range); + + /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`. + /// + /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. + /// + /// The structure expected in `indirect_buffer` is the following: + /// + /// ```rust + /// #[repr(C)] + /// struct DrawIndirect { + /// vertex_count: u32, // The number of vertices to draw. + /// instance_count: u32, // The number of instances to draw. + /// base_vertex: u32, // The Index of the first vertex to draw. + /// base_instance: u32, // The instance ID of the first instance to draw. + /// } + /// ``` + fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress); + + /// Draws indexed primitives using the active index buffer and the active vertex buffers, + /// based on the contents of the `indirect_buffer`. + /// + /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active + /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. + /// + /// The structure expected in `indirect_buffer` is the following: + /// + /// ```rust + /// #[repr(C)] + /// struct DrawIndexedIndirect { + /// vertex_count: u32, // The number of vertices to draw. + /// instance_count: u32, // The number of instances to draw. + /// base_index: u32, // The base index within the index buffer. + /// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer. + /// base_instance: u32, // The instance ID of the first instance to draw. + /// } + /// ``` + fn draw_indexed_indirect( + &mut self, + indirect_buffer: &'a Buffer, + indirect_offset: BufferAddress, + ); +} + +impl<'a> RenderEncoder<'a> for RenderPass<'a> { + #[inline(always)] + fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) { + (self as &mut RenderPass<'a>).set_bind_group(index, bind_group, offsets); + } + + #[inline(always)] + fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { + (self as &mut RenderPass<'a>).set_pipeline(pipeline); + } + + #[inline(always)] + fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { + (self as &mut RenderPass<'a>).set_index_buffer(buffer_slice, index_format); + } + + #[inline(always)] + fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { + (self as &mut RenderPass<'a>).set_vertex_buffer(slot, buffer_slice); + } + + #[inline(always)] + fn draw(&mut self, vertices: Range, instances: Range) { + (self as &mut RenderPass<'a>).draw(vertices, instances); + } + + #[inline(always)] + fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { + (self as &mut RenderPass<'a>).draw_indexed(indices, base_vertex, instances); + } + + #[inline(always)] + fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { + (self as &mut RenderPass<'a>).draw_indirect(indirect_buffer, indirect_offset); + } + + #[inline(always)] + fn draw_indexed_indirect( + &mut self, + indirect_buffer: &'a Buffer, + indirect_offset: BufferAddress, + ) { + (self as &mut RenderPass<'a>).draw_indexed_indirect(indirect_buffer, indirect_offset); + } +} + +impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> { + #[inline(always)] + fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) { + (self as &mut RenderBundleEncoder<'a>).set_bind_group(index, bind_group, offsets); + } + + #[inline(always)] + fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { + (self as &mut RenderBundleEncoder<'a>).set_pipeline(pipeline); + } + + #[inline(always)] + fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { + (self as &mut RenderBundleEncoder<'a>).set_index_buffer(buffer_slice, index_format); + } + + #[inline(always)] + fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { + (self as &mut RenderBundleEncoder<'a>).set_vertex_buffer(slot, buffer_slice); + } + + #[inline(always)] + fn draw(&mut self, vertices: Range, instances: Range) { + (self as &mut RenderBundleEncoder<'a>).draw(vertices, instances); + } + + #[inline(always)] + fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { + (self as &mut RenderBundleEncoder<'a>).draw_indexed(indices, base_vertex, instances); + } + + #[inline(always)] + fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { + (self as &mut RenderBundleEncoder<'a>).draw_indirect(indirect_buffer, indirect_offset); + } + + #[inline(always)] + fn draw_indexed_indirect( + &mut self, + indirect_buffer: &'a Buffer, + indirect_offset: BufferAddress, + ) { + (self as &mut RenderBundleEncoder<'a>) + .draw_indexed_indirect(indirect_buffer, indirect_offset); + } +} + impl Queue { /// Schedule a data write into `buffer` starting at `offset`. /// From 8dc1c0896bfc05eef770f8b8d392856700b3c677 Mon Sep 17 00:00:00 2001 From: 0x182d4454fb211940 Date: Fri, 25 Dec 2020 13:47:38 +0000 Subject: [PATCH 2/4] [rs] Move `RenderEncoder` to `util` --- wgpu/src/lib.rs | 177 ------------------------------------- wgpu/src/util/encoder.rs | 182 +++++++++++++++++++++++++++++++++++++++ wgpu/src/util/mod.rs | 2 + 3 files changed, 184 insertions(+), 177 deletions(-) create mode 100644 wgpu/src/util/encoder.rs diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index ff7e167469..7fe3d51434 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -2575,183 +2575,6 @@ impl<'a> RenderBundleEncoder<'a> { } } -/// Methods shared by `RenderPass` and `RenderBundleEncoder` -pub trait RenderEncoder<'a> { - /// Sets the active bind group for a given bind group index. The bind group layout - /// in the active pipeline when any `draw()` function is called must match the layout of this bind group. - /// - /// If the bind group have dynamic offsets, provide them in order of their declaration. - fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]); - - /// Sets the active render pipeline. - /// - /// Subsequent draw calls will exhibit the behavior defined by `pipeline`. - fn set_pipeline(&mut self, pipeline: &'a RenderPipeline); - - /// Sets the active index buffer. - /// - /// Subsequent calls to [`draw_indexed`](RenderBundleEncoder::draw_indexed) on this [`RenderBundleEncoder`] will - /// use `buffer` as the source index buffer. - fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat); - - /// Assign a vertex buffer to a slot. - /// - /// Subsequent calls to [`draw`] and [`draw_indexed`] on this - /// [`RenderBundleEncoder`] will use `buffer` as one of the source vertex buffers. - /// - /// The `slot` refers to the index of the matching descriptor in - /// [`VertexStateDescriptor::vertex_buffers`]. - /// - /// [`draw`]: RenderBundleEncoder::draw - /// [`draw_indexed`]: RenderBundleEncoder::draw_indexed - fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>); - - /// Draws primitives from the active vertex buffer(s). - /// - /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. - fn draw(&mut self, vertices: Range, instances: Range); - - /// Draws indexed primitives using the active index buffer and the active vertex buffers. - /// - /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active - /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. - fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range); - - /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`. - /// - /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. - /// - /// The structure expected in `indirect_buffer` is the following: - /// - /// ```rust - /// #[repr(C)] - /// struct DrawIndirect { - /// vertex_count: u32, // The number of vertices to draw. - /// instance_count: u32, // The number of instances to draw. - /// base_vertex: u32, // The Index of the first vertex to draw. - /// base_instance: u32, // The instance ID of the first instance to draw. - /// } - /// ``` - fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress); - - /// Draws indexed primitives using the active index buffer and the active vertex buffers, - /// based on the contents of the `indirect_buffer`. - /// - /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active - /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. - /// - /// The structure expected in `indirect_buffer` is the following: - /// - /// ```rust - /// #[repr(C)] - /// struct DrawIndexedIndirect { - /// vertex_count: u32, // The number of vertices to draw. - /// instance_count: u32, // The number of instances to draw. - /// base_index: u32, // The base index within the index buffer. - /// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer. - /// base_instance: u32, // The instance ID of the first instance to draw. - /// } - /// ``` - fn draw_indexed_indirect( - &mut self, - indirect_buffer: &'a Buffer, - indirect_offset: BufferAddress, - ); -} - -impl<'a> RenderEncoder<'a> for RenderPass<'a> { - #[inline(always)] - fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) { - (self as &mut RenderPass<'a>).set_bind_group(index, bind_group, offsets); - } - - #[inline(always)] - fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { - (self as &mut RenderPass<'a>).set_pipeline(pipeline); - } - - #[inline(always)] - fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { - (self as &mut RenderPass<'a>).set_index_buffer(buffer_slice, index_format); - } - - #[inline(always)] - fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { - (self as &mut RenderPass<'a>).set_vertex_buffer(slot, buffer_slice); - } - - #[inline(always)] - fn draw(&mut self, vertices: Range, instances: Range) { - (self as &mut RenderPass<'a>).draw(vertices, instances); - } - - #[inline(always)] - fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { - (self as &mut RenderPass<'a>).draw_indexed(indices, base_vertex, instances); - } - - #[inline(always)] - fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { - (self as &mut RenderPass<'a>).draw_indirect(indirect_buffer, indirect_offset); - } - - #[inline(always)] - fn draw_indexed_indirect( - &mut self, - indirect_buffer: &'a Buffer, - indirect_offset: BufferAddress, - ) { - (self as &mut RenderPass<'a>).draw_indexed_indirect(indirect_buffer, indirect_offset); - } -} - -impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> { - #[inline(always)] - fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) { - (self as &mut RenderBundleEncoder<'a>).set_bind_group(index, bind_group, offsets); - } - - #[inline(always)] - fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { - (self as &mut RenderBundleEncoder<'a>).set_pipeline(pipeline); - } - - #[inline(always)] - fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { - (self as &mut RenderBundleEncoder<'a>).set_index_buffer(buffer_slice, index_format); - } - - #[inline(always)] - fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { - (self as &mut RenderBundleEncoder<'a>).set_vertex_buffer(slot, buffer_slice); - } - - #[inline(always)] - fn draw(&mut self, vertices: Range, instances: Range) { - (self as &mut RenderBundleEncoder<'a>).draw(vertices, instances); - } - - #[inline(always)] - fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { - (self as &mut RenderBundleEncoder<'a>).draw_indexed(indices, base_vertex, instances); - } - - #[inline(always)] - fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { - (self as &mut RenderBundleEncoder<'a>).draw_indirect(indirect_buffer, indirect_offset); - } - - #[inline(always)] - fn draw_indexed_indirect( - &mut self, - indirect_buffer: &'a Buffer, - indirect_offset: BufferAddress, - ) { - (self as &mut RenderBundleEncoder<'a>) - .draw_indexed_indirect(indirect_buffer, indirect_offset); - } -} - impl Queue { /// Schedule a data write into `buffer` starting at `offset`. /// diff --git a/wgpu/src/util/encoder.rs b/wgpu/src/util/encoder.rs new file mode 100644 index 0000000000..e1d064b473 --- /dev/null +++ b/wgpu/src/util/encoder.rs @@ -0,0 +1,182 @@ +use std::ops::Range; + +use wgt::{BufferAddress, DynamicOffset, IndexFormat}; + +use crate::{BindGroup, Buffer, BufferSlice, RenderBundleEncoder, RenderPass, RenderPipeline}; + +/// Methods shared by `RenderPass` and `RenderBundleEncoder` +pub trait RenderEncoder<'a> { + /// Sets the active bind group for a given bind group index. The bind group layout + /// in the active pipeline when any `draw()` function is called must match the layout of this bind group. + /// + /// If the bind group have dynamic offsets, provide them in order of their declaration. + fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]); + + /// Sets the active render pipeline. + /// + /// Subsequent draw calls will exhibit the behavior defined by `pipeline`. + fn set_pipeline(&mut self, pipeline: &'a RenderPipeline); + + /// Sets the active index buffer. + /// + /// Subsequent calls to [`draw_indexed`](RenderBundleEncoder::draw_indexed) on this [`RenderBundleEncoder`] will + /// use `buffer` as the source index buffer. + fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat); + + /// Assign a vertex buffer to a slot. + /// + /// Subsequent calls to [`draw`] and [`draw_indexed`] on this + /// [`RenderBundleEncoder`] will use `buffer` as one of the source vertex buffers. + /// + /// The `slot` refers to the index of the matching descriptor in + /// [`VertexStateDescriptor::vertex_buffers`]. + /// + /// [`draw`]: RenderBundleEncoder::draw + /// [`draw_indexed`]: RenderBundleEncoder::draw_indexed + fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>); + + /// Draws primitives from the active vertex buffer(s). + /// + /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. + fn draw(&mut self, vertices: Range, instances: Range); + + /// Draws indexed primitives using the active index buffer and the active vertex buffers. + /// + /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active + /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. + fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range); + + /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`. + /// + /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. + /// + /// The structure expected in `indirect_buffer` is the following: + /// + /// ```rust + /// #[repr(C)] + /// struct DrawIndirect { + /// vertex_count: u32, // The number of vertices to draw. + /// instance_count: u32, // The number of instances to draw. + /// base_vertex: u32, // The Index of the first vertex to draw. + /// base_instance: u32, // The instance ID of the first instance to draw. + /// } + /// ``` + fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress); + + /// Draws indexed primitives using the active index buffer and the active vertex buffers, + /// based on the contents of the `indirect_buffer`. + /// + /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active + /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`]. + /// + /// The structure expected in `indirect_buffer` is the following: + /// + /// ```rust + /// #[repr(C)] + /// struct DrawIndexedIndirect { + /// vertex_count: u32, // The number of vertices to draw. + /// instance_count: u32, // The number of instances to draw. + /// base_index: u32, // The base index within the index buffer. + /// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer. + /// base_instance: u32, // The instance ID of the first instance to draw. + /// } + /// ``` + fn draw_indexed_indirect( + &mut self, + indirect_buffer: &'a Buffer, + indirect_offset: BufferAddress, + ); +} + +impl<'a> RenderEncoder<'a> for RenderPass<'a> { + #[inline(always)] + fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) { + (self as &mut RenderPass<'a>).set_bind_group(index, bind_group, offsets); + } + + #[inline(always)] + fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { + (self as &mut RenderPass<'a>).set_pipeline(pipeline); + } + + #[inline(always)] + fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { + (self as &mut RenderPass<'a>).set_index_buffer(buffer_slice, index_format); + } + + #[inline(always)] + fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { + (self as &mut RenderPass<'a>).set_vertex_buffer(slot, buffer_slice); + } + + #[inline(always)] + fn draw(&mut self, vertices: Range, instances: Range) { + (self as &mut RenderPass<'a>).draw(vertices, instances); + } + + #[inline(always)] + fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { + (self as &mut RenderPass<'a>).draw_indexed(indices, base_vertex, instances); + } + + #[inline(always)] + fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { + (self as &mut RenderPass<'a>).draw_indirect(indirect_buffer, indirect_offset); + } + + #[inline(always)] + fn draw_indexed_indirect( + &mut self, + indirect_buffer: &'a Buffer, + indirect_offset: BufferAddress, + ) { + (self as &mut RenderPass<'a>).draw_indexed_indirect(indirect_buffer, indirect_offset); + } +} + +impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> { + #[inline(always)] + fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) { + (self as &mut RenderBundleEncoder<'a>).set_bind_group(index, bind_group, offsets); + } + + #[inline(always)] + fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { + (self as &mut RenderBundleEncoder<'a>).set_pipeline(pipeline); + } + + #[inline(always)] + fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { + (self as &mut RenderBundleEncoder<'a>).set_index_buffer(buffer_slice, index_format); + } + + #[inline(always)] + fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { + (self as &mut RenderBundleEncoder<'a>).set_vertex_buffer(slot, buffer_slice); + } + + #[inline(always)] + fn draw(&mut self, vertices: Range, instances: Range) { + (self as &mut RenderBundleEncoder<'a>).draw(vertices, instances); + } + + #[inline(always)] + fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { + (self as &mut RenderBundleEncoder<'a>).draw_indexed(indices, base_vertex, instances); + } + + #[inline(always)] + fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { + (self as &mut RenderBundleEncoder<'a>).draw_indirect(indirect_buffer, indirect_offset); + } + + #[inline(always)] + fn draw_indexed_indirect( + &mut self, + indirect_buffer: &'a Buffer, + indirect_offset: BufferAddress, + ) { + (self as &mut RenderBundleEncoder<'a>) + .draw_indexed_indirect(indirect_buffer, indirect_offset); + } +} diff --git a/wgpu/src/util/mod.rs b/wgpu/src/util/mod.rs index 3bfbfda974..8cfbb4f5b6 100644 --- a/wgpu/src/util/mod.rs +++ b/wgpu/src/util/mod.rs @@ -2,6 +2,7 @@ mod belt; mod device; +mod encoder; use std::{ borrow::Cow, @@ -11,6 +12,7 @@ use std::{ pub use belt::StagingBelt; pub use device::{BufferInitDescriptor, DeviceExt}; +pub use encoder::RenderEncoder; /// Treat the given byte slice as a SPIR-V module. /// From a2ff43f989da348214d26adca19403c3c8bfcc9b Mon Sep 17 00:00:00 2001 From: 0x182d4454fb211940 Date: Fri, 25 Dec 2020 13:50:36 +0000 Subject: [PATCH 3/4] [rs] Remove unneeded cast from `encoder.rs` --- wgpu/src/util/encoder.rs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/wgpu/src/util/encoder.rs b/wgpu/src/util/encoder.rs index e1d064b473..e9c8b66bf9 100644 --- a/wgpu/src/util/encoder.rs +++ b/wgpu/src/util/encoder.rs @@ -91,37 +91,37 @@ pub trait RenderEncoder<'a> { impl<'a> RenderEncoder<'a> for RenderPass<'a> { #[inline(always)] fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) { - (self as &mut RenderPass<'a>).set_bind_group(index, bind_group, offsets); + Self::set_bind_group(self, index, bind_group, offsets); } #[inline(always)] fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { - (self as &mut RenderPass<'a>).set_pipeline(pipeline); + Self::set_pipeline(self, pipeline); } #[inline(always)] fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { - (self as &mut RenderPass<'a>).set_index_buffer(buffer_slice, index_format); + Self::set_index_buffer(self, buffer_slice, index_format); } #[inline(always)] fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { - (self as &mut RenderPass<'a>).set_vertex_buffer(slot, buffer_slice); + Self::set_vertex_buffer(self, slot, buffer_slice); } #[inline(always)] fn draw(&mut self, vertices: Range, instances: Range) { - (self as &mut RenderPass<'a>).draw(vertices, instances); + Self::draw(self, vertices, instances); } #[inline(always)] fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { - (self as &mut RenderPass<'a>).draw_indexed(indices, base_vertex, instances); + Self::draw_indexed(self, indices, base_vertex, instances); } #[inline(always)] fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { - (self as &mut RenderPass<'a>).draw_indirect(indirect_buffer, indirect_offset); + Self::draw_indirect(self, indirect_buffer, indirect_offset); } #[inline(always)] @@ -130,44 +130,44 @@ impl<'a> RenderEncoder<'a> for RenderPass<'a> { indirect_buffer: &'a Buffer, indirect_offset: BufferAddress, ) { - (self as &mut RenderPass<'a>).draw_indexed_indirect(indirect_buffer, indirect_offset); + Self::draw_indexed_indirect(self, indirect_buffer, indirect_offset); } } impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> { #[inline(always)] fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[DynamicOffset]) { - (self as &mut RenderBundleEncoder<'a>).set_bind_group(index, bind_group, offsets); + Self::set_bind_group(self, index, bind_group, offsets); } #[inline(always)] fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) { - (self as &mut RenderBundleEncoder<'a>).set_pipeline(pipeline); + Self::set_pipeline(self, pipeline); } #[inline(always)] fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) { - (self as &mut RenderBundleEncoder<'a>).set_index_buffer(buffer_slice, index_format); + Self::set_index_buffer(self, buffer_slice, index_format); } #[inline(always)] fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { - (self as &mut RenderBundleEncoder<'a>).set_vertex_buffer(slot, buffer_slice); + Self::set_vertex_buffer(self, slot, buffer_slice); } #[inline(always)] fn draw(&mut self, vertices: Range, instances: Range) { - (self as &mut RenderBundleEncoder<'a>).draw(vertices, instances); + Self::draw(self, vertices, instances); } #[inline(always)] fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { - (self as &mut RenderBundleEncoder<'a>).draw_indexed(indices, base_vertex, instances); + Self::draw_indexed(self, indices, base_vertex, instances); } #[inline(always)] fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) { - (self as &mut RenderBundleEncoder<'a>).draw_indirect(indirect_buffer, indirect_offset); + Self::draw_indirect(self, indirect_buffer, indirect_offset); } #[inline(always)] @@ -176,7 +176,6 @@ impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> { indirect_buffer: &'a Buffer, indirect_offset: BufferAddress, ) { - (self as &mut RenderBundleEncoder<'a>) - .draw_indexed_indirect(indirect_buffer, indirect_offset); + Self::draw_indexed_indirect(self, indirect_buffer, indirect_offset); } } From cbbf25c6f8eedf18fb84269f4cf3240070488c1a Mon Sep 17 00:00:00 2001 From: 0x182d4454fb211940 Date: Fri, 25 Dec 2020 14:01:04 +0000 Subject: [PATCH 4/4] [rs] Add `set_push_constants` to `RenderEncoder` --- wgpu/src/util/encoder.rs | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/wgpu/src/util/encoder.rs b/wgpu/src/util/encoder.rs index e9c8b66bf9..48b7e922e2 100644 --- a/wgpu/src/util/encoder.rs +++ b/wgpu/src/util/encoder.rs @@ -86,6 +86,38 @@ pub trait RenderEncoder<'a> { indirect_buffer: &'a Buffer, indirect_offset: BufferAddress, ); + + /// [`Features::PUSH_CONSTANTS`] must be enabled on the device in order to call this function. + /// + /// Set push constant data. + /// + /// Offset is measured in bytes, but must be a multiple of [`PUSH_CONSTANT_ALIGNMENT`]. + /// + /// Data size must be a multiple of 4 and must be aligned to the 4s, so we take an array of u32. + /// For example, with an offset of 4 and an array of `[u32; 3]`, that will write to the range + /// of 4..16. + /// + /// For each byte in the range of push constant data written, the union of the stages of all push constant + /// ranges that covers that byte must be exactly `stages`. There's no good way of explaining this simply, + /// so here are some examples: + /// + /// ```text + /// For the given ranges: + /// - 0..4 Vertex + /// - 4..8 Fragment + /// ``` + /// + /// You would need to upload this in two set_push_constants calls. First for the `Vertex` range, second for the `Fragment` range. + /// + /// ```text + /// For the given ranges: + /// - 0..8 Vertex + /// - 4..12 Fragment + /// ``` + /// + /// You would need to upload this in three set_push_constants calls. First for the `Vertex` only range 0..4, second + /// for the `Vertex | Fragment` range 4..8, third for the `Fragment` range 8..12. + fn set_push_constants(&mut self, stages: wgt::ShaderStage, offset: u32, data: &[u8]); } impl<'a> RenderEncoder<'a> for RenderPass<'a> { @@ -132,6 +164,11 @@ impl<'a> RenderEncoder<'a> for RenderPass<'a> { ) { Self::draw_indexed_indirect(self, indirect_buffer, indirect_offset); } + + #[inline(always)] + fn set_push_constants(&mut self, stages: wgt::ShaderStage, offset: u32, data: &[u8]) { + Self::set_push_constants(self, stages, offset, data); + } } impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> { @@ -178,4 +215,9 @@ impl<'a> RenderEncoder<'a> for RenderBundleEncoder<'a> { ) { Self::draw_indexed_indirect(self, indirect_buffer, indirect_offset); } + + #[inline(always)] + fn set_push_constants(&mut self, stages: wgt::ShaderStage, offset: u32, data: &[u8]) { + Self::set_push_constants(self, stages, offset, data); + } }