mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[rs] Merge #435
435: Implement PUSH_CONSTANTS feature r=kvark a=cwfitzgerald The rust half of the push constant extensions, continuing from https://github.com/gfx-rs/wgpu/pull/777. Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
This commit is contained in:
@@ -27,14 +27,14 @@ vulkan = ["wgc/gfx-backend-vulkan"]
|
||||
package = "wgpu-core"
|
||||
version = "0.5"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "d7ee89018bed6b2e050b8160b2bd837d89f598a6"
|
||||
rev = "f67771fb87ce17a7f7e09f9a01149b4132196928"
|
||||
features = ["raw-window-handle"]
|
||||
|
||||
[dependencies.wgt]
|
||||
package = "wgpu-types"
|
||||
version = "0.5"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "d7ee89018bed6b2e050b8160b2bd837d89f598a6"
|
||||
rev = "f67771fb87ce17a7f7e09f9a01149b4132196928"
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.5"
|
||||
|
||||
@@ -5,7 +5,7 @@ For the simplest examples without using any helping code (see `framework.rs` her
|
||||
- `hello-triangle` for graphics and presentation
|
||||
- `hello-compute` for pure computing
|
||||
|
||||
Notably, `capture` example show rendering without a surface/window. It reads back the contents and saves them to a file.
|
||||
Notably, `capture` example shows rendering without a surface/window. It reads back the contents and saves them to a file.
|
||||
|
||||
All framework-based examples render to the window.
|
||||
|
||||
@@ -32,6 +32,7 @@ All framework-based examples render to the window.
|
||||
| compute passes | :star: | | | | | | | |
|
||||
| optional extensions | | | | | | | :star: | |
|
||||
| - binding indexing | | | | | | | :star: | |
|
||||
| - push constants | | | | | | | :star: | |
|
||||
| WGSL shaders | | | | | | | | |
|
||||
|
||||
## Hacking
|
||||
|
||||
@@ -90,6 +90,7 @@ impl framework::Example for Example {
|
||||
let compute_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&compute_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
// create render pipeline with empty bind group layout
|
||||
@@ -97,6 +98,7 @@ impl framework::Example for Example {
|
||||
let render_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
|
||||
@@ -161,6 +161,7 @@ impl framework::Example for Example {
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
// Create the texture
|
||||
|
||||
@@ -33,6 +33,9 @@ pub trait Example: 'static + Sized {
|
||||
fn needed_features() -> wgpu::Features {
|
||||
wgpu::Features::empty()
|
||||
}
|
||||
fn needed_limits() -> wgpu::Limits {
|
||||
wgpu::Limits::default()
|
||||
}
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
@@ -97,12 +100,14 @@ async fn setup<E: Example>(title: &str) -> Setup {
|
||||
|
||||
let adapter_features = adapter.features();
|
||||
|
||||
let needed_limits = E::needed_limits();
|
||||
|
||||
let trace_dir = std::env::var("WGPU_TRACE");
|
||||
let (device, queue) = adapter
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
features: adapter_features & needed_features,
|
||||
limits: wgpu::Limits::default(),
|
||||
limits: needed_limits,
|
||||
shader_validation: true,
|
||||
},
|
||||
trace_dir.ok().as_ref().map(std::path::Path::new),
|
||||
|
||||
@@ -81,6 +81,7 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let compute_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
|
||||
|
||||
@@ -36,6 +36,7 @@ async fn run(event_loop: EventLoop<()>, window: Window, swapchain_format: wgpu::
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/// This example shows how to describe the adapter in use.
|
||||
async fn run() {
|
||||
#[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
|
||||
let adapter = wgpu::Instance::new(wgpu::BackendBit::PRIMARY)
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
|
||||
@@ -101,6 +101,7 @@ impl Example {
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let vs_module = device.create_shader_module(wgpu::include_spirv!("blit.vert.spv"));
|
||||
@@ -249,6 +250,7 @@ impl framework::Example for Example {
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
// Create the texture
|
||||
|
||||
@@ -141,6 +141,7 @@ impl framework::Example for Example {
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let multisampled_framebuffer =
|
||||
|
||||
@@ -442,6 +442,7 @@ impl framework::Example for Example {
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
@@ -553,6 +554,7 @@ impl framework::Example for Example {
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
|
||||
@@ -84,6 +84,7 @@ impl framework::Example for Skybox {
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
// Create the render pipeline
|
||||
|
||||
@@ -23,12 +23,6 @@ struct Uniform {
|
||||
unsafe impl Pod for Uniform {}
|
||||
unsafe impl Zeroable for Uniform {}
|
||||
|
||||
struct UniformWorkaroundData {
|
||||
bind_group_layout: wgpu::BindGroupLayout,
|
||||
bind_group0: wgpu::BindGroup,
|
||||
bind_group1: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
fn vertex(pos: [i8; 2], tc: [i8; 2], index: i8) -> Vertex {
|
||||
Vertex {
|
||||
_pos: [pos[0] as f32, pos[1] as f32],
|
||||
@@ -81,7 +75,7 @@ struct Example {
|
||||
bind_group: wgpu::BindGroup,
|
||||
vertex_buffer: wgpu::Buffer,
|
||||
index_buffer: wgpu::Buffer,
|
||||
uniform_workaround_data: Option<UniformWorkaroundData>,
|
||||
uniform_workaround: bool,
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
@@ -90,6 +84,13 @@ impl framework::Example for Example {
|
||||
| wgpu::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
|
||||
| wgpu::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING
|
||||
| wgpu::Features::SAMPLED_TEXTURE_BINDING_ARRAY
|
||||
| wgpu::Features::PUSH_CONSTANTS
|
||||
}
|
||||
fn needed_limits() -> wgpu::Limits {
|
||||
wgpu::Limits {
|
||||
max_push_constant_size: 4,
|
||||
..wgpu::Limits::default()
|
||||
}
|
||||
}
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
@@ -131,56 +132,6 @@ impl framework::Example for Example {
|
||||
let index_buffer = device
|
||||
.create_buffer_with_data(bytemuck::cast_slice(&index_data), wgpu::BufferUsage::INDEX);
|
||||
|
||||
let uniform_workaround_data = if uniform_workaround {
|
||||
let buffer0 = device.create_buffer_with_data(
|
||||
&bytemuck::cast_slice(&[Uniform { index: 0 }]),
|
||||
wgpu::BufferUsage::UNIFORM,
|
||||
);
|
||||
let buffer1 = device.create_buffer_with_data(
|
||||
&bytemuck::cast_slice(&[Uniform { index: 1 }]),
|
||||
wgpu::BufferUsage::UNIFORM,
|
||||
);
|
||||
|
||||
let bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
)],
|
||||
label: Some("uniform workaround bind group layout"),
|
||||
});
|
||||
|
||||
let bind_group0 = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(buffer0.slice(..)),
|
||||
}],
|
||||
label: Some("uniform workaround bind group 0"),
|
||||
});
|
||||
|
||||
let bind_group1 = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(buffer1.slice(..)),
|
||||
}],
|
||||
label: Some("uniform workaround bind group 1"),
|
||||
});
|
||||
|
||||
Some(UniformWorkaroundData {
|
||||
bind_group_layout,
|
||||
bind_group0,
|
||||
bind_group1,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let red_texture_data = create_texture_data(Color::RED);
|
||||
let green_texture_data = create_texture_data(Color::GREEN);
|
||||
|
||||
@@ -289,13 +240,18 @@ impl framework::Example for Example {
|
||||
label: Some("bind group"),
|
||||
});
|
||||
|
||||
let pipeline_layout = if let Some(ref workaround) = uniform_workaround_data {
|
||||
let pipeline_layout = if uniform_workaround {
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, &workaround.bind_group_layout],
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[wgpu::PushConstantRange {
|
||||
stages: wgpu::ShaderStage::FRAGMENT,
|
||||
range: 0..4,
|
||||
}],
|
||||
})
|
||||
} else {
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
})
|
||||
};
|
||||
|
||||
@@ -342,7 +298,7 @@ impl framework::Example for Example {
|
||||
index_buffer,
|
||||
bind_group,
|
||||
pipeline,
|
||||
uniform_workaround_data,
|
||||
uniform_workaround,
|
||||
}
|
||||
}
|
||||
fn resize(
|
||||
@@ -378,14 +334,28 @@ impl framework::Example for Example {
|
||||
}],
|
||||
depth_stencil_attachment: None,
|
||||
});
|
||||
|
||||
let uniform_workaround_data = if self.uniform_workaround {
|
||||
Some([Uniform { index: 0 }, Uniform { index: 1 }])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
rpass.set_pipeline(&self.pipeline);
|
||||
rpass.set_bind_group(0, &self.bind_group, &[]);
|
||||
rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
||||
rpass.set_index_buffer(self.index_buffer.slice(..));
|
||||
if let Some(ref workaround) = self.uniform_workaround_data {
|
||||
rpass.set_bind_group(1, &workaround.bind_group0, &[]);
|
||||
if let Some(ref data) = uniform_workaround_data {
|
||||
rpass.set_push_constants(
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
0,
|
||||
bytemuck::cast_slice(&data[0..1]),
|
||||
);
|
||||
rpass.draw_indexed(0..6, 0, 0..1);
|
||||
rpass.set_bind_group(1, &workaround.bind_group1, &[]);
|
||||
rpass.set_push_constants(
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
0,
|
||||
bytemuck::cast_slice(&data[1..2]),
|
||||
);
|
||||
rpass.draw_indexed(6..12, 0, 0..1);
|
||||
} else {
|
||||
rpass.draw_indexed(0..12, 0, 0..1);
|
||||
|
||||
@@ -6,7 +6,7 @@ layout(location = 0) out vec4 o_Color;
|
||||
|
||||
layout(set = 0, binding = 0) uniform texture2D u_Textures[2];
|
||||
layout(set = 0, binding = 1) uniform sampler u_Sampler;
|
||||
layout(set = 1, binding = 0) uniform Uniforms {
|
||||
layout(push_constant) uniform Uniforms {
|
||||
int u_Index; // dynamically uniform
|
||||
};
|
||||
|
||||
|
||||
Binary file not shown.
@@ -414,11 +414,13 @@ impl framework::Example for Example {
|
||||
let water_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&water_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let terrain_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&terrain_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let water_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
|
||||
@@ -33,6 +33,7 @@ pub type Context = wgc::hub::Global<wgc::hub::IdentityManagerFactory>;
|
||||
mod pass_impl {
|
||||
use super::Context;
|
||||
use smallvec::SmallVec;
|
||||
use std::convert::TryInto;
|
||||
use std::ops::Range;
|
||||
use wgc::command::{bundle_ffi::*, compute_ffi::*, render_ffi::*};
|
||||
|
||||
@@ -56,6 +57,18 @@ mod pass_impl {
|
||||
)
|
||||
}
|
||||
}
|
||||
fn set_push_constants(&mut self, offset: u32, data: &[u32]) {
|
||||
unsafe {
|
||||
wgpu_compute_pass_set_push_constant(
|
||||
self,
|
||||
offset,
|
||||
(data.len() * std::mem::size_of::<u32>())
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
data.as_ptr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
fn dispatch(&mut self, x: u32, y: u32, z: u32) {
|
||||
wgpu_compute_pass_dispatch(self, x, y, z)
|
||||
}
|
||||
@@ -105,6 +118,19 @@ mod pass_impl {
|
||||
) {
|
||||
wgpu_render_pass_set_vertex_buffer(self, slot, *buffer, offset, size)
|
||||
}
|
||||
fn set_push_constants(&mut self, stages: wgt::ShaderStage, offset: u32, data: &[u32]) {
|
||||
unsafe {
|
||||
wgpu_render_pass_set_push_constants(
|
||||
self,
|
||||
stages,
|
||||
offset,
|
||||
(data.len() * std::mem::size_of::<u32>())
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
data.as_ptr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
|
||||
wgpu_render_pass_draw(
|
||||
self,
|
||||
@@ -288,6 +314,20 @@ mod pass_impl {
|
||||
) {
|
||||
wgpu_render_bundle_set_vertex_buffer(self, slot, *buffer, offset, size)
|
||||
}
|
||||
|
||||
fn set_push_constants(&mut self, stages: wgt::ShaderStage, offset: u32, data: &[u32]) {
|
||||
unsafe {
|
||||
wgpu_render_bundle_set_push_constants(
|
||||
self,
|
||||
stages,
|
||||
offset,
|
||||
(data.len() * std::mem::size_of::<u32>())
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
data.as_ptr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
|
||||
wgpu_render_bundle_draw(
|
||||
self,
|
||||
@@ -583,17 +623,27 @@ impl crate::Context for Context {
|
||||
desc: &PipelineLayoutDescriptor,
|
||||
) -> Self::PipelineLayoutId {
|
||||
wgc::span!(_guard, TRACE, "Device::create_pipeline_layout wrapper");
|
||||
//TODO: avoid allocation here
|
||||
|
||||
// Limit is always less or equal to wgc::MAX_BIND_GROUPS, so this is always right
|
||||
// Guards following ArrayVec
|
||||
assert!(
|
||||
desc.bind_group_layouts.len() <= wgc::MAX_BIND_GROUPS,
|
||||
"Bind group layout count {} exceeds device bind group limit {}",
|
||||
desc.bind_group_layouts.len(),
|
||||
wgc::MAX_BIND_GROUPS
|
||||
);
|
||||
|
||||
let temp_layouts = desc
|
||||
.bind_group_layouts
|
||||
.iter()
|
||||
.map(|bgl| bgl.id)
|
||||
.collect::<Vec<_>>();
|
||||
.collect::<ArrayVec<[_; wgc::MAX_BIND_GROUPS]>>();
|
||||
|
||||
gfx_select!(*device => self.device_create_pipeline_layout(
|
||||
*device,
|
||||
&wgc::binding_model::PipelineLayoutDescriptor {
|
||||
&wgt::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &temp_layouts,
|
||||
push_constant_ranges: &desc.push_constant_ranges,
|
||||
},
|
||||
PhantomData
|
||||
))
|
||||
|
||||
@@ -71,6 +71,9 @@ impl crate::ComputePassInner<Context> for ComputePass {
|
||||
offsets.len() as u32,
|
||||
);
|
||||
}
|
||||
fn set_push_constants(&mut self, _offset: u32, _data: &[u32]) {
|
||||
panic!("PUSH_CONSTANTS feature must be enabled to call multi_draw_indexed_indirect")
|
||||
}
|
||||
fn dispatch(&mut self, x: u32, y: u32, z: u32) {
|
||||
self.0.dispatch_with_y_and_z(x, y, z);
|
||||
}
|
||||
@@ -129,6 +132,9 @@ impl crate::RenderInner<Context> for RenderPass {
|
||||
size.expect("TODO").get() as f64,
|
||||
);
|
||||
}
|
||||
fn set_push_constants(&mut self, _stages: wgt::ShaderStage, _offset: u32, _data: &[u32]) {
|
||||
panic!("PUSH_CONSTANTS feature must be enabled to call multi_draw_indexed_indirect")
|
||||
}
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
|
||||
self.0
|
||||
.draw_with_instance_count_and_first_vertex_and_first_instance(
|
||||
|
||||
107
wgpu/src/lib.rs
107
wgpu/src/lib.rs
@@ -29,12 +29,13 @@ pub use wgt::{
|
||||
ColorStateDescriptor, ColorWrite, CommandBufferDescriptor, CompareFunction, CullMode,
|
||||
DepthStencilStateDescriptor, DeviceDescriptor, DynamicOffset, Extent3d, Features, FilterMode,
|
||||
FrontFace, IndexFormat, InputStepMode, Limits, Origin3d, PowerPreference, PresentMode,
|
||||
PrimitiveTopology, RasterizationStateDescriptor, RenderBundleEncoderDescriptor, ShaderLocation,
|
||||
ShaderStage, StencilOperation, StencilStateFaceDescriptor, SwapChainDescriptor,
|
||||
SwapChainStatus, TextureAspect, TextureComponentType, TextureDataLayout, TextureDimension,
|
||||
TextureFormat, TextureUsage, TextureViewDimension, VertexAttributeDescriptor,
|
||||
VertexBufferDescriptor, VertexFormat, VertexStateDescriptor, BIND_BUFFER_ALIGNMENT,
|
||||
COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT,
|
||||
PrimitiveTopology, PushConstantRange, RasterizationStateDescriptor,
|
||||
RenderBundleEncoderDescriptor, ShaderLocation, ShaderStage, StencilOperation,
|
||||
StencilStateFaceDescriptor, SwapChainDescriptor, SwapChainStatus, TextureAspect,
|
||||
TextureComponentType, TextureDataLayout, TextureDimension, TextureFormat, TextureUsage,
|
||||
TextureViewDimension, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
|
||||
VertexStateDescriptor, BIND_BUFFER_ALIGNMENT, COPY_BUFFER_ALIGNMENT,
|
||||
COPY_BYTES_PER_ROW_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT,
|
||||
};
|
||||
|
||||
use backend::Context as C;
|
||||
@@ -47,6 +48,7 @@ trait ComputePassInner<Ctx: Context> {
|
||||
bind_group: &Ctx::BindGroupId,
|
||||
offsets: &[DynamicOffset],
|
||||
);
|
||||
fn set_push_constants(&mut self, offset: u32, data: &[u32]);
|
||||
fn dispatch(&mut self, x: u32, y: u32, z: u32);
|
||||
fn dispatch_indirect(
|
||||
&mut self,
|
||||
@@ -76,6 +78,7 @@ trait RenderInner<Ctx: Context> {
|
||||
offset: BufferAddress,
|
||||
size: Option<BufferSize>,
|
||||
);
|
||||
fn set_push_constants(&mut self, stages: wgt::ShaderStage, offset: u32, data: &[u32]);
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>);
|
||||
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
|
||||
fn draw_indirect(&mut self, indirect_buffer: &Ctx::BufferId, indirect_offset: BufferAddress);
|
||||
@@ -857,6 +860,10 @@ pub use wgt::TextureViewDescriptor as TextureViewDescriptorBase;
|
||||
/// Describes a [`TextureView`].
|
||||
pub type TextureViewDescriptor<'a> = TextureViewDescriptorBase<Option<&'a str>>;
|
||||
|
||||
pub use wgt::PipelineLayoutDescriptor as PipelineLayoutDescriptorBase;
|
||||
/// Describes a [`PipelineLayout`].
|
||||
pub type PipelineLayoutDescriptor<'a> = PipelineLayoutDescriptorBase<'a, &'a BindGroupLayout>;
|
||||
|
||||
pub use wgt::SamplerDescriptor as SamplerDescriptorBase;
|
||||
/// Describes a [`Sampler`].
|
||||
pub type SamplerDescriptor<'a> = SamplerDescriptorBase<Option<&'a str>>;
|
||||
@@ -870,10 +877,6 @@ pub use wgt::BindGroupDescriptor as BindGroupDescriptorBase;
|
||||
pub type BindGroupDescriptor<'a> =
|
||||
BindGroupDescriptorBase<'a, &'a BindGroupLayout, BindGroupEntry<'a>>;
|
||||
|
||||
pub use wgt::PipelineLayoutDescriptor as PipelineLayoutDescriptorBase;
|
||||
/// Describes a pipeline layout.
|
||||
pub type PipelineLayoutDescriptor<'a> = PipelineLayoutDescriptorBase<'a, &'a BindGroupLayout>;
|
||||
|
||||
pub use wgt::ProgrammableStageDescriptor as ProgrammableStageDescriptorBase;
|
||||
/// Describes a programmable pipeline stage.
|
||||
pub type ProgrammableStageDescriptor<'a> = wgt::ProgrammableStageDescriptor<'a, &'a ShaderModule>;
|
||||
@@ -1921,6 +1924,41 @@ impl<'a> RenderPass<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Features::PUSH_CONSTANTS`] must be enabled on the device in order to call these functions.
|
||||
impl<'a> RenderPass<'a> {
|
||||
/// 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.
|
||||
pub fn set_push_constants(&mut self, stages: wgt::ShaderStage, offset: u32, data: &'a [u32]) {
|
||||
self.id.set_push_constants(stages, offset, data);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for RenderPass<'a> {
|
||||
fn drop(&mut self) {
|
||||
if !thread::panicking() {
|
||||
@@ -1967,6 +2005,20 @@ impl<'a> ComputePass<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Features::PUSH_CONSTANTS`] must be enabled on the device in order to call these functions.
|
||||
impl<'a> ComputePass<'a> {
|
||||
/// 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.
|
||||
pub fn set_push_constants(&mut self, offset: u32, data: &'a [u32]) {
|
||||
self.id.set_push_constants(offset, data);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for ComputePass<'a> {
|
||||
fn drop(&mut self) {
|
||||
if !thread::panicking() {
|
||||
@@ -2101,6 +2153,41 @@ impl<'a> RenderBundleEncoder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Features::PUSH_CONSTANTS`] must be enabled on the device in order to call these functions.
|
||||
impl<'a> RenderBundleEncoder<'a> {
|
||||
/// 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.
|
||||
pub fn set_push_constants(&mut self, stages: wgt::ShaderStage, offset: u32, data: &'a [u32]) {
|
||||
self.id.set_push_constants(stages, offset, data);
|
||||
}
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
/// Schedule a data write into `buffer` starting at `offset`.
|
||||
pub fn write_buffer(&self, buffer: &Buffer, offset: BufferAddress, data: &[u8]) {
|
||||
|
||||
Reference in New Issue
Block a user