mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
extract set_pipeline
from render_pass_end_impl
This commit is contained in:
parent
bc683fae3a
commit
36e5381531
@ -3,6 +3,7 @@ use crate::command::{
|
|||||||
validate_and_begin_occlusion_query, validate_and_begin_pipeline_statistics_query,
|
validate_and_begin_occlusion_query, validate_and_begin_pipeline_statistics_query,
|
||||||
};
|
};
|
||||||
use crate::init_tracker::BufferInitTrackerAction;
|
use crate::init_tracker::BufferInitTrackerAction;
|
||||||
|
use crate::pipeline::RenderPipeline;
|
||||||
use crate::resource::Resource;
|
use crate::resource::Resource;
|
||||||
use crate::snatch::SnatchGuard;
|
use crate::snatch::SnatchGuard;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -1532,129 +1533,8 @@ impl Global {
|
|||||||
.map_pass_err(scope)?;
|
.map_pass_err(scope)?;
|
||||||
}
|
}
|
||||||
ArcRenderCommand::SetPipeline(pipeline) => {
|
ArcRenderCommand::SetPipeline(pipeline) => {
|
||||||
api_log!("RenderPass::set_pipeline {}", pipeline.error_ident());
|
|
||||||
|
|
||||||
let scope = PassErrorScope::SetPipelineRender(pipeline.as_info().id());
|
let scope = PassErrorScope::SetPipelineRender(pipeline.as_info().id());
|
||||||
state.pipeline = Some(pipeline.as_info().id());
|
set_pipeline(&mut state, &cmd_buf, pipeline).map_pass_err(scope)?;
|
||||||
|
|
||||||
let pipeline = state.tracker.render_pipelines.insert_single(pipeline);
|
|
||||||
|
|
||||||
pipeline
|
|
||||||
.same_device_as(cmd_buf.as_ref())
|
|
||||||
.map_pass_err(scope)?;
|
|
||||||
|
|
||||||
state
|
|
||||||
.info
|
|
||||||
.context
|
|
||||||
.check_compatible(
|
|
||||||
&pipeline.pass_context,
|
|
||||||
RenderPassCompatibilityCheckType::RenderPipeline,
|
|
||||||
)
|
|
||||||
.map_err(RenderCommandError::IncompatiblePipelineTargets)
|
|
||||||
.map_pass_err(scope)?;
|
|
||||||
|
|
||||||
state.pipeline_flags = pipeline.flags;
|
|
||||||
|
|
||||||
if (pipeline.flags.contains(PipelineFlags::WRITES_DEPTH)
|
|
||||||
&& state.info.is_depth_read_only)
|
|
||||||
|| (pipeline.flags.contains(PipelineFlags::WRITES_STENCIL)
|
|
||||||
&& state.info.is_stencil_read_only)
|
|
||||||
{
|
|
||||||
return Err(RenderCommandError::IncompatiblePipelineRods)
|
|
||||||
.map_pass_err(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
state
|
|
||||||
.blend_constant
|
|
||||||
.require(pipeline.flags.contains(PipelineFlags::BLEND_CONSTANT));
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
state.raw_encoder.set_render_pipeline(pipeline.raw());
|
|
||||||
}
|
|
||||||
|
|
||||||
if pipeline.flags.contains(PipelineFlags::STENCIL_REFERENCE) {
|
|
||||||
unsafe {
|
|
||||||
state
|
|
||||||
.raw_encoder
|
|
||||||
.set_stencil_reference(state.stencil_reference);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rebind resource
|
|
||||||
if state.binder.pipeline_layout.is_none()
|
|
||||||
|| !state
|
|
||||||
.binder
|
|
||||||
.pipeline_layout
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.is_equal(&pipeline.layout)
|
|
||||||
{
|
|
||||||
let (start_index, entries) = state.binder.change_pipeline_layout(
|
|
||||||
&pipeline.layout,
|
|
||||||
&pipeline.late_sized_buffer_groups,
|
|
||||||
);
|
|
||||||
if !entries.is_empty() {
|
|
||||||
for (i, e) in entries.iter().enumerate() {
|
|
||||||
if let Some(group) = e.group.as_ref() {
|
|
||||||
let raw_bg = group
|
|
||||||
.try_raw(state.snatch_guard)
|
|
||||||
.map_pass_err(scope)?;
|
|
||||||
unsafe {
|
|
||||||
state.raw_encoder.set_bind_group(
|
|
||||||
pipeline.layout.raw(),
|
|
||||||
start_index as u32 + i as u32,
|
|
||||||
raw_bg,
|
|
||||||
&e.dynamic_offsets,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear push constant ranges
|
|
||||||
let non_overlapping = super::bind::compute_nonoverlapping_ranges(
|
|
||||||
&pipeline.layout.push_constant_ranges,
|
|
||||||
);
|
|
||||||
for range in non_overlapping {
|
|
||||||
let offset = range.range.start;
|
|
||||||
let size_bytes = range.range.end - offset;
|
|
||||||
super::push_constant_clear(
|
|
||||||
offset,
|
|
||||||
size_bytes,
|
|
||||||
|clear_offset, clear_data| unsafe {
|
|
||||||
state.raw_encoder.set_push_constants(
|
|
||||||
pipeline.layout.raw(),
|
|
||||||
range.stages,
|
|
||||||
clear_offset,
|
|
||||||
clear_data,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.index.pipeline_format = pipeline.strip_index_format;
|
|
||||||
|
|
||||||
let vertex_steps_len = pipeline.vertex_steps.len();
|
|
||||||
state.vertex.buffers_required = vertex_steps_len as u32;
|
|
||||||
|
|
||||||
// Initialize each `vertex.inputs[i].step` from
|
|
||||||
// `pipeline.vertex_steps[i]`. Enlarge `vertex.inputs`
|
|
||||||
// as necessary to accommodate 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
ArcRenderCommand::SetIndexBuffer {
|
ArcRenderCommand::SetIndexBuffer {
|
||||||
buffer,
|
buffer,
|
||||||
@ -2555,6 +2435,123 @@ fn set_bind_group<A: HalApi>(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_pipeline<A: HalApi>(
|
||||||
|
state: &mut State<A>,
|
||||||
|
cmd_buf: &Arc<CommandBuffer<A>>,
|
||||||
|
pipeline: Arc<RenderPipeline<A>>,
|
||||||
|
) -> Result<(), RenderPassErrorInner> {
|
||||||
|
api_log!("RenderPass::set_pipeline {}", pipeline.error_ident());
|
||||||
|
|
||||||
|
state.pipeline = Some(pipeline.as_info().id());
|
||||||
|
|
||||||
|
let pipeline = state.tracker.render_pipelines.insert_single(pipeline);
|
||||||
|
|
||||||
|
pipeline.same_device_as(cmd_buf.as_ref())?;
|
||||||
|
|
||||||
|
state
|
||||||
|
.info
|
||||||
|
.context
|
||||||
|
.check_compatible(
|
||||||
|
&pipeline.pass_context,
|
||||||
|
RenderPassCompatibilityCheckType::RenderPipeline,
|
||||||
|
)
|
||||||
|
.map_err(RenderCommandError::IncompatiblePipelineTargets)?;
|
||||||
|
|
||||||
|
state.pipeline_flags = pipeline.flags;
|
||||||
|
|
||||||
|
if (pipeline.flags.contains(PipelineFlags::WRITES_DEPTH) && state.info.is_depth_read_only)
|
||||||
|
|| (pipeline.flags.contains(PipelineFlags::WRITES_STENCIL)
|
||||||
|
&& state.info.is_stencil_read_only)
|
||||||
|
{
|
||||||
|
return Err(RenderCommandError::IncompatiblePipelineRods.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
state
|
||||||
|
.blend_constant
|
||||||
|
.require(pipeline.flags.contains(PipelineFlags::BLEND_CONSTANT));
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
state.raw_encoder.set_render_pipeline(pipeline.raw());
|
||||||
|
}
|
||||||
|
|
||||||
|
if pipeline.flags.contains(PipelineFlags::STENCIL_REFERENCE) {
|
||||||
|
unsafe {
|
||||||
|
state
|
||||||
|
.raw_encoder
|
||||||
|
.set_stencil_reference(state.stencil_reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebind resource
|
||||||
|
if state.binder.pipeline_layout.is_none()
|
||||||
|
|| !state
|
||||||
|
.binder
|
||||||
|
.pipeline_layout
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.is_equal(&pipeline.layout)
|
||||||
|
{
|
||||||
|
let (start_index, entries) = state
|
||||||
|
.binder
|
||||||
|
.change_pipeline_layout(&pipeline.layout, &pipeline.late_sized_buffer_groups);
|
||||||
|
if !entries.is_empty() {
|
||||||
|
for (i, e) in entries.iter().enumerate() {
|
||||||
|
if let Some(group) = e.group.as_ref() {
|
||||||
|
let raw_bg = group.try_raw(state.snatch_guard)?;
|
||||||
|
unsafe {
|
||||||
|
state.raw_encoder.set_bind_group(
|
||||||
|
pipeline.layout.raw(),
|
||||||
|
start_index as u32 + i as u32,
|
||||||
|
raw_bg,
|
||||||
|
&e.dynamic_offsets,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear push constant ranges
|
||||||
|
let non_overlapping =
|
||||||
|
super::bind::compute_nonoverlapping_ranges(&pipeline.layout.push_constant_ranges);
|
||||||
|
for range in non_overlapping {
|
||||||
|
let offset = range.range.start;
|
||||||
|
let size_bytes = range.range.end - offset;
|
||||||
|
super::push_constant_clear(offset, size_bytes, |clear_offset, clear_data| unsafe {
|
||||||
|
state.raw_encoder.set_push_constants(
|
||||||
|
pipeline.layout.raw(),
|
||||||
|
range.stages,
|
||||||
|
clear_offset,
|
||||||
|
clear_data,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.index.pipeline_format = pipeline.strip_index_format;
|
||||||
|
|
||||||
|
let vertex_steps_len = pipeline.vertex_steps.len();
|
||||||
|
state.vertex.buffers_required = vertex_steps_len as u32;
|
||||||
|
|
||||||
|
// Initialize each `vertex.inputs[i].step` from
|
||||||
|
// `pipeline.vertex_steps[i]`. Enlarge `vertex.inputs`
|
||||||
|
// as necessary to accommodate 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
pub fn render_pass_set_bind_group(
|
pub fn render_pass_set_bind_group(
|
||||||
&self,
|
&self,
|
||||||
|
Loading…
Reference in New Issue
Block a user