mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-18 01:52:35 +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
|
// `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
|
// 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.
|
// 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();
|
.unwrap();
|
||||||
// Finish building the command buffer by calling `build`.
|
// Finish building the command buffer by calling `build`.
|
||||||
let command_buffer = builder.build().unwrap();
|
let command_buffer = builder.build().unwrap();
|
||||||
|
@ -291,7 +291,7 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
// Draw our buffer
|
// Draw our buffer
|
||||||
.draw(pipeline.clone(), &dynamic_state, buffer, (), (), vec![])
|
.draw(pipeline.clone(), &dynamic_state, buffer, (), ())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -158,7 +158,6 @@ impl AmbientLightingSystem {
|
|||||||
vec![self.vertex_buffer.clone()],
|
vec![self.vertex_buffer.clone()],
|
||||||
descriptor_set,
|
descriptor_set,
|
||||||
push_constants,
|
push_constants,
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
builder.build().unwrap()
|
builder.build().unwrap()
|
||||||
|
@ -172,7 +172,6 @@ impl DirectionalLightingSystem {
|
|||||||
vec![self.vertex_buffer.clone()],
|
vec![self.vertex_buffer.clone()],
|
||||||
descriptor_set,
|
descriptor_set,
|
||||||
push_constants,
|
push_constants,
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
builder.build().unwrap()
|
builder.build().unwrap()
|
||||||
|
@ -187,7 +187,6 @@ impl PointLightingSystem {
|
|||||||
vec![self.vertex_buffer.clone()],
|
vec![self.vertex_buffer.clone()],
|
||||||
descriptor_set,
|
descriptor_set,
|
||||||
push_constants,
|
push_constants,
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
builder.build().unwrap()
|
builder.build().unwrap()
|
||||||
|
@ -101,7 +101,6 @@ impl TriangleDrawSystem {
|
|||||||
vec![self.vertex_buffer.clone()],
|
vec![self.vertex_buffer.clone()],
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
builder.build().unwrap()
|
builder.build().unwrap()
|
||||||
|
@ -19,7 +19,7 @@ use std::sync::Arc;
|
|||||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
||||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage};
|
||||||
use vulkano::descriptor_set::layout::{DescriptorSetDesc, DescriptorSetLayout};
|
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::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||||
use vulkano::device::{Device, DeviceExtensions, Features};
|
use vulkano::device::{Device, DeviceExtensions, Features};
|
||||||
use vulkano::instance::{Instance, InstanceExtensions};
|
use vulkano::instance::{Instance, InstanceExtensions};
|
||||||
@ -222,25 +222,22 @@ fn main() {
|
|||||||
.dispatch(
|
.dispatch(
|
||||||
[12, 1, 1],
|
[12, 1, 1],
|
||||||
pipeline.clone(),
|
pipeline.clone(),
|
||||||
set.clone(),
|
set.clone().offsets([0 * align as u32]),
|
||||||
(),
|
(),
|
||||||
vec![0 * align as u32],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dispatch(
|
.dispatch(
|
||||||
[12, 1, 1],
|
[12, 1, 1],
|
||||||
pipeline.clone(),
|
pipeline.clone(),
|
||||||
set.clone(),
|
set.clone().offsets([1 * align as u32]),
|
||||||
(),
|
(),
|
||||||
vec![1 * align as u32],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.dispatch(
|
.dispatch(
|
||||||
[12, 1, 1],
|
[12, 1, 1],
|
||||||
pipeline.clone(),
|
pipeline.clone(),
|
||||||
set.clone(),
|
set.clone().offsets([2 * align as u32]),
|
||||||
(),
|
(),
|
||||||
vec![2 * align as u32],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let command_buffer = builder.build().unwrap();
|
let command_buffer = builder.build().unwrap();
|
||||||
|
@ -231,7 +231,6 @@ fn main() {
|
|||||||
pipeline.clone(),
|
pipeline.clone(),
|
||||||
set.clone(),
|
set.clone(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.copy_image_to_buffer(image.clone(), buf.clone())
|
.copy_image_to_buffer(image.clone(), buf.clone())
|
||||||
|
@ -297,7 +297,6 @@ fn main() {
|
|||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
set.clone(),
|
set.clone(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -159,7 +159,7 @@ void main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), ())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let command_buffer = builder.build().unwrap();
|
let command_buffer = builder.build().unwrap();
|
||||||
|
@ -357,7 +357,6 @@ fn main() {
|
|||||||
compute_pipeline.clone(),
|
compute_pipeline.clone(),
|
||||||
cs_desciptor_set.clone(),
|
cs_desciptor_set.clone(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.begin_render_pass(
|
.begin_render_pass(
|
||||||
@ -375,7 +374,6 @@ fn main() {
|
|||||||
indirect_args.clone(),
|
indirect_args.clone(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -340,7 +340,6 @@ fn main() {
|
|||||||
(triangle_vertex_buffer.clone(), instance_data_buffer.clone()),
|
(triangle_vertex_buffer.clone(), instance_data_buffer.clone()),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -317,7 +317,6 @@ fn main() {
|
|||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -386,7 +386,6 @@ fn main() {
|
|||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -294,7 +294,6 @@ fn main() {
|
|||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -345,14 +345,7 @@ fn main() {
|
|||||||
// the `occlusion_query_precise` feature to be enabled on the device.
|
// the `occlusion_query_precise` feature to be enabled on the device.
|
||||||
.begin_query(query_pool.clone(), 0, QueryControlFlags { precise: false })
|
.begin_query(query_pool.clone(), 0, QueryControlFlags { precise: false })
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.draw(
|
.draw(pipeline.clone(), &dynamic_state, triangle1.clone(), (), ())
|
||||||
pipeline.clone(),
|
|
||||||
&dynamic_state,
|
|
||||||
triangle1.clone(),
|
|
||||||
(),
|
|
||||||
(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
// End query 0.
|
// End query 0.
|
||||||
.end_query(query_pool.clone(), 0)
|
.end_query(query_pool.clone(), 0)
|
||||||
@ -360,28 +353,14 @@ fn main() {
|
|||||||
// Begin query 1 for the cyan triangle.
|
// Begin query 1 for the cyan triangle.
|
||||||
.begin_query(query_pool.clone(), 1, QueryControlFlags { precise: false })
|
.begin_query(query_pool.clone(), 1, QueryControlFlags { precise: false })
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.draw(
|
.draw(pipeline.clone(), &dynamic_state, triangle2.clone(), (), ())
|
||||||
pipeline.clone(),
|
|
||||||
&dynamic_state,
|
|
||||||
triangle2.clone(),
|
|
||||||
(),
|
|
||||||
(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_query(query_pool.clone(), 1)
|
.end_query(query_pool.clone(), 1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
// Finally, query 2 for the green triangle.
|
// Finally, query 2 for the green triangle.
|
||||||
.begin_query(query_pool.clone(), 2, QueryControlFlags { precise: false })
|
.begin_query(query_pool.clone(), 2, QueryControlFlags { precise: false })
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.draw(
|
.draw(pipeline.clone(), &dynamic_state, triangle3.clone(), (), ())
|
||||||
pipeline.clone(),
|
|
||||||
&dynamic_state,
|
|
||||||
triangle3.clone(),
|
|
||||||
(),
|
|
||||||
(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_query(query_pool.clone(), 2)
|
.end_query(query_pool.clone(), 2)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -129,13 +129,7 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
builder
|
builder
|
||||||
.dispatch(
|
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), push_constants)
|
||||||
[1024, 1, 1],
|
|
||||||
pipeline.clone(),
|
|
||||||
set.clone(),
|
|
||||||
push_constants,
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let command_buffer = builder.build().unwrap();
|
let command_buffer = builder.build().unwrap();
|
||||||
|
|
||||||
|
@ -365,7 +365,6 @@ fn main() {
|
|||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -115,7 +115,7 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
builder
|
builder
|
||||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), ())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let command_buffer = builder.build().unwrap();
|
let command_buffer = builder.build().unwrap();
|
||||||
let future = sync::now(device.clone())
|
let future = sync::now(device.clone())
|
||||||
|
@ -127,7 +127,7 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
builder
|
builder
|
||||||
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), (), vec![])
|
.dispatch([1024, 1, 1], pipeline.clone(), set.clone(), ())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let command_buffer = builder.build().unwrap();
|
let command_buffer = builder.build().unwrap();
|
||||||
|
|
||||||
|
@ -269,7 +269,6 @@ fn main() {
|
|||||||
index_buffer.clone(),
|
index_buffer.clone(),
|
||||||
set.clone(),
|
set.clone(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -372,7 +372,6 @@ fn main() {
|
|||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
@ -495,7 +495,6 @@ fn main() {
|
|||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
// We leave the render pass by calling `draw_end`. Note that if we had multiple
|
// 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::StateCacher;
|
||||||
use crate::command_buffer::StateCacherOutcome;
|
use crate::command_buffer::StateCacherOutcome;
|
||||||
use crate::command_buffer::SubpassContents;
|
use crate::command_buffer::SubpassContents;
|
||||||
use crate::descriptor_set::layout::{DescriptorBufferDesc, DescriptorDescTy};
|
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||||
use crate::descriptor_set::DescriptorSetsCollection;
|
use crate::descriptor_set::DescriptorSetsCollection;
|
||||||
use crate::device::physical::QueueFamily;
|
use crate::device::physical::QueueFamily;
|
||||||
use crate::device::Device;
|
use crate::device::Device;
|
||||||
@ -77,7 +77,6 @@ use crate::sync::PipelineStages;
|
|||||||
use crate::VulkanObject;
|
use crate::VulkanObject;
|
||||||
use crate::{OomError, SafeDeref};
|
use crate::{OomError, SafeDeref};
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use smallvec::SmallVec;
|
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -1051,28 +1050,27 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
|
|
||||||
/// Perform a single compute operation using a compute pipeline.
|
/// Perform a single compute operation using a compute pipeline.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dispatch<Cp, S, Pc, Do, Doi>(
|
pub fn dispatch<Cp, S, Pc>(
|
||||||
&mut self,
|
&mut self,
|
||||||
group_counts: [u32; 3],
|
group_counts: [u32; 3],
|
||||||
pipeline: Cp,
|
pipeline: Cp,
|
||||||
sets: S,
|
descriptor_sets: S,
|
||||||
constants: Pc,
|
push_constants: Pc,
|
||||||
dynamic_offsets: Do,
|
|
||||||
) -> Result<&mut Self, DispatchError>
|
) -> Result<&mut Self, DispatchError>
|
||||||
where
|
where
|
||||||
Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
S: DescriptorSetsCollection,
|
S: DescriptorSetsCollection,
|
||||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
|
||||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
|
let descriptor_sets = descriptor_sets.into_vec();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if !self.queue_family().supports_compute() {
|
if !self.queue_family().supports_compute() {
|
||||||
return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
|
return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ensure_outside_render_pass()?;
|
self.ensure_outside_render_pass()?;
|
||||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||||
check_dispatch(pipeline.device(), group_counts)?;
|
check_dispatch(pipeline.device(), group_counts)?;
|
||||||
|
|
||||||
if let StateCacherOutcome::NeedChange =
|
if let StateCacherOutcome::NeedChange =
|
||||||
@ -1081,14 +1079,13 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
self.inner.bind_pipeline_compute(pipeline.clone());
|
self.inner.bind_pipeline_compute(pipeline.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
push_constants(&mut self.inner, pipeline.layout(), constants);
|
set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
|
||||||
descriptor_sets(
|
bind_descriptor_sets(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
PipelineBindPoint::Compute,
|
PipelineBindPoint::Compute,
|
||||||
pipeline.layout(),
|
pipeline.layout(),
|
||||||
sets,
|
descriptor_sets,
|
||||||
dynamic_offsets,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.inner.dispatch(group_counts);
|
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
|
/// Perform multiple compute operations using a compute pipeline. One dispatch is performed for
|
||||||
/// each `vulkano::command_buffer::DispatchIndirectCommand` struct in `indirect_buffer`.
|
/// each `vulkano::command_buffer::DispatchIndirectCommand` struct in `indirect_buffer`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dispatch_indirect<Inb, Cp, S, Pc, Do, Doi>(
|
pub fn dispatch_indirect<Inb, Cp, S, Pc>(
|
||||||
&mut self,
|
&mut self,
|
||||||
indirect_buffer: Inb,
|
indirect_buffer: Inb,
|
||||||
pipeline: Cp,
|
pipeline: Cp,
|
||||||
sets: S,
|
descriptor_sets: S,
|
||||||
constants: Pc,
|
push_constants: Pc,
|
||||||
dynamic_offsets: Do,
|
|
||||||
) -> Result<&mut Self, DispatchIndirectError>
|
) -> Result<&mut Self, DispatchIndirectError>
|
||||||
where
|
where
|
||||||
Inb: BufferAccess
|
Inb: BufferAccess
|
||||||
@ -1115,9 +1111,9 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
+ 'static,
|
+ 'static,
|
||||||
Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
S: DescriptorSetsCollection,
|
S: DescriptorSetsCollection,
|
||||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
|
||||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
|
let descriptor_sets = descriptor_sets.into_vec();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if !self.queue_family().supports_compute() {
|
if !self.queue_family().supports_compute() {
|
||||||
return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
|
return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
|
||||||
@ -1125,8 +1121,8 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
|
|
||||||
self.ensure_outside_render_pass()?;
|
self.ensure_outside_render_pass()?;
|
||||||
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
||||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||||
|
|
||||||
if let StateCacherOutcome::NeedChange =
|
if let StateCacherOutcome::NeedChange =
|
||||||
self.state_cacher.bind_compute_pipeline(&pipeline)
|
self.state_cacher.bind_compute_pipeline(&pipeline)
|
||||||
@ -1134,14 +1130,13 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
self.inner.bind_pipeline_compute(pipeline.clone());
|
self.inner.bind_pipeline_compute(pipeline.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
push_constants(&mut self.inner, pipeline.layout(), constants);
|
set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
|
||||||
descriptor_sets(
|
bind_descriptor_sets(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
PipelineBindPoint::Compute,
|
PipelineBindPoint::Compute,
|
||||||
pipeline.layout(),
|
pipeline.layout(),
|
||||||
sets,
|
descriptor_sets,
|
||||||
dynamic_offsets,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.inner.dispatch_indirect(indirect_buffer)?;
|
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
|
/// 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`.
|
/// buffer, wrap it in a `vulkano::buffer::BufferSlice`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn draw<V, Gp, S, Pc, Do, Doi>(
|
pub fn draw<V, Gp, S, Pc>(
|
||||||
&mut self,
|
&mut self,
|
||||||
pipeline: Gp,
|
pipeline: Gp,
|
||||||
dynamic: &DynamicState,
|
dynamic: &DynamicState,
|
||||||
vertex_buffer: V,
|
vertex_buffers: V,
|
||||||
sets: S,
|
descriptor_sets: S,
|
||||||
constants: Pc,
|
push_constants: Pc,
|
||||||
dynamic_offsets: Do,
|
|
||||||
) -> Result<&mut Self, DrawError>
|
) -> Result<&mut Self, DrawError>
|
||||||
where
|
where
|
||||||
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
S: DescriptorSetsCollection,
|
S: DescriptorSetsCollection,
|
||||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
|
||||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
|
let descriptor_sets = descriptor_sets.into_vec();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// TODO: must check that pipeline is compatible with render pass
|
// TODO: must check that pipeline is compatible with render pass
|
||||||
|
|
||||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||||
check_dynamic_state_validity(&pipeline, dynamic)?;
|
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffer)?;
|
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
|
||||||
|
|
||||||
if let StateCacherOutcome::NeedChange =
|
if let StateCacherOutcome::NeedChange =
|
||||||
self.state_cacher.bind_graphics_pipeline(&pipeline)
|
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);
|
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);
|
set_state(&mut self.inner, &dynamic);
|
||||||
descriptor_sets(
|
bind_descriptor_sets(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
PipelineBindPoint::Graphics,
|
PipelineBindPoint::Graphics,
|
||||||
pipeline.layout(),
|
pipeline.layout(),
|
||||||
sets,
|
descriptor_sets,
|
||||||
dynamic_offsets,
|
|
||||||
)?;
|
)?;
|
||||||
vertex_buffers(
|
bind_vertex_buffers(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
vb_infos.vertex_buffers,
|
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
|
/// 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`.
|
/// buffer, wrap it in a `vulkano::buffer::BufferSlice`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn draw_indirect<V, Gp, S, Pc, Inb, Do, Doi>(
|
pub fn draw_indirect<V, Gp, S, Pc, Inb>(
|
||||||
&mut self,
|
&mut self,
|
||||||
pipeline: Gp,
|
pipeline: Gp,
|
||||||
dynamic: &DynamicState,
|
dynamic: &DynamicState,
|
||||||
vertex_buffer: V,
|
vertex_buffers: V,
|
||||||
indirect_buffer: Inb,
|
indirect_buffer: Inb,
|
||||||
sets: S,
|
descriptor_sets: S,
|
||||||
constants: Pc,
|
push_constants: Pc,
|
||||||
dynamic_offsets: Do,
|
|
||||||
) -> Result<&mut Self, DrawIndirectError>
|
) -> Result<&mut Self, DrawIndirectError>
|
||||||
where
|
where
|
||||||
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
@ -1249,18 +1241,18 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
Do: IntoIterator<Item = u32, IntoIter = Doi>,
|
|
||||||
Doi: Iterator<Item = u32> + Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
|
let descriptor_sets = descriptor_sets.into_vec();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// TODO: must check that pipeline is compatible with render pass
|
// TODO: must check that pipeline is compatible with render pass
|
||||||
|
|
||||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||||
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
||||||
check_dynamic_state_validity(&pipeline, dynamic)?;
|
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffer)?;
|
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
|
||||||
|
|
||||||
let requested = indirect_buffer.len() as u32;
|
let requested = indirect_buffer.len() as u32;
|
||||||
let limit = self
|
let limit = self
|
||||||
@ -1288,17 +1280,16 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
|
|
||||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
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);
|
set_state(&mut self.inner, &dynamic);
|
||||||
descriptor_sets(
|
bind_descriptor_sets(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
PipelineBindPoint::Graphics,
|
PipelineBindPoint::Graphics,
|
||||||
pipeline.layout(),
|
pipeline.layout(),
|
||||||
sets,
|
descriptor_sets,
|
||||||
dynamic_offsets,
|
|
||||||
)?;
|
)?;
|
||||||
vertex_buffers(
|
bind_vertex_buffers(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
vb_infos.vertex_buffers,
|
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
|
/// 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`.
|
/// only some data in the buffer, wrap it in a `vulkano::buffer::BufferSlice`.
|
||||||
#[inline]
|
#[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,
|
&mut self,
|
||||||
pipeline: Gp,
|
pipeline: Gp,
|
||||||
dynamic: &DynamicState,
|
dynamic: &DynamicState,
|
||||||
vertex_buffer: V,
|
vertex_buffers: V,
|
||||||
index_buffer: Ib,
|
index_buffer: Ib,
|
||||||
sets: S,
|
descriptor_sets: S,
|
||||||
constants: Pc,
|
push_constants: Pc,
|
||||||
dynamic_offsets: Do,
|
|
||||||
) -> Result<&mut Self, DrawIndexedError>
|
) -> Result<&mut Self, DrawIndexedError>
|
||||||
where
|
where
|
||||||
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
S: DescriptorSetsCollection,
|
S: DescriptorSetsCollection,
|
||||||
Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static,
|
Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static,
|
||||||
I: Index + '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 {
|
unsafe {
|
||||||
// TODO: must check that pipeline is compatible with render pass
|
// TODO: must check that pipeline is compatible with render pass
|
||||||
|
|
||||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||||
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
|
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
|
||||||
check_dynamic_state_validity(&pipeline, dynamic)?;
|
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffer)?;
|
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
|
||||||
|
|
||||||
if let StateCacherOutcome::NeedChange =
|
if let StateCacherOutcome::NeedChange =
|
||||||
self.state_cacher.bind_graphics_pipeline(&pipeline)
|
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);
|
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);
|
set_state(&mut self.inner, &dynamic);
|
||||||
descriptor_sets(
|
bind_descriptor_sets(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
PipelineBindPoint::Graphics,
|
PipelineBindPoint::Graphics,
|
||||||
pipeline.layout(),
|
pipeline.layout(),
|
||||||
sets,
|
descriptor_sets,
|
||||||
dynamic_offsets,
|
|
||||||
)?;
|
)?;
|
||||||
vertex_buffers(
|
bind_vertex_buffers(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
vb_infos.vertex_buffers,
|
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
|
/// 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`.
|
/// only some data in the buffer, wrap it in a `vulkano::buffer::BufferSlice`.
|
||||||
#[inline]
|
#[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,
|
&mut self,
|
||||||
pipeline: Gp,
|
pipeline: Gp,
|
||||||
dynamic: &DynamicState,
|
dynamic: &DynamicState,
|
||||||
vertex_buffer: V,
|
vertex_buffers: V,
|
||||||
index_buffer: Ib,
|
index_buffer: Ib,
|
||||||
indirect_buffer: Inb,
|
indirect_buffer: Inb,
|
||||||
sets: S,
|
descriptor_sets: S,
|
||||||
constants: Pc,
|
push_constants: Pc,
|
||||||
dynamic_offsets: Do,
|
|
||||||
) -> Result<&mut Self, DrawIndexedIndirectError>
|
) -> Result<&mut Self, DrawIndexedIndirectError>
|
||||||
where
|
where
|
||||||
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
@ -1433,9 +1421,9 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
I: Index + '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 {
|
unsafe {
|
||||||
// TODO: must check that pipeline is compatible with render pass
|
// 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)?;
|
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
|
||||||
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
check_indirect_buffer(self.device(), &indirect_buffer)?;
|
||||||
check_dynamic_state_validity(&pipeline, dynamic)?;
|
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||||
check_push_constants_validity(pipeline.layout(), &constants)?;
|
check_push_constants_validity(pipeline.layout(), &push_constants)?;
|
||||||
check_descriptor_sets_validity(pipeline.layout(), &sets)?;
|
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
|
||||||
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffer)?;
|
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
|
||||||
|
|
||||||
let requested = indirect_buffer.len() as u32;
|
let requested = indirect_buffer.len() as u32;
|
||||||
let limit = self
|
let limit = self
|
||||||
@ -1479,17 +1467,16 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
|||||||
|
|
||||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
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);
|
set_state(&mut self.inner, &dynamic);
|
||||||
descriptor_sets(
|
bind_descriptor_sets(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
PipelineBindPoint::Graphics,
|
PipelineBindPoint::Graphics,
|
||||||
pipeline.layout(),
|
pipeline.layout(),
|
||||||
sets,
|
descriptor_sets,
|
||||||
dynamic_offsets,
|
|
||||||
)?;
|
)?;
|
||||||
vertex_buffers(
|
bind_vertex_buffers(
|
||||||
&mut self.inner,
|
&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
vb_infos.vertex_buffers,
|
vb_infos.vertex_buffers,
|
||||||
@ -2097,7 +2084,7 @@ unsafe impl<L, P> DeviceOwned for AutoCommandBufferBuilder<L, P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shortcut function to set the push constants.
|
// Shortcut function to set the push constants.
|
||||||
unsafe fn push_constants<Pc>(
|
unsafe fn set_push_constants<Pc>(
|
||||||
destination: &mut SyncCommandBufferBuilder,
|
destination: &mut SyncCommandBufferBuilder,
|
||||||
pipeline_layout: &Arc<PipelineLayout>,
|
pipeline_layout: &Arc<PipelineLayout>,
|
||||||
push_constants: Pc,
|
push_constants: Pc,
|
||||||
@ -2151,7 +2138,7 @@ unsafe fn set_state(destination: &mut SyncCommandBufferBuilder, dynamic: &Dynami
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shortcut function to bind vertex buffers.
|
// Shortcut function to bind vertex buffers.
|
||||||
unsafe fn vertex_buffers(
|
unsafe fn bind_vertex_buffers(
|
||||||
destination: &mut SyncCommandBufferBuilder,
|
destination: &mut SyncCommandBufferBuilder,
|
||||||
state_cacher: &mut StateCacher,
|
state_cacher: &mut StateCacher,
|
||||||
vertex_buffers: Vec<Box<dyn BufferAccess + Send + Sync>>,
|
vertex_buffers: Vec<Box<dyn BufferAccess + Send + Sync>>,
|
||||||
@ -2182,76 +2169,17 @@ unsafe fn vertex_buffers(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn descriptor_sets<S, Do, Doi>(
|
unsafe fn bind_descriptor_sets(
|
||||||
destination: &mut SyncCommandBufferBuilder,
|
destination: &mut SyncCommandBufferBuilder,
|
||||||
state_cacher: &mut StateCacher,
|
state_cacher: &mut StateCacher,
|
||||||
pipeline_bind_point: PipelineBindPoint,
|
pipeline_bind_point: PipelineBindPoint,
|
||||||
pipeline_layout: &Arc<PipelineLayout>,
|
pipeline_layout: &Arc<PipelineLayout>,
|
||||||
sets: S,
|
descriptor_sets: Vec<DescriptorSetWithOffsets>,
|
||||||
dynamic_offsets: Do,
|
) -> Result<(), SyncCommandBufferBuilderError> {
|
||||||
) -> 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
|
|
||||||
);
|
|
||||||
|
|
||||||
let first_binding = {
|
let first_binding = {
|
||||||
let mut compare = state_cacher.bind_descriptor_sets(pipeline_bind_point);
|
let mut compare = state_cacher.bind_descriptor_sets(pipeline_bind_point);
|
||||||
for set in sets.iter() {
|
for descriptor_set in descriptor_sets.iter() {
|
||||||
compare.add(set, &dynamic_offsets);
|
compare.add(descriptor_set);
|
||||||
}
|
}
|
||||||
compare.compare()
|
compare.compare()
|
||||||
};
|
};
|
||||||
@ -2262,15 +2190,10 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut sets_binder = destination.bind_descriptor_sets();
|
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.add(set);
|
||||||
}
|
}
|
||||||
sets_binder.submit(
|
sets_binder.submit(pipeline_bind_point, pipeline_layout.clone(), first_binding)?;
|
||||||
pipeline_bind_point,
|
|
||||||
pipeline_layout.clone(),
|
|
||||||
first_binding,
|
|
||||||
dynamic_offsets.into_iter(),
|
|
||||||
)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
use crate::buffer::BufferAccess;
|
use crate::buffer::BufferAccess;
|
||||||
use crate::command_buffer::DynamicState;
|
use crate::command_buffer::DynamicState;
|
||||||
use crate::descriptor_set::DescriptorSet;
|
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||||
use crate::pipeline::input_assembly::IndexType;
|
use crate::pipeline::input_assembly::IndexType;
|
||||||
use crate::pipeline::ComputePipelineAbstract;
|
use crate::pipeline::ComputePipelineAbstract;
|
||||||
use crate::pipeline::GraphicsPipelineAbstract;
|
use crate::pipeline::GraphicsPipelineAbstract;
|
||||||
@ -253,21 +253,20 @@ pub struct StateCacherDescriptorSets<'s> {
|
|||||||
impl<'s> StateCacherDescriptorSets<'s> {
|
impl<'s> StateCacherDescriptorSets<'s> {
|
||||||
/// Adds a descriptor set to the list to compare.
|
/// Adds a descriptor set to the list to compare.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add<S>(&mut self, set: &S, dynamic_offsets: &SmallVec<[u32; 32]>)
|
pub fn add(&mut self, descriptor_set: &DescriptorSetWithOffsets) {
|
||||||
where
|
let (descriptor_set, dynamic_offsets) = descriptor_set.as_ref();
|
||||||
S: ?Sized + DescriptorSet,
|
let raw = descriptor_set.inner().internal_object();
|
||||||
{
|
let dynamic_offsets = dynamic_offsets.iter().copied().collect();
|
||||||
let raw = set.inner().internal_object();
|
|
||||||
|
|
||||||
if self.offset < self.state.len() {
|
if let Some(state) = self.state.get_mut(self.offset) {
|
||||||
if (&self.state[self.offset].0, &self.state[self.offset].1) == (&raw, dynamic_offsets) {
|
if (&state.0, &state.1) == (&raw, &dynamic_offsets) {
|
||||||
self.offset += 1;
|
self.offset += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state[self.offset] = (raw, dynamic_offsets.clone());
|
*state = (raw, dynamic_offsets);
|
||||||
} else {
|
} else {
|
||||||
self.state.push((raw, dynamic_offsets.clone()));
|
self.state.push((raw, dynamic_offsets));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.found_diff.is_none() {
|
if self.found_diff.is_none() {
|
||||||
|
@ -27,6 +27,7 @@ use crate::command_buffer::SecondaryCommandBuffer;
|
|||||||
use crate::command_buffer::SubpassContents;
|
use crate::command_buffer::SubpassContents;
|
||||||
use crate::descriptor_set::layout::DescriptorDescTy;
|
use crate::descriptor_set::layout::DescriptorDescTy;
|
||||||
use crate::descriptor_set::DescriptorSet;
|
use crate::descriptor_set::DescriptorSet;
|
||||||
|
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||||
use crate::format::ClearValue;
|
use crate::format::ClearValue;
|
||||||
use crate::image::ImageAccess;
|
use crate::image::ImageAccess;
|
||||||
use crate::image::ImageLayout;
|
use crate::image::ImageLayout;
|
||||||
@ -393,7 +394,7 @@ impl SyncCommandBufferBuilder {
|
|||||||
pub fn bind_descriptor_sets(&mut self) -> SyncCommandBufferBuilderBindDescriptorSets {
|
pub fn bind_descriptor_sets(&mut self) -> SyncCommandBufferBuilderBindDescriptorSets {
|
||||||
SyncCommandBufferBuilderBindDescriptorSets {
|
SyncCommandBufferBuilderBindDescriptorSets {
|
||||||
builder: self,
|
builder: self,
|
||||||
inner: SmallVec::new(),
|
descriptor_sets: SmallVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2613,57 +2614,56 @@ impl SyncCommandBufferBuilder {
|
|||||||
|
|
||||||
pub struct SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
pub struct SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||||
builder: &'b mut SyncCommandBufferBuilder,
|
builder: &'b mut SyncCommandBufferBuilder,
|
||||||
inner: SmallVec<[Box<dyn DescriptorSet + Send + Sync>; 12]>,
|
descriptor_sets: SmallVec<[DescriptorSetWithOffsets; 12]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||||
/// Adds a descriptor set to the list.
|
/// Adds a descriptor set to the list.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add<S>(&mut self, set: S)
|
pub fn add<S>(&mut self, descriptor_set: S)
|
||||||
where
|
where
|
||||||
S: DescriptorSet + Send + Sync + 'static,
|
S: Into<DescriptorSetWithOffsets>,
|
||||||
{
|
{
|
||||||
self.inner.push(Box::new(set));
|
self.descriptor_sets.push(descriptor_set.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn submit<I>(
|
pub unsafe fn submit(
|
||||||
self,
|
self,
|
||||||
pipeline_bind_point: PipelineBindPoint,
|
pipeline_bind_point: PipelineBindPoint,
|
||||||
pipeline_layout: Arc<PipelineLayout>,
|
pipeline_layout: Arc<PipelineLayout>,
|
||||||
first_binding: u32,
|
first_binding: u32,
|
||||||
dynamic_offsets: I,
|
) -> Result<(), SyncCommandBufferBuilderError> {
|
||||||
) -> Result<(), SyncCommandBufferBuilderError>
|
if self.descriptor_sets.is_empty() {
|
||||||
where
|
|
||||||
I: Iterator<Item = u32> + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
if self.inner.is_empty() {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Cmd<I> {
|
struct Cmd {
|
||||||
inner: SmallVec<[Box<dyn DescriptorSet + Send + Sync>; 12]>,
|
descriptor_sets: SmallVec<[DescriptorSetWithOffsets; 12]>,
|
||||||
pipeline_bind_point: PipelineBindPoint,
|
pipeline_bind_point: PipelineBindPoint,
|
||||||
pipeline_layout: Arc<PipelineLayout>,
|
pipeline_layout: Arc<PipelineLayout>,
|
||||||
first_binding: u32,
|
first_binding: u32,
|
||||||
dynamic_offsets: Option<I>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I> Command for Cmd<I>
|
impl Command for Cmd {
|
||||||
where
|
|
||||||
I: Iterator<Item = u32>,
|
|
||||||
{
|
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"vkCmdBindDescriptorSets"
|
"vkCmdBindDescriptorSets"
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder) {
|
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(
|
out.bind_descriptor_sets(
|
||||||
self.pipeline_bind_point,
|
self.pipeline_bind_point,
|
||||||
&self.pipeline_layout,
|
&self.pipeline_layout,
|
||||||
self.first_binding,
|
self.first_binding,
|
||||||
self.inner.iter().map(|s| s.inner()),
|
descriptor_sets,
|
||||||
self.dynamic_offsets.take().unwrap(),
|
dynamic_offsets,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2718,11 +2718,16 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
|||||||
panic!()
|
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 {
|
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) {
|
if let Some(buf) = set.buffer(num) {
|
||||||
return buf.0;
|
return buf.0;
|
||||||
}
|
}
|
||||||
@ -2732,7 +2737,12 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn buffer_name(&self, mut num: usize) -> Cow<'static, str> {
|
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) {
|
if let Some(buf) = set.buffer(num) {
|
||||||
return format!("Buffer bound to descriptor {} of set {}", buf.1, set_num)
|
return format!("Buffer bound to descriptor {} of set {}", buf.1, set_num)
|
||||||
.into();
|
.into();
|
||||||
@ -2743,7 +2753,7 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn image(&self, mut num: usize) -> &dyn ImageAccess {
|
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) {
|
if let Some(img) = set.image(num) {
|
||||||
return img.0.image();
|
return img.0.image();
|
||||||
}
|
}
|
||||||
@ -2753,7 +2763,12 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn image_name(&self, mut num: usize) -> Cow<'static, str> {
|
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) {
|
if let Some(img) = set.image(num) {
|
||||||
return format!("Image bound to descriptor {} of set {}", img.1, set_num)
|
return format!("Image bound to descriptor {} of set {}", img.1, set_num)
|
||||||
.into();
|
.into();
|
||||||
@ -2766,7 +2781,7 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
|||||||
|
|
||||||
let resources = {
|
let resources = {
|
||||||
let mut resources = Vec::new();
|
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() {
|
for buf_num in 0..ds.num_buffers() {
|
||||||
let desc = ds
|
let desc = ds
|
||||||
.layout()
|
.layout()
|
||||||
@ -2842,11 +2857,10 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
|||||||
|
|
||||||
self.builder.append_command(
|
self.builder.append_command(
|
||||||
Cmd {
|
Cmd {
|
||||||
inner: self.inner,
|
descriptor_sets: self.descriptor_sets,
|
||||||
pipeline_bind_point,
|
pipeline_bind_point,
|
||||||
pipeline_layout,
|
pipeline_layout,
|
||||||
first_binding,
|
first_binding,
|
||||||
dynamic_offsets: Some(dynamic_offsets),
|
|
||||||
},
|
},
|
||||||
&resources,
|
&resources,
|
||||||
)?;
|
)?;
|
||||||
|
@ -11,17 +11,14 @@ use std::error;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::descriptor_set::layout::DescriptorDescSupersetError;
|
use crate::descriptor_set::layout::DescriptorDescSupersetError;
|
||||||
use crate::descriptor_set::DescriptorSetsCollection;
|
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||||
use crate::pipeline::layout::PipelineLayout;
|
use crate::pipeline::layout::PipelineLayout;
|
||||||
|
|
||||||
/// Checks whether descriptor sets are compatible with the pipeline.
|
/// 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,
|
pipeline_layout: &PipelineLayout,
|
||||||
descriptor_sets: &D,
|
descriptor_sets: &[DescriptorSetWithOffsets],
|
||||||
) -> Result<(), CheckDescriptorSetsValidityError>
|
) -> Result<(), CheckDescriptorSetsValidityError> {
|
||||||
where
|
|
||||||
D: ?Sized + DescriptorSetsCollection,
|
|
||||||
{
|
|
||||||
// What's important is not that the pipeline layout and the descriptor sets *match*. Instead
|
// 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
|
// 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.
|
// a problem if the descriptor sets provide more elements than expected.
|
||||||
@ -30,7 +27,9 @@ where
|
|||||||
for (binding_num, pipeline_desc) in
|
for (binding_num, pipeline_desc) in
|
||||||
(0..set.num_bindings()).filter_map(|i| set.descriptor(i).map(|d| (i, d)))
|
(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 {
|
let set_desc = match set_desc {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
|
@ -7,194 +7,59 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::descriptor_set::layout::DescriptorDesc;
|
use crate::descriptor_set::DescriptorSetWithOffsets;
|
||||||
use crate::descriptor_set::DescriptorSet;
|
|
||||||
|
|
||||||
/// A collection of descriptor set objects.
|
/// A collection of descriptor set objects.
|
||||||
pub unsafe trait DescriptorSetsCollection {
|
pub unsafe trait DescriptorSetsCollection {
|
||||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>>;
|
fn into_vec(self) -> Vec<DescriptorSetWithOffsets>;
|
||||||
|
|
||||||
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>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl DescriptorSetsCollection for () {
|
unsafe impl DescriptorSetsCollection for () {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>> {
|
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||||
vec![]
|
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
|
unsafe impl<T> DescriptorSetsCollection for T
|
||||||
where
|
where
|
||||||
T: DescriptorSet + Send + Sync + 'static,
|
T: Into<DescriptorSetWithOffsets>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>> {
|
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||||
vec![Box::new(self) as Box<_>]
|
vec![self.into()]
|
||||||
}
|
|
||||||
|
|
||||||
#[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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T> DescriptorSetsCollection for Vec<T>
|
unsafe impl<T> DescriptorSetsCollection for Vec<T>
|
||||||
where
|
where
|
||||||
T: DescriptorSet + Send + Sync + 'static,
|
T: Into<DescriptorSetWithOffsets>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>> {
|
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||||
let mut v = Vec::new();
|
self.into_iter().map(|x| x.into()).collect()
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_collection {
|
macro_rules! impl_collection {
|
||||||
($first:ident $(, $others:ident)+) => (
|
($first:ident $(, $others:ident)+) => (
|
||||||
unsafe impl<$first$(, $others)+> DescriptorSetsCollection for ($first, $($others),+)
|
unsafe impl<$first$(, $others)+> DescriptorSetsCollection for ($first, $($others),+)
|
||||||
where $first: DescriptorSet + Send + Sync + 'static
|
where $first: Into<DescriptorSetWithOffsets>
|
||||||
$(, $others: DescriptorSet + Send + Sync + 'static)*
|
$(, $others: Into<DescriptorSetWithOffsets>)*
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_vec(self) -> Vec<Box<dyn DescriptorSet + Send + Sync>> {
|
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
let ($first, $($others,)*) = self;
|
let ($first, $($others,)*) = self;
|
||||||
|
|
||||||
let mut list = Vec::new();
|
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
|
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),+);
|
impl_collection!($($others),+);
|
||||||
|
@ -81,10 +81,12 @@ pub use self::persistent::PersistentDescriptorSetBuildError;
|
|||||||
pub use self::persistent::PersistentDescriptorSetError;
|
pub use self::persistent::PersistentDescriptorSetError;
|
||||||
use self::sys::UnsafeDescriptorSet;
|
use self::sys::UnsafeDescriptorSet;
|
||||||
use crate::buffer::BufferAccess;
|
use crate::buffer::BufferAccess;
|
||||||
|
use crate::descriptor_set::layout::{DescriptorBufferDesc, DescriptorDescTy};
|
||||||
use crate::device::DeviceOwned;
|
use crate::device::DeviceOwned;
|
||||||
use crate::image::view::ImageViewAbstract;
|
use crate::image::view::ImageViewAbstract;
|
||||||
use crate::SafeDeref;
|
use crate::SafeDeref;
|
||||||
use crate::VulkanObject;
|
use crate::VulkanObject;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -106,6 +108,15 @@ pub unsafe trait DescriptorSet: DeviceOwned {
|
|||||||
/// Returns the layout of this descriptor set.
|
/// Returns the layout of this descriptor set.
|
||||||
fn layout(&self) -> &Arc<DescriptorSetLayout>;
|
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.
|
/// Returns the number of buffers within this descriptor set.
|
||||||
fn num_buffers(&self) -> usize;
|
fn num_buffers(&self) -> usize;
|
||||||
|
|
||||||
@ -178,3 +189,99 @@ impl Hash for dyn DescriptorSet + Send + Sync {
|
|||||||
self.device().hash(state);
|
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,
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
cbb.dispatch([1, 1, 1], pipeline.clone(), set, (), vec![])
|
cbb.dispatch([1, 1, 1], pipeline.clone(), set, ()).unwrap();
|
||||||
.unwrap();
|
|
||||||
let cb = cbb.build().unwrap();
|
let cb = cbb.build().unwrap();
|
||||||
|
|
||||||
let future = now(device.clone())
|
let future = now(device.clone())
|
||||||
|
Loading…
Reference in New Issue
Block a user