Implement push constants for metal backend (#2314)

* Implement push constants for metal backend

* Clear push constants on reset; get upload size from layout
This commit is contained in:
TheOnlyMrCat
2021-12-25 06:49:57 +11:00
committed by GitHub
parent 97e6ea7b71
commit 61fa8a3b63
4 changed files with 43 additions and 5 deletions

View File

@@ -918,6 +918,7 @@ impl super::PrivateCapabilities {
| F::MAPPABLE_PRIMARY_BUFFERS
| F::VERTEX_WRITABLE_STORAGE
| F::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES
| F::PUSH_CONSTANTS
| F::POLYGON_MODE_LINE
| F::CLEAR_COMMANDS
| F::TEXTURE_FORMAT_16BIT_NORM;

View File

@@ -16,6 +16,7 @@ impl Default for super::CommandState {
stage_infos: Default::default(),
storage_buffer_length_map: Default::default(),
work_group_memory_sizes: Vec::new(),
push_constants: Vec::new(),
}
}
}
@@ -61,6 +62,7 @@ impl super::CommandState {
self.stage_infos.fs.clear();
self.stage_infos.cs.clear();
self.work_group_memory_sizes.clear();
self.push_constants.clear();
}
fn make_sizes_buffer_update<'a>(
@@ -587,12 +589,41 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
unsafe fn set_push_constants(
&mut self,
_layout: &super::PipelineLayout,
_stages: wgt::ShaderStages,
_offset: u32,
_data: &[u32],
layout: &super::PipelineLayout,
stages: wgt::ShaderStages,
offset: u32,
data: &[u32],
) {
//TODO
let state_pc = &mut self.state.push_constants;
if state_pc.len() < layout.total_push_constants as usize {
state_pc.resize(layout.total_push_constants as usize, 0);
}
assert_eq!(offset as usize % WORD_SIZE, 0);
let offset = offset as usize / WORD_SIZE;
state_pc[offset..offset + data.len()].copy_from_slice(data);
if stages.contains(wgt::ShaderStages::COMPUTE) {
self.state.compute.as_ref().unwrap().set_bytes(
layout.push_constants_infos.cs.unwrap().buffer_index as _,
(layout.total_push_constants as usize * WORD_SIZE) as _,
state_pc.as_ptr() as _,
)
}
if stages.contains(wgt::ShaderStages::VERTEX) {
self.state.render.as_ref().unwrap().set_vertex_bytes(
layout.push_constants_infos.vs.unwrap().buffer_index as _,
(layout.total_push_constants as usize * WORD_SIZE) as _,
state_pc.as_ptr() as _,
)
}
if stages.contains(wgt::ShaderStages::FRAGMENT) {
self.state.render.as_ref().unwrap().set_fragment_bytes(
layout.push_constants_infos.fs.unwrap().buffer_index as _,
(layout.total_push_constants as usize * WORD_SIZE) as _,
state_pc.as_ptr() as _,
)
}
}
unsafe fn insert_debug_marker(&mut self, label: &str) {

View File

@@ -471,6 +471,7 @@ impl crate::Device<super::Api> for super::Device {
let mut bind_group_infos = arrayvec::ArrayVec::new();
// First, place the push constants
let mut total_push_constants = 0;
for info in stage_data.iter_mut() {
for pcr in desc.push_constant_ranges {
if pcr.stages.contains(map_naga_stage(info.stage)) {
@@ -492,6 +493,8 @@ impl crate::Device<super::Api> for super::Device {
info.pc_buffer = Some(info.counters.buffers);
info.counters.buffers += 1;
}
total_push_constants = total_push_constants.max(info.pc_limit);
}
// Second, place the described resources
@@ -641,6 +644,7 @@ impl crate::Device<super::Api> for super::Device {
image: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
},
},
total_push_constants,
})
}
unsafe fn destroy_pipeline_layout(&self, _pipeline_layout: super::PipelineLayout) {}

View File

@@ -524,6 +524,7 @@ pub struct PipelineLayout {
bind_group_infos: ArrayVec<BindGroupLayoutInfo, { crate::MAX_BIND_GROUPS }>,
push_constants_infos: MultiStageData<Option<PushConstantsInfo>>,
total_counters: MultiStageResourceCounters,
total_push_constants: u32,
}
trait AsNative {
@@ -709,6 +710,7 @@ struct CommandState {
stage_infos: MultiStageData<PipelineStageInfo>,
storage_buffer_length_map: fxhash::FxHashMap<naga::ResourceBinding, wgt::BufferSize>,
work_group_memory_sizes: Vec<u32>,
push_constants: Vec<u32>,
}
pub struct CommandEncoder {