mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-29 10:14:29 +00:00
Add DescriptorSetWithOffsets
type (#1641)
* Add DescriptorSetWithOffsets, remove the dynamic_offsets parameters on AutoCommandBufferBuilder * Modify StateCacher, add checking to DescriptorSetWithOffsets constructor * Add DescriptorSetWithOffsets to SyncCommandBufferBuilder
This commit is contained in:
parent
2ef4e57ee5
commit
0ad56aaeda
@ -166,7 +166,7 @@ fn main() {
|
||||
// `Arc`, this only clones the `Arc` and not the whole pipeline or set (which aren't
|
||||
// cloneable anyway). In this example we would avoid cloning them since this is the last
|
||||
// time we use them, but in a real code you would probably need to clone them.
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), ())
|
||||
.unwrap();
|
||||
// Finish building the command buffer by calling `build`.
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
@ -291,7 +291,7 @@ fn main() {
|
||||
)
|
||||
.unwrap()
|
||||
// Draw our buffer
|
||||
.draw(pipeline.clone(), &dynamic_state, buffer, (), (), vec![])
|
||||
.draw(pipeline.clone(), &dynamic_state, buffer, (), ())
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
.unwrap();
|
||||
|
@ -158,7 +158,6 @@ impl AmbientLightingSystem {
|
||||
vec![self.vertex_buffer.clone()],
|
||||
descriptor_set,
|
||||
push_constants,
|
||||
vec![],
|
||||
)
|
||||
.unwrap();
|
||||
builder.build().unwrap()
|
||||
|
@ -172,7 +172,6 @@ impl DirectionalLightingSystem {
|
||||
vec![self.vertex_buffer.clone()],
|
||||
descriptor_set,
|
||||
push_constants,
|
||||
vec![],
|
||||
)
|
||||
.unwrap();
|
||||
builder.build().unwrap()
|
||||
|
@ -187,7 +187,6 @@ impl PointLightingSystem {
|
||||
vec![self.vertex_buffer.clone()],
|
||||
descriptor_set,
|
||||
push_constants,
|
||||
vec![],
|
||||
)
|
||||
.unwrap();
|
||||
builder.build().unwrap()
|
||||
|
@ -101,7 +101,6 @@ impl TriangleDrawSystem {
|
||||
vec![self.vertex_buffer.clone()],
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap();
|
||||
builder.build().unwrap()
|
||||
|
@ -19,7 +19,7 @@ use std::sync::Arc;
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||
use vulkano::descriptor_set::layout::{DescriptorSetDesc, DescriptorSetLayout};
|
||||
use vulkano::descriptor_set::PersistentDescriptorSet;
|
||||
use vulkano::descriptor_set::{DescriptorSet, PersistentDescriptorSet};
|
||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||
use vulkano::instance::{Instance, InstanceExtensions};
|
||||
@ -222,25 +222,22 @@ fn main() {
|
||||
.dispatch(
|
||||
[12, 1, 1],
|
||||
pipeline.clone(),
|
||||
set.clone(),
|
||||
set.clone().offsets([0 * align as u32]),
|
||||
(),
|
||||
vec![0 * align as u32],
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch(
|
||||
[12, 1, 1],
|
||||
pipeline.clone(),
|
||||
set.clone(),
|
||||
set.clone().offsets([1 * align as u32]),
|
||||
(),
|
||||
vec![1 * align as u32],
|
||||
)
|
||||
.unwrap()
|
||||
.dispatch(
|
||||
[12, 1, 1],
|
||||
pipeline.clone(),
|
||||
set.clone(),
|
||||
set.clone().offsets([2 * align as u32]),
|
||||
(),
|
||||
vec![2 * align as u32],
|
||||
)
|
||||
.unwrap();
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
@ -231,7 +231,6 @@ fn main() {
|
||||
pipeline.clone(),
|
||||
set.clone(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.copy_image_to_buffer(image.clone(), buf.clone())
|
||||
|
@ -297,7 +297,6 @@ fn main() {
|
||||
vertex_buffer.clone(),
|
||||
set.clone(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -159,7 +159,7 @@ void main() {
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), ())
|
||||
.unwrap();
|
||||
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
@ -357,7 +357,6 @@ fn main() {
|
||||
compute_pipeline.clone(),
|
||||
cs_desciptor_set.clone(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.begin_render_pass(
|
||||
@ -375,7 +374,6 @@ fn main() {
|
||||
indirect_args.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -340,7 +340,6 @@ fn main() {
|
||||
(triangle_vertex_buffer.clone(), instance_data_buffer.clone()),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -317,7 +317,6 @@ fn main() {
|
||||
vertex_buffer.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -386,7 +386,6 @@ fn main() {
|
||||
vertex_buffer.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -294,7 +294,6 @@ fn main() {
|
||||
vertex_buffer.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -345,14 +345,7 @@ fn main() {
|
||||
// the `occlusion_query_precise` feature to be enabled on the device.
|
||||
.begin_query(query_pool.clone(), 0, QueryControlFlags { precise: false })
|
||||
.unwrap()
|
||||
.draw(
|
||||
pipeline.clone(),
|
||||
&dynamic_state,
|
||||
triangle1.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.draw(pipeline.clone(), &dynamic_state, triangle1.clone(), (), ())
|
||||
.unwrap()
|
||||
// End query 0.
|
||||
.end_query(query_pool.clone(), 0)
|
||||
@ -360,28 +353,14 @@ fn main() {
|
||||
// Begin query 1 for the cyan triangle.
|
||||
.begin_query(query_pool.clone(), 1, QueryControlFlags { precise: false })
|
||||
.unwrap()
|
||||
.draw(
|
||||
pipeline.clone(),
|
||||
&dynamic_state,
|
||||
triangle2.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.draw(pipeline.clone(), &dynamic_state, triangle2.clone(), (), ())
|
||||
.unwrap()
|
||||
.end_query(query_pool.clone(), 1)
|
||||
.unwrap()
|
||||
// Finally, query 2 for the green triangle.
|
||||
.begin_query(query_pool.clone(), 2, QueryControlFlags { precise: false })
|
||||
.unwrap()
|
||||
.draw(
|
||||
pipeline.clone(),
|
||||
&dynamic_state,
|
||||
triangle3.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.draw(pipeline.clone(), &dynamic_state, triangle3.clone(), (), ())
|
||||
.unwrap()
|
||||
.end_query(query_pool.clone(), 2)
|
||||
.unwrap()
|
||||
|
@ -129,13 +129,7 @@ fn main() {
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.dispatch(
|
||||
[1024, 1, 1],
|
||||
pipeline.clone(),
|
||||
set.clone(),
|
||||
push_constants,
|
||||
vec![],
|
||||
)
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), push_constants)
|
||||
.unwrap();
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
||||
|
@ -365,7 +365,6 @@ fn main() {
|
||||
vertex_buffer.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -115,7 +115,7 @@ fn main() {
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), ())
|
||||
.unwrap();
|
||||
let command_buffer = builder.build().unwrap();
|
||||
let future = sync::now(device.clone())
|
||||
|
@ -127,7 +127,7 @@ fn main() {
|
||||
)
|
||||
.unwrap();
|
||||
builder
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), ())
|
||||
.unwrap();
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
||||
|
@ -269,7 +269,6 @@ fn main() {
|
||||
index_buffer.clone(),
|
||||
set.clone(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -372,7 +372,6 @@ fn main() {
|
||||
vertex_buffer.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
|
@ -495,7 +495,6 @@ fn main() {
|
||||
vertex_buffer.clone(),
|
||||
(),
|
||||
(),
|
||||
vec![],
|
||||
)
|
||||
.unwrap()
|
||||
// We leave the render pass by calling `draw_end`. Note that if we had multiple
|
||||
|
@ -37,7 +37,7 @@ use crate::command_buffer::SecondaryCommandBuffer;
|
||||
use crate::command_buffer::StateCacher;
|
||||
use crate::command_buffer::StateCacherOutcome;
|
||||
use crate::command_buffer::SubpassContents;
|
||||
use crate::descriptor_set::layout::{DescriptorBufferDesc, DescriptorDescTy};
|
||||
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||
use crate::descriptor_set::DescriptorSetsCollection;
|
||||
use crate::device::physical::QueueFamily;
|
||||
use crate::device::Device;
|
||||
@ -77,7 +77,6 @@ use crate::sync::PipelineStages;
|
||||
use crate::VulkanObject;
|
||||
use crate::{OomError, SafeDeref};
|
||||
use fnv::FnvHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use std::error;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
@ -1051,28 +1050,27 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
|
||||
/// Perform a single compute operation using a compute pipeline.
|
||||
#[inline]
|
||||
pub fn dispatch<Cp, S, Pc, Do, Doi>(
|
||||
pub fn dispatch<Cp, S, Pc>(
|
||||
&mut self,
|
||||
group_counts: [u32; 3],
|
||||
pipeline: Cp,
|
||||
sets: S,
|
||||
constants: Pc,
|
||||
dynamic_offsets: Do,
|
||||
descriptor_sets: S,
|
||||
push_constants: Pc,
|
||||
) -> Result<&mut Self, DispatchError>
|
||||
where
|
||||
Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||
S: DescriptorSetsCollection,
|
||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
||||
{
|
||||
let descriptor_sets = descriptor_sets.into_vec();
|
||||
|
||||
unsafe {
|
||||
if !self.queue_family().supports_compute() {
|
||||
return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
|
||||
}
|
||||
|
||||
self.ensure_outside_render_pass()?;
|
||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
||||
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||
check_dispatch(pipeline.device(), group_counts)?;
|
||||
|
||||
if let StateCacherOutcome::NeedChange =
|
||||
@ -1081,14 +1079,13 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
self.inner.bind_pipeline_compute(pipeline.clone());
|
||||
}
|
||||
|
||||
push_constants(&mut self.inner, pipeline.layout(), constants);
|
||||
descriptor_sets(
|
||||
set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
|
||||
bind_descriptor_sets(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
PipelineBindPoint::Compute,
|
||||
pipeline.layout(),
|
||||
sets,
|
||||
dynamic_offsets,
|
||||
descriptor_sets,
|
||||
)?;
|
||||
|
||||
self.inner.dispatch(group_counts);
|
||||
@ -1099,13 +1096,12 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// Perform multiple compute operations using a compute pipeline. One dispatch is performed for
|
||||
/// each `vulkano::command_buffer::DispatchIndirectCommand` struct in `indirect_buffer`.
|
||||
#[inline]
|
||||
pub fn dispatch_indirect<Inb, Cp, S, Pc, Do, Doi>(
|
||||
pub fn dispatch_indirect<Inb, Cp, S, Pc>(
|
||||
&mut self,
|
||||
indirect_buffer: Inb,
|
||||
pipeline: Cp,
|
||||
sets: S,
|
||||
constants: Pc,
|
||||
dynamic_offsets: Do,
|
||||
descriptor_sets: S,
|
||||
push_constants: Pc,
|
||||
) -> Result<&mut Self, DispatchIndirectError>
|
||||
where
|
||||
Inb: BufferAccess
|
||||
@ -1115,9 +1111,9 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
+ 'static,
|
||||
Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||
S: DescriptorSetsCollection,
|
||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
||||
{
|
||||
let descriptor_sets = descriptor_sets.into_vec();
|
||||
|
||||
unsafe {
|
||||
if !self.queue_family().supports_compute() {
|
||||
return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
|
||||
@ -1125,8 +1121,8 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
|
||||
self.ensure_outside_render_pass()?;
|
||||
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
||||
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||
|
||||
if let StateCacherOutcome::NeedChange =
|
||||
self.state_cacher.bind_compute_pipeline(&pipeline)
|
||||
@ -1134,14 +1130,13 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
self.inner.bind_pipeline_compute(pipeline.clone());
|
||||
}
|
||||
|
||||
push_constants(&mut self.inner, pipeline.layout(), constants);
|
||||
descriptor_sets(
|
||||
set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
|
||||
bind_descriptor_sets(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
PipelineBindPoint::Compute,
|
||||
pipeline.layout(),
|
||||
sets,
|
||||
dynamic_offsets,
|
||||
descriptor_sets,
|
||||
)?;
|
||||
|
||||
self.inner.dispatch_indirect(indirect_buffer)?;
|
||||
@ -1156,29 +1151,28 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// All data in `vertex_buffer` is used for the draw operation. To use only some data in the
|
||||
/// buffer, wrap it in a `vulkano::buffer::BufferSlice`.
|
||||
#[inline]
|
||||
pub fn draw<V, Gp, S, Pc, Do, Doi>(
|
||||
pub fn draw<V, Gp, S, Pc>(
|
||||
&mut self,
|
||||
pipeline: Gp,
|
||||
dynamic: &DynamicState,
|
||||
vertex_buffer: V,
|
||||
sets: S,
|
||||
constants: Pc,
|
||||
dynamic_offsets: Do,
|
||||
vertex_buffers: V,
|
||||
descriptor_sets: S,
|
||||
push_constants: Pc,
|
||||
) -> Result<&mut Self, DrawError>
|
||||
where
|
||||
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||
S: DescriptorSetsCollection,
|
||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
||||
{
|
||||
let descriptor_sets = descriptor_sets.into_vec();
|
||||
|
||||
unsafe {
|
||||
// TODO: must check that pipeline is compatible with render pass
|
||||
|
||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffer)?;
|
||||
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
|
||||
|
||||
if let StateCacherOutcome::NeedChange =
|
||||
self.state_cacher.bind_graphics_pipeline(&pipeline)
|
||||
@ -1188,17 +1182,16 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
|
||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
||||
|
||||
push_constants(&mut self.inner, pipeline.layout(), constants);
|
||||
set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
|
||||
set_state(&mut self.inner, &dynamic);
|
||||
descriptor_sets(
|
||||
bind_descriptor_sets(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
PipelineBindPoint::Graphics,
|
||||
pipeline.layout(),
|
||||
sets,
|
||||
dynamic_offsets,
|
||||
descriptor_sets,
|
||||
)?;
|
||||
vertex_buffers(
|
||||
bind_vertex_buffers(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
vb_infos.vertex_buffers,
|
||||
@ -1231,15 +1224,14 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// All data in `vertex_buffer` is used for every draw operation. To use only some data in the
|
||||
/// buffer, wrap it in a `vulkano::buffer::BufferSlice`.
|
||||
#[inline]
|
||||
pub fn draw_indirect<V, Gp, S, Pc, Inb, Do, Doi>(
|
||||
pub fn draw_indirect<V, Gp, S, Pc, Inb>(
|
||||
&mut self,
|
||||
pipeline: Gp,
|
||||
dynamic: &DynamicState,
|
||||
vertex_buffer: V,
|
||||
vertex_buffers: V,
|
||||
indirect_buffer: Inb,
|
||||
sets: S,
|
||||
constants: Pc,
|
||||
dynamic_offsets: Do,
|
||||
descriptor_sets: S,
|
||||
push_constants: Pc,
|
||||
) -> Result<&mut Self, DrawIndirectError>
|
||||
where
|
||||
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||
@ -1249,18 +1241,18 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
||||
{
|
||||
let descriptor_sets = descriptor_sets.into_vec();
|
||||
|
||||
unsafe {
|
||||
// TODO: must check that pipeline is compatible with render pass
|
||||
|
||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
||||
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffer)?;
|
||||
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
|
||||
|
||||
let requested = indirect_buffer.len() as u32;
|
||||
let limit = self
|
||||
@ -1288,17 +1280,16 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
|
||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
||||
|
||||
push_constants(&mut self.inner, pipeline.layout(), constants);
|
||||
set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
|
||||
set_state(&mut self.inner, &dynamic);
|
||||
descriptor_sets(
|
||||
bind_descriptor_sets(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
PipelineBindPoint::Graphics,
|
||||
pipeline.layout(),
|
||||
sets,
|
||||
dynamic_offsets,
|
||||
descriptor_sets,
|
||||
)?;
|
||||
vertex_buffers(
|
||||
bind_vertex_buffers(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
vb_infos.vertex_buffers,
|
||||
@ -1324,33 +1315,32 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// All data in `vertex_buffer` and `index_buffer` is used for the draw operation. To use
|
||||
/// only some data in the buffer, wrap it in a `vulkano::buffer::BufferSlice`.
|
||||
#[inline]
|
||||
pub fn draw_indexed<V, Gp, S, Pc, Ib, I, Do, Doi>(
|
||||
pub fn draw_indexed<V, Gp, S, Pc, Ib, I>(
|
||||
&mut self,
|
||||
pipeline: Gp,
|
||||
dynamic: &DynamicState,
|
||||
vertex_buffer: V,
|
||||
vertex_buffers: V,
|
||||
index_buffer: Ib,
|
||||
sets: S,
|
||||
constants: Pc,
|
||||
dynamic_offsets: Do,
|
||||
descriptor_sets: S,
|
||||
push_constants: Pc,
|
||||
) -> Result<&mut Self, DrawIndexedError>
|
||||
where
|
||||
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||
S: DescriptorSetsCollection,
|
||||
Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static,
|
||||
I: Index + 'static,
|
||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
||||
{
|
||||
let descriptor_sets = descriptor_sets.into_vec();
|
||||
|
||||
unsafe {
|
||||
// TODO: must check that pipeline is compatible with render pass
|
||||
|
||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
|
||||
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffer)?;
|
||||
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
|
||||
|
||||
if let StateCacherOutcome::NeedChange =
|
||||
self.state_cacher.bind_graphics_pipeline(&pipeline)
|
||||
@ -1366,17 +1356,16 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
|
||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
||||
|
||||
push_constants(&mut self.inner, pipeline.layout(), constants);
|
||||
set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
|
||||
set_state(&mut self.inner, &dynamic);
|
||||
descriptor_sets(
|
||||
bind_descriptor_sets(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
PipelineBindPoint::Graphics,
|
||||
pipeline.layout(),
|
||||
sets,
|
||||
dynamic_offsets,
|
||||
descriptor_sets,
|
||||
)?;
|
||||
vertex_buffers(
|
||||
bind_vertex_buffers(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
vb_infos.vertex_buffers,
|
||||
@ -1412,16 +1401,15 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// All data in `vertex_buffer` and `index_buffer` is used for every draw operation. To use
|
||||
/// only some data in the buffer, wrap it in a `vulkano::buffer::BufferSlice`.
|
||||
#[inline]
|
||||
pub fn draw_indexed_indirect<V, Gp, S, Pc, Ib, Inb, I, Do, Doi>(
|
||||
pub fn draw_indexed_indirect<V, Gp, S, Pc, Ib, Inb, I>(
|
||||
&mut self,
|
||||
pipeline: Gp,
|
||||
dynamic: &DynamicState,
|
||||
vertex_buffer: V,
|
||||
vertex_buffers: V,
|
||||
index_buffer: Ib,
|
||||
indirect_buffer: Inb,
|
||||
sets: S,
|
||||
constants: Pc,
|
||||
dynamic_offsets: Do,
|
||||
descriptor_sets: S,
|
||||
push_constants: Pc,
|
||||
) -> Result<&mut Self, DrawIndexedIndirectError>
|
||||
where
|
||||
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||
@ -1433,9 +1421,9 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
+ Sync
|
||||
+ 'static,
|
||||
I: Index + 'static,
|
||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
||||
{
|
||||
let descriptor_sets = descriptor_sets.into_vec();
|
||||
|
||||
unsafe {
|
||||
// TODO: must check that pipeline is compatible with render pass
|
||||
|
||||
@ -1443,9 +1431,9 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
|
||||
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
||||
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffer)?;
|
||||
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
|
||||
|
||||
let requested = indirect_buffer.len() as u32;
|
||||
let limit = self
|
||||
@ -1479,17 +1467,16 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
|
||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
||||
|
||||
push_constants(&mut self.inner, pipeline.layout(), constants);
|
||||
set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
|
||||
set_state(&mut self.inner, &dynamic);
|
||||
descriptor_sets(
|
||||
bind_descriptor_sets(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
PipelineBindPoint::Graphics,
|
||||
pipeline.layout(),
|
||||
sets,
|
||||
dynamic_offsets,
|
||||
descriptor_sets,
|
||||
)?;
|
||||
vertex_buffers(
|
||||
bind_vertex_buffers(
|
||||
&mut self.inner,
|
||||
&mut self.state_cacher,
|
||||
vb_infos.vertex_buffers,
|
||||
@ -2097,7 +2084,7 @@ unsafe impl<L, P> DeviceOwned for AutoCommandBufferBuilder<L, P> {
|
||||
}
|
||||
|
||||
// Shortcut function to set the push constants.
|
||||
unsafe fn push_constants<Pc>(
|
||||
unsafe fn set_push_constants<Pc>(
|
||||
destination: &mut SyncCommandBufferBuilder,
|
||||
pipeline_layout: &Arc<PipelineLayout>,
|
||||
push_constants: Pc,
|
||||
@ -2151,7 +2138,7 @@ unsafe fn set_state(destination: &mut SyncCommandBufferBuilder, dynamic: &Dynami
|
||||
}
|
||||
|
||||
// Shortcut function to bind vertex buffers.
|
||||
unsafe fn vertex_buffers(
|
||||
unsafe fn bind_vertex_buffers(
|
||||
destination: &mut SyncCommandBufferBuilder,
|
||||
state_cacher: &mut StateCacher,
|
||||
vertex_buffers: Vec<Box<dyn BufferAccess + Send + Sync>>,
|
||||
@ -2182,76 +2169,17 @@ unsafe fn vertex_buffers(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn descriptor_sets<S, Do, Doi>(
|
||||
unsafe fn bind_descriptor_sets(
|
||||
destination: &mut SyncCommandBufferBuilder,
|
||||
state_cacher: &mut StateCacher,
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
pipeline_layout: &Arc<PipelineLayout>,
|
||||
sets: S,
|
||||
dynamic_offsets: Do,
|
||||
) -> Result<(), SyncCommandBufferBuilderError>
|
||||
where
|
||||
S: DescriptorSetsCollection,
|
||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
||||
{
|
||||
let sets = sets.into_vec();
|
||||
let dynamic_offsets: SmallVec<[u32; 32]> = dynamic_offsets.into_iter().collect();
|
||||
|
||||
// Ensure that the number of dynamic_offsets is correct and that each
|
||||
// dynamic offset is a multiple of the minimum offset alignment specified
|
||||
// by the physical device.
|
||||
let properties = pipeline_layout.device().physical_device().properties();
|
||||
let min_uniform_off_align = properties.min_uniform_buffer_offset_alignment.unwrap() as u32;
|
||||
let min_storage_off_align = properties.min_storage_buffer_offset_alignment.unwrap() as u32;
|
||||
let mut dynamic_offset_index = 0;
|
||||
for set in &sets {
|
||||
for desc_index in 0..set.layout().num_bindings() {
|
||||
let desc = set.layout().descriptor(desc_index).unwrap();
|
||||
if let DescriptorDescTy::Buffer(DescriptorBufferDesc {
|
||||
dynamic: Some(true),
|
||||
storage,
|
||||
}) = desc.ty
|
||||
{
|
||||
// Don't check alignment if there are not enough offsets anyway
|
||||
if dynamic_offsets.len() > dynamic_offset_index {
|
||||
if storage {
|
||||
assert!(
|
||||
dynamic_offsets[dynamic_offset_index] % min_storage_off_align == 0,
|
||||
"Dynamic storage buffer offset must be a multiple of min_storage_buffer_offset_alignment: got {}, expected a multiple of {}",
|
||||
dynamic_offsets[dynamic_offset_index],
|
||||
min_storage_off_align
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
dynamic_offsets[dynamic_offset_index] % min_uniform_off_align == 0,
|
||||
"Dynamic uniform buffer offset must be a multiple of min_uniform_buffer_offset_alignment: got {}, expected a multiple of {}",
|
||||
dynamic_offsets[dynamic_offset_index],
|
||||
min_uniform_off_align
|
||||
);
|
||||
}
|
||||
}
|
||||
dynamic_offset_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
!(dynamic_offsets.len() < dynamic_offset_index),
|
||||
"Too few dynamic offsets: got {}, expected {}",
|
||||
dynamic_offsets.len(),
|
||||
dynamic_offset_index
|
||||
);
|
||||
assert!(
|
||||
!(dynamic_offsets.len() > dynamic_offset_index),
|
||||
"Too many dynamic offsets: got {}, expected {}",
|
||||
dynamic_offsets.len(),
|
||||
dynamic_offset_index
|
||||
);
|
||||
|
||||
descriptor_sets: Vec<DescriptorSetWithOffsets>,
|
||||
) -> Result<(), SyncCommandBufferBuilderError> {
|
||||
let first_binding = {
|
||||
let mut compare = state_cacher.bind_descriptor_sets(pipeline_bind_point);
|
||||
for set in sets.iter() {
|
||||
compare.add(set, &dynamic_offsets);
|
||||
for descriptor_set in descriptor_sets.iter() {
|
||||
compare.add(descriptor_set);
|
||||
}
|
||||
compare.compare()
|
||||
};
|
||||
@ -2262,15 +2190,10 @@ where
|
||||
};
|
||||
|
||||
let mut sets_binder = destination.bind_descriptor_sets();
|
||||
for set in sets.into_iter().skip(first_binding as usize) {
|
||||
for set in descriptor_sets.into_iter().skip(first_binding as usize) {
|
||||
sets_binder.add(set);
|
||||
}
|
||||
sets_binder.submit(
|
||||
pipeline_bind_point,
|
||||
pipeline_layout.clone(),
|
||||
first_binding,
|
||||
dynamic_offsets.into_iter(),
|
||||
)?;
|
||||
sets_binder.submit(pipeline_bind_point, pipeline_layout.clone(), first_binding)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
use crate::buffer::BufferAccess;
|
||||
use crate::command_buffer::DynamicState;
|
||||
use crate::descriptor_set::DescriptorSet;
|
||||
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||
use crate::pipeline::input_assembly::IndexType;
|
||||
use crate::pipeline::ComputePipelineAbstract;
|
||||
use crate::pipeline::GraphicsPipelineAbstract;
|
||||
@ -253,21 +253,20 @@ pub struct StateCacherDescriptorSets<'s> {
|
||||
impl<'s> StateCacherDescriptorSets<'s> {
|
||||
/// Adds a descriptor set to the list to compare.
|
||||
#[inline]
|
||||
pub fn add<S>(&mut self, set: &S, dynamic_offsets: &SmallVec<[u32; 32]>)
|
||||
where
|
||||
S: ?Sized + DescriptorSet,
|
||||
{
|
||||
let raw = set.inner().internal_object();
|
||||
pub fn add(&mut self, descriptor_set: &DescriptorSetWithOffsets) {
|
||||
let (descriptor_set, dynamic_offsets) = descriptor_set.as_ref();
|
||||
let raw = descriptor_set.inner().internal_object();
|
||||
let dynamic_offsets = dynamic_offsets.iter().copied().collect();
|
||||
|
||||
if self.offset < self.state.len() {
|
||||
if (&self.state[self.offset].0, &self.state[self.offset].1) == (&raw, dynamic_offsets) {
|
||||
if let Some(state) = self.state.get_mut(self.offset) {
|
||||
if (&state.0, &state.1) == (&raw, &dynamic_offsets) {
|
||||
self.offset += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
self.state[self.offset] = (raw, dynamic_offsets.clone());
|
||||
*state = (raw, dynamic_offsets);
|
||||
} else {
|
||||
self.state.push((raw, dynamic_offsets.clone()));
|
||||
self.state.push((raw, dynamic_offsets));
|
||||
}
|
||||
|
||||
if self.found_diff.is_none() {
|
||||
|
@ -27,6 +27,7 @@ use crate::command_buffer::SecondaryCommandBuffer;
|
||||
use crate::command_buffer::SubpassContents;
|
||||
use crate::descriptor_set::layout::DescriptorDescTy;
|
||||
use crate::descriptor_set::DescriptorSet;
|
||||
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||
use crate::format::ClearValue;
|
||||
use crate::image::ImageAccess;
|
||||
use crate::image::ImageLayout;
|
||||
@ -393,7 +394,7 @@ impl SyncCommandBufferBuilder {
|
||||
pub fn bind_descriptor_sets(&mut self) -> SyncCommandBufferBuilderBindDescriptorSets {
|
||||
SyncCommandBufferBuilderBindDescriptorSets {
|
||||
builder: self,
|
||||
inner: SmallVec::new(),
|
||||
descriptor_sets: SmallVec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2613,57 +2614,56 @@ impl SyncCommandBufferBuilder {
|
||||
|
||||
pub struct SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
builder: &'b mut SyncCommandBufferBuilder,
|
||||
inner: SmallVec<[Box<dyn DescriptorSet + Send + Sync>; 12]>,
|
||||
descriptor_sets: SmallVec<[DescriptorSetWithOffsets; 12]>,
|
||||
}
|
||||
|
||||
impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
/// Adds a descriptor set to the list.
|
||||
#[inline]
|
||||
pub fn add<S>(&mut self, set: S)
|
||||
pub fn add<S>(&mut self, descriptor_set: S)
|
||||
where
|
||||
S: DescriptorSet + Send + Sync + 'static,
|
||||
S: Into<DescriptorSetWithOffsets>,
|
||||
{
|
||||
self.inner.push(Box::new(set));
|
||||
self.descriptor_sets.push(descriptor_set.into());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn submit<I>(
|
||||
pub unsafe fn submit(
|
||||
self,
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
pipeline_layout: Arc<PipelineLayout>,
|
||||
first_binding: u32,
|
||||
dynamic_offsets: I,
|
||||
) -> Result<(), SyncCommandBufferBuilderError>
|
||||
where
|
||||
I: Iterator<Item = u32> + Send + Sync + 'static,
|
||||
{
|
||||
if self.inner.is_empty() {
|
||||
) -> Result<(), SyncCommandBufferBuilderError> {
|
||||
if self.descriptor_sets.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
struct Cmd<I> {
|
||||
inner: SmallVec<[Box<dyn DescriptorSet + Send + Sync>; 12]>,
|
||||
struct Cmd {
|
||||
descriptor_sets: SmallVec<[DescriptorSetWithOffsets; 12]>,
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
pipeline_layout: Arc<PipelineLayout>,
|
||||
first_binding: u32,
|
||||
dynamic_offsets: Option<I>,
|
||||
}
|
||||
|
||||
impl<I> Command for Cmd<I>
|
||||
where
|
||||
I: Iterator<Item = u32>,
|
||||
{
|
||||
impl Command for Cmd {
|
||||
fn name(&self) -> &'static str {
|
||||
"vkCmdBindDescriptorSets"
|
||||
}
|
||||
|
||||
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder) {
|
||||
let descriptor_sets = self.descriptor_sets.iter().map(|x| x.as_ref().0.inner());
|
||||
let dynamic_offsets = self
|
||||
.descriptor_sets
|
||||
.iter()
|
||||
.map(|x| x.as_ref().1.iter().copied())
|
||||
.flatten();
|
||||
|
||||
out.bind_descriptor_sets(
|
||||
self.pipeline_bind_point,
|
||||
&self.pipeline_layout,
|
||||
self.first_binding,
|
||||
self.inner.iter().map(|s| s.inner()),
|
||||
self.dynamic_offsets.take().unwrap(),
|
||||
descriptor_sets,
|
||||
dynamic_offsets,
|
||||
);
|
||||
}
|
||||
|
||||
@ -2718,11 +2718,16 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
Box::new(Fin(self.inner))
|
||||
|
||||
Box::new(Fin(self
|
||||
.descriptor_sets
|
||||
.into_iter()
|
||||
.map(|x| x.into_tuple().0)
|
||||
.collect()))
|
||||
}
|
||||
|
||||
fn buffer(&self, mut num: usize) -> &dyn BufferAccess {
|
||||
for set in self.inner.iter() {
|
||||
for set in self.descriptor_sets.iter().map(|so| so.as_ref().0) {
|
||||
if let Some(buf) = set.buffer(num) {
|
||||
return buf.0;
|
||||
}
|
||||
@ -2732,7 +2737,12 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
}
|
||||
|
||||
fn buffer_name(&self, mut num: usize) -> Cow<'static, str> {
|
||||
for (set_num, set) in self.inner.iter().enumerate() {
|
||||
for (set_num, set) in self
|
||||
.descriptor_sets
|
||||
.iter()
|
||||
.map(|so| so.as_ref().0)
|
||||
.enumerate()
|
||||
{
|
||||
if let Some(buf) = set.buffer(num) {
|
||||
return format!("Buffer bound to descriptor {} of set {}", buf.1, set_num)
|
||||
.into();
|
||||
@ -2743,7 +2753,7 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
}
|
||||
|
||||
fn image(&self, mut num: usize) -> &dyn ImageAccess {
|
||||
for set in self.inner.iter() {
|
||||
for set in self.descriptor_sets.iter().map(|so| so.as_ref().0) {
|
||||
if let Some(img) = set.image(num) {
|
||||
return img.0.image();
|
||||
}
|
||||
@ -2753,7 +2763,12 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
}
|
||||
|
||||
fn image_name(&self, mut num: usize) -> Cow<'static, str> {
|
||||
for (set_num, set) in self.inner.iter().enumerate() {
|
||||
for (set_num, set) in self
|
||||
.descriptor_sets
|
||||
.iter()
|
||||
.map(|so| so.as_ref().0)
|
||||
.enumerate()
|
||||
{
|
||||
if let Some(img) = set.image(num) {
|
||||
return format!("Image bound to descriptor {} of set {}", img.1, set_num)
|
||||
.into();
|
||||
@ -2766,7 +2781,7 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
|
||||
let resources = {
|
||||
let mut resources = Vec::new();
|
||||
for ds in self.inner.iter() {
|
||||
for ds in self.descriptor_sets.iter().map(|so| so.as_ref().0) {
|
||||
for buf_num in 0..ds.num_buffers() {
|
||||
let desc = ds
|
||||
.layout()
|
||||
@ -2842,11 +2857,10 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
|
||||
self.builder.append_command(
|
||||
Cmd {
|
||||
inner: self.inner,
|
||||
descriptor_sets: self.descriptor_sets,
|
||||
pipeline_bind_point,
|
||||
pipeline_layout,
|
||||
first_binding,
|
||||
dynamic_offsets: Some(dynamic_offsets),
|
||||
},
|
||||
&resources,
|
||||
)?;
|
||||
|
@ -11,17 +11,14 @@ use std::error;
|
||||
use std::fmt;
|
||||
|
||||
use crate::descriptor_set::layout::DescriptorDescSupersetError;
|
||||
use crate::descriptor_set::DescriptorSetsCollection;
|
||||
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||
use crate::pipeline::layout::PipelineLayout;
|
||||
|
||||
/// Checks whether descriptor sets are compatible with the pipeline.
|
||||
pub fn check_descriptor_sets_validity<D>(
|
||||
pub fn check_descriptor_sets_validity(
|
||||
pipeline_layout: &PipelineLayout,
|
||||
descriptor_sets: &D,
|
||||
) -> Result<(), CheckDescriptorSetsValidityError>
|
||||
where
|
||||
D: ?Sized + DescriptorSetsCollection,
|
||||
{
|
||||
descriptor_sets: &[DescriptorSetWithOffsets],
|
||||
) -> Result<(), CheckDescriptorSetsValidityError> {
|
||||
// What's important is not that the pipeline layout and the descriptor sets *match*. Instead
|
||||
// what's important is that the descriptor sets are a superset of the pipeline layout. It's not
|
||||
// a problem if the descriptor sets provide more elements than expected.
|
||||
@ -30,7 +27,9 @@ where
|
||||
for (binding_num, pipeline_desc) in
|
||||
(0..set.num_bindings()).filter_map(|i| set.descriptor(i).map(|d| (i, d)))
|
||||
{
|
||||
let set_desc = descriptor_sets.descriptor(set_num, binding_num);
|
||||
let set_desc = descriptor_sets
|
||||
.get(set_num)
|
||||
.and_then(|so| so.as_ref().0.layout().descriptor(binding_num));
|
||||
|
||||
let set_desc = match set_desc {
|
||||
Some(s) => s,
|
||||
|
@ -7,194 +7,59 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use crate::descriptor_set::layout::DescriptorDesc;
|
||||
use crate::descriptor_set::DescriptorSet;
|
||||
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||
|
||||
/// A collection of descriptor set objects.
|
||||
pub unsafe trait DescriptorSetsCollection {
|
||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>>;
|
||||
|
||||
fn set(&self, num: usize) -> Option<&(dyn DescriptorSet + Send + Sync)>;
|
||||
|
||||
/// Returns the number of descriptors in the set. Includes possibly empty descriptors.
|
||||
///
|
||||
/// Returns `None` if the set is out of range.
|
||||
// TODO: remove ; user should just use `into_vec` instead
|
||||
fn num_bindings_in_set(&self, set: usize) -> Option<usize>;
|
||||
|
||||
/// Returns the descriptor for the given binding of the given set.
|
||||
///
|
||||
/// Returns `None` if out of range.
|
||||
// TODO: remove ; user should just use `into_vec` instead
|
||||
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc>;
|
||||
fn into_vec(self) -> Vec<DescriptorSetWithOffsets>;
|
||||
}
|
||||
|
||||
unsafe impl DescriptorSetsCollection for () {
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>> {
|
||||
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&self, num: usize) -> Option<&(dyn DescriptorSet + Send + Sync)> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_bindings_in_set(&self, _: usize) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor(&self, _: usize, _: usize) -> Option<DescriptorDesc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> DescriptorSetsCollection for T
|
||||
where
|
||||
T: DescriptorSet + Send + Sync + 'static,
|
||||
T: Into<DescriptorSetWithOffsets>,
|
||||
{
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>> {
|
||||
vec![Box::new(self) as Box<_>]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&self, num: usize) -> Option<&(dyn DescriptorSet + Send + Sync)> {
|
||||
match num {
|
||||
0 => Some(self),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_bindings_in_set(&self, set: usize) -> Option<usize> {
|
||||
match set {
|
||||
0 => Some(self.layout().num_bindings()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
|
||||
match set {
|
||||
0 => self.layout().descriptor(binding),
|
||||
_ => None,
|
||||
}
|
||||
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||
vec![self.into()]
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> DescriptorSetsCollection for Vec<T>
|
||||
where
|
||||
T: DescriptorSet + Send + Sync + 'static,
|
||||
T: Into<DescriptorSetWithOffsets>,
|
||||
{
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>> {
|
||||
let mut v = Vec::new();
|
||||
for o in self {
|
||||
v.push(Box::new(o) as Box<_>);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&self, num: usize) -> Option<&(dyn DescriptorSet + Send + Sync)> {
|
||||
self.get(num).map(|x| x as _)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_bindings_in_set(&self, set: usize) -> Option<usize> {
|
||||
self.get(set).map(|x| x.layout().num_bindings())
|
||||
}
|
||||
#[inline]
|
||||
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
|
||||
self.get(set).and_then(|x| x.layout().descriptor(binding))
|
||||
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||
self.into_iter().map(|x| x.into()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_collection {
|
||||
($first:ident $(, $others:ident)+) => (
|
||||
unsafe impl<$first$(, $others)+> DescriptorSetsCollection for ($first, $($others),+)
|
||||
where $first: DescriptorSet + Send + Sync + 'static
|
||||
$(, $others: DescriptorSet + Send + Sync + 'static)*
|
||||
where $first: Into<DescriptorSetWithOffsets>
|
||||
$(, $others: Into<DescriptorSetWithOffsets>)*
|
||||
{
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>> {
|
||||
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
let ($first, $($others,)*) = self;
|
||||
|
||||
let mut list = Vec::new();
|
||||
list.push(Box::new($first) as Box<_>);
|
||||
list.push($first.into());
|
||||
$(
|
||||
list.push(Box::new($others) as Box<_>);
|
||||
list.push($others.into());
|
||||
)+
|
||||
list
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&self, mut num: usize) -> Option<&(dyn DescriptorSet + Send + Sync)> {
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(unused_mut)] // For the `num` parameter.
|
||||
|
||||
if num == 0 {
|
||||
return Some(&self.0);
|
||||
}
|
||||
|
||||
let &(_, $(ref $others,)*) = self;
|
||||
|
||||
$(
|
||||
num -= 1;
|
||||
if num == 0 {
|
||||
return Some($others);
|
||||
}
|
||||
)*
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_bindings_in_set(&self, mut set: usize) -> Option<usize> {
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(unused_mut)] // For the `set` parameter.
|
||||
|
||||
if set == 0 {
|
||||
return Some(self.0.layout().num_bindings());
|
||||
}
|
||||
|
||||
let &(_, $(ref $others,)*) = self;
|
||||
|
||||
$(
|
||||
set -= 1;
|
||||
if set == 0 {
|
||||
return Some($others.layout().num_bindings());
|
||||
}
|
||||
)*
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor(&self, mut set: usize, binding: usize) -> Option<DescriptorDesc> {
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(unused_mut)] // For the `set` parameter.
|
||||
|
||||
if set == 0 {
|
||||
return self.0.layout().descriptor(binding);
|
||||
}
|
||||
|
||||
let &(_, $(ref $others,)*) = self;
|
||||
|
||||
$(
|
||||
set -= 1;
|
||||
if set == 0 {
|
||||
return $others.layout().descriptor(binding);
|
||||
}
|
||||
)*
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl_collection!($($others),+);
|
||||
|
@ -81,10 +81,12 @@ pub use self::persistent::PersistentDescriptorSetBuildError;
|
||||
pub use self::persistent::PersistentDescriptorSetError;
|
||||
use self::sys::UnsafeDescriptorSet;
|
||||
use crate::buffer::BufferAccess;
|
||||
use crate::descriptor_set::layout::{DescriptorBufferDesc, DescriptorDescTy};
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::image::view::ImageViewAbstract;
|
||||
use crate::SafeDeref;
|
||||
use crate::VulkanObject;
|
||||
use smallvec::SmallVec;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::sync::Arc;
|
||||
@ -106,6 +108,15 @@ pub unsafe trait DescriptorSet: DeviceOwned {
|
||||
/// Returns the layout of this descriptor set.
|
||||
fn layout(&self) -> &Arc<DescriptorSetLayout>;
|
||||
|
||||
/// Creates a [`DescriptorSetWithOffsets`] with the given dynamic offsets.
|
||||
fn offsets<I>(self, dynamic_offsets: I) -> DescriptorSetWithOffsets
|
||||
where
|
||||
Self: Sized + Send + Sync + 'static,
|
||||
I: IntoIterator<Item = u32>,
|
||||
{
|
||||
DescriptorSetWithOffsets::new(self, dynamic_offsets)
|
||||
}
|
||||
|
||||
/// Returns the number of buffers within this descriptor set.
|
||||
fn num_buffers(&self) -> usize;
|
||||
|
||||
@ -178,3 +189,99 @@ impl Hash for dyn DescriptorSet + Send + Sync {
|
||||
self.device().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DescriptorSetWithOffsets {
|
||||
descriptor_set: Box<dyn DescriptorSet + Send + Sync>,
|
||||
dynamic_offsets: SmallVec<[u32; 4]>,
|
||||
}
|
||||
|
||||
impl DescriptorSetWithOffsets {
|
||||
#[inline]
|
||||
pub fn new<S, O>(descriptor_set: S, dynamic_offsets: O) -> Self
|
||||
where
|
||||
S: DescriptorSet + Send + Sync + 'static,
|
||||
O: IntoIterator<Item = u32>,
|
||||
{
|
||||
let dynamic_offsets: SmallVec<_> = dynamic_offsets.into_iter().collect();
|
||||
let layout = descriptor_set.layout();
|
||||
let properties = layout.device().physical_device().properties();
|
||||
let min_uniform_off_align = properties.min_uniform_buffer_offset_alignment.unwrap() as u32;
|
||||
let min_storage_off_align = properties.min_storage_buffer_offset_alignment.unwrap() as u32;
|
||||
let mut dynamic_offset_index = 0;
|
||||
|
||||
// Ensure that the number of dynamic_offsets is correct and that each
|
||||
// dynamic offset is a multiple of the minimum offset alignment specified
|
||||
// by the physical device.
|
||||
for desc in layout.desc().bindings() {
|
||||
let desc = desc.as_ref().unwrap();
|
||||
if let DescriptorDescTy::Buffer(DescriptorBufferDesc {
|
||||
dynamic: Some(true),
|
||||
storage,
|
||||
}) = desc.ty
|
||||
{
|
||||
// Don't check alignment if there are not enough offsets anyway
|
||||
if dynamic_offsets.len() > dynamic_offset_index {
|
||||
if storage {
|
||||
assert!(
|
||||
dynamic_offsets[dynamic_offset_index] % min_storage_off_align == 0,
|
||||
"Dynamic storage buffer offset must be a multiple of min_storage_buffer_offset_alignment: got {}, expected a multiple of {}",
|
||||
dynamic_offsets[dynamic_offset_index],
|
||||
min_storage_off_align
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
dynamic_offsets[dynamic_offset_index] % min_uniform_off_align == 0,
|
||||
"Dynamic uniform buffer offset must be a multiple of min_uniform_buffer_offset_alignment: got {}, expected a multiple of {}",
|
||||
dynamic_offsets[dynamic_offset_index],
|
||||
min_uniform_off_align
|
||||
);
|
||||
}
|
||||
}
|
||||
dynamic_offset_index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
!(dynamic_offsets.len() < dynamic_offset_index),
|
||||
"Too few dynamic offsets: got {}, expected {}",
|
||||
dynamic_offsets.len(),
|
||||
dynamic_offset_index
|
||||
);
|
||||
assert!(
|
||||
!(dynamic_offsets.len() > dynamic_offset_index),
|
||||
"Too many dynamic offsets: got {}, expected {}",
|
||||
dynamic_offsets.len(),
|
||||
dynamic_offset_index
|
||||
);
|
||||
|
||||
DescriptorSetWithOffsets {
|
||||
descriptor_set: Box::new(descriptor_set),
|
||||
dynamic_offsets,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_ref(&self) -> (&dyn DescriptorSet, &[u32]) {
|
||||
(&self.descriptor_set, &self.dynamic_offsets)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_tuple(
|
||||
self,
|
||||
) -> (
|
||||
Box<dyn DescriptorSet + Send + Sync>,
|
||||
impl ExactSizeIterator<Item = u32>,
|
||||
) {
|
||||
(self.descriptor_set, self.dynamic_offsets.into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<S> for DescriptorSetWithOffsets
|
||||
where
|
||||
S: DescriptorSet + Send + Sync + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn from(descriptor_set: S) -> Self {
|
||||
Self::new(descriptor_set, std::iter::empty())
|
||||
}
|
||||
}
|
||||
|
@ -507,8 +507,7 @@ mod tests {
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.dispatch([1, 1, 1], pipeline.clone(), set, (), vec![])
|
||||
.unwrap();
|
||||
cbb.dispatch([1, 1, 1], pipeline.clone(), set, ()).unwrap();
|
||||
let cb = cbb.build().unwrap();
|
||||
|
||||
let future = now(device.clone())
|
||||
|
Loading…
Reference in New Issue
Block a user