mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 16:24:24 +00:00
Introduce VertexStep
: a stride and a step mode. (#2768)
This is used in various places around render pipelines, passes, and bundles. The public `wgpu_core::pipeline::VertexBufferLayout` could use `VertexStep` as well, but I think it's best to let that continue to resemble `GPUVertexBufferLayout`.
This commit is contained in:
parent
a4352a1dac
commit
3a193ec3d3
@ -376,7 +376,7 @@ impl RenderBundleEncoder {
|
||||
state.pipeline_layout = Some(pipeline.layout_id.value);
|
||||
|
||||
state.set_pipeline(
|
||||
&pipeline.vertex_strides,
|
||||
&pipeline.vertex_steps,
|
||||
&layout.bind_group_layout_ids,
|
||||
&layout.push_constant_ranges,
|
||||
);
|
||||
@ -996,8 +996,7 @@ impl IndexState {
|
||||
struct VertexState {
|
||||
buffer: Option<id::BufferId>,
|
||||
range: Range<wgt::BufferAddress>,
|
||||
stride: wgt::BufferAddress,
|
||||
rate: wgt::VertexStepMode,
|
||||
step: pipeline::VertexStep,
|
||||
is_dirty: bool,
|
||||
}
|
||||
|
||||
@ -1008,8 +1007,7 @@ impl VertexState {
|
||||
Self {
|
||||
buffer: None,
|
||||
range: 0..0,
|
||||
stride: 0,
|
||||
rate: wgt::VertexStepMode::Vertex,
|
||||
step: pipeline::VertexStep::default(),
|
||||
is_dirty: false,
|
||||
}
|
||||
}
|
||||
@ -1149,11 +1147,11 @@ impl<A: HalApi> State<A> {
|
||||
instance_limit_slot: 0,
|
||||
};
|
||||
for (idx, vbs) in self.vertex.iter().enumerate() {
|
||||
if vbs.stride == 0 {
|
||||
if vbs.step.stride == 0 {
|
||||
continue;
|
||||
}
|
||||
let limit = ((vbs.range.end - vbs.range.start) / vbs.stride) as u32;
|
||||
match vbs.rate {
|
||||
let limit = ((vbs.range.end - vbs.range.start) / vbs.step.stride) as u32;
|
||||
match vbs.step.mode {
|
||||
wgt::VertexStepMode::Vertex => {
|
||||
if limit < vert_state.vertex_limit {
|
||||
vert_state.vertex_limit = limit;
|
||||
@ -1211,13 +1209,12 @@ impl<A: HalApi> State<A> {
|
||||
|
||||
fn set_pipeline(
|
||||
&mut self,
|
||||
vertex_strides: &[(wgt::BufferAddress, wgt::VertexStepMode)],
|
||||
steps: &[pipeline::VertexStep],
|
||||
layout_ids: &[id::Valid<id::BindGroupLayoutId>],
|
||||
push_constant_layouts: &[wgt::PushConstantRange],
|
||||
) {
|
||||
for (vs, &(stride, step_mode)) in self.vertex.iter_mut().zip(vertex_strides) {
|
||||
vs.stride = stride;
|
||||
vs.rate = step_mode;
|
||||
for (vs, &step) in self.vertex.iter_mut().zip(steps) {
|
||||
vs.step = step;
|
||||
}
|
||||
|
||||
let push_constants_changed = self
|
||||
|
@ -17,7 +17,7 @@ use crate::{
|
||||
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
|
||||
id,
|
||||
init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction},
|
||||
pipeline::PipelineFlags,
|
||||
pipeline::{self, PipelineFlags},
|
||||
resource::{self, Buffer, Texture, TextureView},
|
||||
track::{TextureSelector, UsageConflict, UsageScope},
|
||||
validation::{
|
||||
@ -298,16 +298,17 @@ impl IndexState {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct VertexBufferState {
|
||||
total_size: BufferAddress,
|
||||
stride: BufferAddress,
|
||||
rate: VertexStepMode,
|
||||
step: pipeline::VertexStep,
|
||||
bound: bool,
|
||||
}
|
||||
|
||||
impl VertexBufferState {
|
||||
const EMPTY: Self = Self {
|
||||
total_size: 0,
|
||||
stride: 0,
|
||||
rate: VertexStepMode::Vertex,
|
||||
step: pipeline::VertexStep {
|
||||
stride: 0,
|
||||
mode: VertexStepMode::Vertex,
|
||||
},
|
||||
bound: false,
|
||||
};
|
||||
}
|
||||
@ -332,11 +333,11 @@ impl VertexState {
|
||||
self.vertex_limit = u32::MAX;
|
||||
self.instance_limit = u32::MAX;
|
||||
for (idx, vbs) in self.inputs.iter().enumerate() {
|
||||
if vbs.stride == 0 || !vbs.bound {
|
||||
if vbs.step.stride == 0 || !vbs.bound {
|
||||
continue;
|
||||
}
|
||||
let limit = (vbs.total_size / vbs.stride) as u32;
|
||||
match vbs.rate {
|
||||
let limit = (vbs.total_size / vbs.step.stride) as u32;
|
||||
match vbs.step.mode {
|
||||
VertexStepMode::Vertex => {
|
||||
if limit < self.vertex_limit {
|
||||
self.vertex_limit = limit;
|
||||
@ -1340,24 +1341,25 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
|
||||
state.index.pipeline_format = pipeline.strip_index_format;
|
||||
|
||||
let vertex_strides_len = pipeline.vertex_strides.len();
|
||||
state.vertex.buffers_required = vertex_strides_len as u32;
|
||||
let vertex_steps_len = pipeline.vertex_steps.len();
|
||||
state.vertex.buffers_required = vertex_steps_len as u32;
|
||||
|
||||
while state.vertex.inputs.len() < vertex_strides_len {
|
||||
// Initialize each `vertex.inputs[i].step` from
|
||||
// `pipeline.vertex_steps[i]`. Enlarge `vertex.inputs`
|
||||
// as necessary to accomodate all slots in the
|
||||
// pipeline. If `vertex.inputs` is longer, fill the
|
||||
// extra entries with default `VertexStep`s.
|
||||
while state.vertex.inputs.len() < vertex_steps_len {
|
||||
state.vertex.inputs.push(VertexBufferState::EMPTY);
|
||||
}
|
||||
|
||||
// Update vertex buffer limits
|
||||
for (vbs, &(stride, rate)) in
|
||||
state.vertex.inputs.iter_mut().zip(&pipeline.vertex_strides)
|
||||
{
|
||||
vbs.stride = stride;
|
||||
vbs.rate = rate;
|
||||
}
|
||||
for vbs in state.vertex.inputs.iter_mut().skip(vertex_strides_len) {
|
||||
vbs.stride = 0;
|
||||
vbs.rate = VertexStepMode::Vertex;
|
||||
// This is worse as a `zip`, but it's close.
|
||||
let mut steps = pipeline.vertex_steps.iter();
|
||||
for input in state.vertex.inputs.iter_mut() {
|
||||
input.step = steps.next().cloned().unwrap_or_default();
|
||||
}
|
||||
|
||||
// Update vertex buffer limits.
|
||||
state.vertex.update_limits();
|
||||
}
|
||||
RenderCommand::SetIndexBuffer {
|
||||
|
@ -2458,13 +2458,14 @@ impl<A: HalApi> Device<A> {
|
||||
let mut io = validation::StageIo::default();
|
||||
let mut validated_stages = wgt::ShaderStages::empty();
|
||||
|
||||
let mut vertex_strides = Vec::with_capacity(desc.vertex.buffers.len());
|
||||
let mut vertex_steps = Vec::with_capacity(desc.vertex.buffers.len());
|
||||
let mut vertex_buffers = Vec::with_capacity(desc.vertex.buffers.len());
|
||||
let mut total_attributes = 0;
|
||||
for (i, vb_state) in desc.vertex.buffers.iter().enumerate() {
|
||||
vertex_strides
|
||||
.alloc()
|
||||
.init((vb_state.array_stride, vb_state.step_mode));
|
||||
vertex_steps.alloc().init(pipeline::VertexStep {
|
||||
stride: vb_state.array_stride,
|
||||
mode: vb_state.step_mode,
|
||||
});
|
||||
if vb_state.attributes.is_empty() {
|
||||
continue;
|
||||
}
|
||||
@ -2862,7 +2863,7 @@ impl<A: HalApi> Device<A> {
|
||||
pass_context,
|
||||
flags,
|
||||
strip_index_format: desc.primitive.strip_index_format,
|
||||
vertex_strides,
|
||||
vertex_steps,
|
||||
late_sized_buffer_groups,
|
||||
life_guard: LifeGuard::new(desc.label.borrow_or_default()),
|
||||
};
|
||||
|
@ -357,6 +357,25 @@ bitflags::bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
/// How a render pipeline will retrieve attributes from a particular vertex buffer.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct VertexStep {
|
||||
/// The byte stride in the buffer between one attribute value and the next.
|
||||
pub stride: wgt::BufferAddress,
|
||||
|
||||
/// Whether the buffer is indexed by vertex number or instance number.
|
||||
pub mode: wgt::VertexStepMode,
|
||||
}
|
||||
|
||||
impl Default for VertexStep {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
stride: 0,
|
||||
mode: wgt::VertexStepMode::Vertex,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RenderPipeline<A: hal::Api> {
|
||||
pub(crate) raw: A::RenderPipeline,
|
||||
@ -365,7 +384,7 @@ pub struct RenderPipeline<A: hal::Api> {
|
||||
pub(crate) pass_context: RenderPassContext,
|
||||
pub(crate) flags: PipelineFlags,
|
||||
pub(crate) strip_index_format: Option<wgt::IndexFormat>,
|
||||
pub(crate) vertex_strides: Vec<(wgt::BufferAddress, wgt::VertexStepMode)>,
|
||||
pub(crate) vertex_steps: Vec<VertexStep>,
|
||||
pub(crate) late_sized_buffer_groups: ArrayVec<LateSizedBufferGroup, { hal::MAX_BIND_GROUPS }>,
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user