mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 00:04:15 +00:00
Add support for the khr_draw_indirect_count
extension (#2432)
This commit is contained in:
parent
7c66eb8b43
commit
218ad3afcd
@ -26,7 +26,7 @@ use crate::{
|
||||
},
|
||||
shader::{DescriptorBindingRequirements, DescriptorIdentifier, ShaderStage, ShaderStages},
|
||||
sync::{PipelineStageAccess, PipelineStageAccessFlags},
|
||||
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject,
|
||||
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, VulkanObject,
|
||||
};
|
||||
use std::{mem::size_of, sync::Arc};
|
||||
|
||||
@ -37,8 +37,10 @@ macro_rules! vuids {
|
||||
VUIDType::DispatchIndirect => &[$(concat!("VUID-vkCmdDispatchIndirect-", $id)),+],
|
||||
VUIDType::Draw => &[$(concat!("VUID-vkCmdDraw-", $id)),+],
|
||||
VUIDType::DrawIndirect => &[$(concat!("VUID-vkCmdDrawIndirect-", $id)),+],
|
||||
VUIDType::DrawIndirectCount => &[$(concat!("VUID-vkCmdDrawIndirectCount-", $id)),+],
|
||||
VUIDType::DrawIndexed => &[$(concat!("VUID-vkCmdDrawIndexed-", $id)),+],
|
||||
VUIDType::DrawIndexedIndirect => &[$(concat!("VUID-vkCmdDrawIndexedIndirect-", $id)),+],
|
||||
VUIDType::DrawIndexedIndirectCount => &[$(concat!("VUID-vkCmdDrawIndexedIndirectCount-", $id)),+],
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -496,6 +498,142 @@ impl RecordingCommandBuffer {
|
||||
self
|
||||
}
|
||||
|
||||
/// Perform multiple draw operations using a graphics pipeline,
|
||||
/// reading the number of draw operations from a separate buffer.
|
||||
///
|
||||
/// One draw is performed for each [`DrawIndirectCommand`] struct that is read from
|
||||
/// `indirect_buffer`. The number of draws to perform is read from `count_buffer`, or
|
||||
/// specified by `max_draw_count`, whichever is lower.
|
||||
/// This number is limited by the
|
||||
/// [`max_draw_indirect_count`](Properties::max_draw_indirect_count) limit.
|
||||
///
|
||||
/// A graphics pipeline must have been bound using
|
||||
/// [`bind_pipeline_graphics`](Self::bind_pipeline_graphics). Any resources used by the graphics
|
||||
/// pipeline, such as descriptor sets, vertex buffers and dynamic state, must have been set
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the vertex and instance
|
||||
/// ranges of each `DrawIndirectCommand` in the indirect buffer must be in range of the bound
|
||||
/// vertex buffers.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The general [shader safety requirements](crate::shader#safety) apply.
|
||||
/// - The [safety requirements for `DrawIndirectCommand`](DrawIndirectCommand#safety)
|
||||
/// apply.
|
||||
/// - The count stored in `count_buffer` must not be greater than the
|
||||
/// [`max_draw_indirect_count`](Properties::max_draw_indirect_count) device limit.
|
||||
/// - The count stored in `count_buffer` must fall within the range of `indirect_buffer`.
|
||||
pub unsafe fn draw_indirect_count(
|
||||
&mut self,
|
||||
indirect_buffer: Subbuffer<[DrawIndirectCommand]>,
|
||||
count_buffer: Subbuffer<u32>,
|
||||
max_draw_count: u32,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
let stride = size_of::<DrawIndirectCommand>() as u32;
|
||||
self.validate_draw_indirect_count(
|
||||
indirect_buffer.as_bytes(),
|
||||
count_buffer.as_bytes(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
)?;
|
||||
|
||||
unsafe {
|
||||
Ok(self.draw_indirect_count_unchecked(
|
||||
indirect_buffer,
|
||||
count_buffer,
|
||||
max_draw_count,
|
||||
stride,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_draw_indirect_count(
|
||||
&self,
|
||||
indirect_buffer: &Subbuffer<[u8]>,
|
||||
count_buffer: &Subbuffer<[u8]>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> Result<(), Box<ValidationError>> {
|
||||
self.inner.validate_draw_indirect_count(
|
||||
indirect_buffer,
|
||||
count_buffer,
|
||||
max_draw_count,
|
||||
stride,
|
||||
)?;
|
||||
|
||||
let render_pass_state = self.builder_state.render_pass.as_ref().ok_or_else(|| {
|
||||
Box::new(ValidationError {
|
||||
problem: "a render pass instance is not active".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-renderpass"],
|
||||
..Default::default()
|
||||
})
|
||||
})?;
|
||||
|
||||
let pipeline = self
|
||||
.builder_state
|
||||
.pipeline_graphics
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
Box::new(ValidationError {
|
||||
problem: "no graphics pipeline is currently bound".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-None-08606"],
|
||||
..Default::default()
|
||||
})
|
||||
})?
|
||||
.as_ref();
|
||||
|
||||
const VUID_TYPE: VUIDType = VUIDType::DrawIndirectCount;
|
||||
self.validate_pipeline_descriptor_sets(VUID_TYPE, pipeline)?;
|
||||
self.validate_pipeline_push_constants(VUID_TYPE, pipeline.layout())?;
|
||||
self.validate_pipeline_graphics_dynamic_state(VUID_TYPE, pipeline)?;
|
||||
self.validate_pipeline_graphics_render_pass(VUID_TYPE, pipeline, render_pass_state)?;
|
||||
self.validate_pipeline_graphics_vertex_buffers(VUID_TYPE, pipeline)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn draw_indirect_count_unchecked(
|
||||
&mut self,
|
||||
indirect_buffer: Subbuffer<[DrawIndirectCommand]>,
|
||||
count_buffer: Subbuffer<u32>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> &mut Self {
|
||||
if let RenderPassStateType::BeginRendering(state) =
|
||||
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
||||
{
|
||||
state.pipeline_used = true;
|
||||
}
|
||||
|
||||
let pipeline = self
|
||||
.builder_state
|
||||
.pipeline_graphics
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref();
|
||||
|
||||
let mut used_resources = Vec::new();
|
||||
self.add_descriptor_sets_resources(&mut used_resources, pipeline);
|
||||
self.add_vertex_buffers_resources(&mut used_resources, pipeline);
|
||||
self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes());
|
||||
self.add_indirect_buffer_resources(&mut used_resources, count_buffer.as_bytes());
|
||||
|
||||
self.add_command(
|
||||
"draw_indirect_count",
|
||||
used_resources,
|
||||
move |out: &mut RawRecordingCommandBuffer| {
|
||||
out.draw_indirect_count_unchecked(
|
||||
&indirect_buffer,
|
||||
&count_buffer,
|
||||
max_draw_count,
|
||||
stride,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Perform a single draw operation using a graphics pipeline, using an index buffer.
|
||||
///
|
||||
/// The parameters specify the first index and the number of indices in the index buffer that
|
||||
@ -854,6 +992,156 @@ impl RecordingCommandBuffer {
|
||||
self
|
||||
}
|
||||
|
||||
/// Perform multiple draw operations using a graphics pipeline, using an index buffer,
|
||||
/// and reading the number of draw operations from a separate buffer.
|
||||
///
|
||||
/// One draw is performed for each [`DrawIndexedIndirectCommand`] struct that is read from
|
||||
/// `indirect_buffer`. The number of draws to perform is read from `count_buffer`, or
|
||||
/// specified by `max_draw_count`, whichever is lower.
|
||||
/// This number is limited by the
|
||||
/// [`max_draw_indirect_count`](Properties::max_draw_indirect_count) limit.
|
||||
///
|
||||
/// An index buffer must have been bound using
|
||||
/// [`bind_index_buffer`](Self::bind_index_buffer), and the index ranges of each
|
||||
/// `DrawIndexedIndirectCommand` in the indirect buffer must be in range of the bound index
|
||||
/// buffer.
|
||||
///
|
||||
/// A graphics pipeline must have been bound using
|
||||
/// [`bind_pipeline_graphics`](Self::bind_pipeline_graphics). Any resources used by the graphics
|
||||
/// pipeline, such as descriptor sets, vertex buffers and dynamic state, must have been set
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the instance ranges of
|
||||
/// each `DrawIndexedIndirectCommand` in the indirect buffer must be in range of the bound
|
||||
/// vertex buffers.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The general [shader safety requirements](crate::shader#safety) apply.
|
||||
/// - The [safety requirements for `DrawIndexedIndirectCommand`](DrawIndexedIndirectCommand#safety)
|
||||
/// apply.
|
||||
/// - The count stored in `count_buffer` must not be greater than the
|
||||
/// [`max_draw_indirect_count`](Properties::max_draw_indirect_count) device limit.
|
||||
/// - The count stored in `count_buffer` must fall within the range of `indirect_buffer`.
|
||||
pub unsafe fn draw_indexed_indirect_count(
|
||||
&mut self,
|
||||
indirect_buffer: Subbuffer<[DrawIndexedIndirectCommand]>,
|
||||
count_buffer: Subbuffer<u32>,
|
||||
max_draw_count: u32,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
let stride = size_of::<DrawIndexedIndirectCommand>() as u32;
|
||||
self.validate_draw_indexed_indirect_count(
|
||||
indirect_buffer.as_bytes(),
|
||||
count_buffer.as_bytes(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
)?;
|
||||
|
||||
unsafe {
|
||||
Ok(self.draw_indexed_indirect_count_unchecked(
|
||||
indirect_buffer,
|
||||
count_buffer,
|
||||
max_draw_count,
|
||||
stride,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_draw_indexed_indirect_count(
|
||||
&self,
|
||||
indirect_buffer: &Subbuffer<[u8]>,
|
||||
count_buffer: &Subbuffer<[u8]>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> Result<(), Box<ValidationError>> {
|
||||
self.inner.validate_draw_indexed_indirect_count(
|
||||
indirect_buffer,
|
||||
count_buffer,
|
||||
max_draw_count,
|
||||
stride,
|
||||
)?;
|
||||
|
||||
let render_pass_state = self.builder_state.render_pass.as_ref().ok_or_else(|| {
|
||||
Box::new(ValidationError {
|
||||
problem: "a render pass instance is not active".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-renderpass"],
|
||||
..Default::default()
|
||||
})
|
||||
})?;
|
||||
|
||||
let pipeline = self
|
||||
.builder_state
|
||||
.pipeline_graphics
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
Box::new(ValidationError {
|
||||
problem: "no graphics pipeline is currently bound".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-None-08606"],
|
||||
..Default::default()
|
||||
})
|
||||
})?
|
||||
.as_ref();
|
||||
|
||||
const VUID_TYPE: VUIDType = VUIDType::DrawIndexedIndirectCount;
|
||||
self.validate_pipeline_descriptor_sets(VUID_TYPE, pipeline)?;
|
||||
self.validate_pipeline_push_constants(VUID_TYPE, pipeline.layout())?;
|
||||
self.validate_pipeline_graphics_dynamic_state(VUID_TYPE, pipeline)?;
|
||||
self.validate_pipeline_graphics_render_pass(VUID_TYPE, pipeline, render_pass_state)?;
|
||||
self.validate_pipeline_graphics_vertex_buffers(VUID_TYPE, pipeline)?;
|
||||
|
||||
let _index_buffer = self.builder_state.index_buffer.as_ref().ok_or_else(|| {
|
||||
Box::new(ValidationError {
|
||||
problem: "no index buffer is currently bound".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-None-07312"],
|
||||
..Default::default()
|
||||
})
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn draw_indexed_indirect_count_unchecked(
|
||||
&mut self,
|
||||
indirect_buffer: Subbuffer<[DrawIndexedIndirectCommand]>,
|
||||
count_buffer: Subbuffer<u32>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> &mut Self {
|
||||
if let RenderPassStateType::BeginRendering(state) =
|
||||
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
||||
{
|
||||
state.pipeline_used = true;
|
||||
}
|
||||
|
||||
let pipeline = self
|
||||
.builder_state
|
||||
.pipeline_graphics
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref();
|
||||
|
||||
let mut used_resources = Vec::new();
|
||||
self.add_descriptor_sets_resources(&mut used_resources, pipeline);
|
||||
self.add_vertex_buffers_resources(&mut used_resources, pipeline);
|
||||
self.add_index_buffer_resources(&mut used_resources);
|
||||
self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes());
|
||||
self.add_indirect_buffer_resources(&mut used_resources, count_buffer.as_bytes());
|
||||
|
||||
self.add_command(
|
||||
"draw_indexed_indirect_count",
|
||||
used_resources,
|
||||
move |out: &mut RawRecordingCommandBuffer| {
|
||||
out.draw_indexed_indirect_count_unchecked(
|
||||
&indirect_buffer,
|
||||
&count_buffer,
|
||||
max_draw_count,
|
||||
stride,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
fn validate_pipeline_descriptor_sets<Pl: Pipeline>(
|
||||
&self,
|
||||
vuid_type: VUIDType,
|
||||
@ -3144,6 +3432,169 @@ impl RawRecordingCommandBuffer {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn draw_indirect_count(
|
||||
&mut self,
|
||||
indirect_buffer: &Subbuffer<[DrawIndirectCommand]>,
|
||||
count_buffer: &Subbuffer<u32>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_draw_indirect_count(
|
||||
indirect_buffer.as_bytes(),
|
||||
count_buffer.as_bytes(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
)?;
|
||||
|
||||
Ok(self.draw_indirect_count_unchecked(
|
||||
indirect_buffer,
|
||||
count_buffer,
|
||||
max_draw_count,
|
||||
stride,
|
||||
))
|
||||
}
|
||||
|
||||
fn validate_draw_indirect_count(
|
||||
&self,
|
||||
indirect_buffer: &Subbuffer<[u8]>,
|
||||
count_buffer: &Subbuffer<[u8]>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> Result<(), Box<ValidationError>> {
|
||||
if !self.device().enabled_features().draw_indirect_count {
|
||||
return Err(Box::new(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"draw_indirect_count",
|
||||
)])]),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-None-04445"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if !self
|
||||
.queue_family_properties()
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "the queue family of the command buffer does not support \
|
||||
graphics operations"
|
||||
.into(),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-commandBuffer-cmdpool"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if !indirect_buffer
|
||||
.buffer()
|
||||
.usage()
|
||||
.intersects(BufferUsage::INDIRECT_BUFFER)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "indirect_buffer.usage()".into(),
|
||||
problem: "does not contain `BufferUsage::INDIRECT_BUFFER`".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-buffer-02709"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if !count_buffer
|
||||
.buffer()
|
||||
.usage()
|
||||
.intersects(BufferUsage::INDIRECT_BUFFER)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "count_buffer.usage()".into(),
|
||||
problem: "does not contain `BufferUsage::INDIRECT_BUFFER`".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-countBuffer-02715"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if stride % 4 != 0 {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "stride".into(),
|
||||
problem: "is not a multiple of 4".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-stride-03110"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if (stride as DeviceSize) < size_of::<DrawIndirectCommand>() as DeviceSize {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "stride".into(),
|
||||
problem: "is not greater than `size_of::<DrawIndirectCommand>()`".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-stride-03110"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if max_draw_count >= 1
|
||||
&& stride as DeviceSize * (max_draw_count as DeviceSize - 1)
|
||||
+ size_of::<DrawIndirectCommand>() as DeviceSize
|
||||
> indirect_buffer.size()
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "`max_draw_count` is equal to or greater than 1, but \
|
||||
`stride * (max_draw_count - 1) + size_of::<DrawIndirectCommand>()` is \
|
||||
greater than `indirect_buffer.size()`"
|
||||
.into(),
|
||||
vuids: &["VUID-vkCmdDrawIndirectCount-maxDrawCount-03111"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn draw_indirect_count_unchecked(
|
||||
&mut self,
|
||||
indirect_buffer: &Subbuffer<[DrawIndirectCommand]>,
|
||||
count_buffer: &Subbuffer<u32>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> &mut Self {
|
||||
let device = self.device();
|
||||
let fns = device.fns();
|
||||
|
||||
if device.api_version() >= Version::V1_2 {
|
||||
(fns.v1_2.cmd_draw_indirect_count)(
|
||||
self.handle(),
|
||||
indirect_buffer.buffer().handle(),
|
||||
indirect_buffer.offset(),
|
||||
count_buffer.buffer().handle(),
|
||||
count_buffer.offset(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
);
|
||||
} else if device.enabled_extensions().khr_draw_indirect_count {
|
||||
(fns.khr_draw_indirect_count.cmd_draw_indirect_count_khr)(
|
||||
self.handle(),
|
||||
indirect_buffer.buffer().handle(),
|
||||
indirect_buffer.offset(),
|
||||
count_buffer.buffer().handle(),
|
||||
count_buffer.offset(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
);
|
||||
} else {
|
||||
debug_assert!(device.enabled_extensions().amd_draw_indirect_count);
|
||||
(fns.amd_draw_indirect_count.cmd_draw_indirect_count_amd)(
|
||||
self.handle(),
|
||||
indirect_buffer.buffer().handle(),
|
||||
indirect_buffer.offset(),
|
||||
count_buffer.buffer().handle(),
|
||||
count_buffer.offset(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn draw_indexed(
|
||||
&mut self,
|
||||
@ -3351,6 +3802,171 @@ impl RawRecordingCommandBuffer {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn draw_indexed_indirect_count(
|
||||
&mut self,
|
||||
indirect_buffer: &Subbuffer<[DrawIndexedIndirectCommand]>,
|
||||
count_buffer: &Subbuffer<u32>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_draw_indexed_indirect_count(
|
||||
indirect_buffer.as_bytes(),
|
||||
count_buffer.as_bytes(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
)?;
|
||||
|
||||
Ok(self.draw_indexed_indirect_count_unchecked(
|
||||
indirect_buffer,
|
||||
count_buffer,
|
||||
max_draw_count,
|
||||
stride,
|
||||
))
|
||||
}
|
||||
|
||||
fn validate_draw_indexed_indirect_count(
|
||||
&self,
|
||||
indirect_buffer: &Subbuffer<[u8]>,
|
||||
count_buffer: &Subbuffer<[u8]>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> Result<(), Box<ValidationError>> {
|
||||
if !self.device().enabled_features().draw_indirect_count {
|
||||
return Err(Box::new(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"draw_indirect_count",
|
||||
)])]),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-None-04445"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if !self
|
||||
.queue_family_properties()
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "the queue family of the command buffer does not support \
|
||||
graphics operations"
|
||||
.into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-commandBuffer-cmdpool"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if !indirect_buffer
|
||||
.buffer()
|
||||
.usage()
|
||||
.intersects(BufferUsage::INDIRECT_BUFFER)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "indirect_buffer.usage()".into(),
|
||||
problem: "does not contain `BufferUsage::INDIRECT_BUFFER`".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-buffer-02709"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if !count_buffer
|
||||
.buffer()
|
||||
.usage()
|
||||
.intersects(BufferUsage::INDIRECT_BUFFER)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "count_buffer.usage()".into(),
|
||||
problem: "does not contain `BufferUsage::INDIRECT_BUFFER`".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-countBuffer-02715"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if stride % 4 != 0 {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "stride".into(),
|
||||
problem: "is not a multiple of 4".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-stride-03142"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if (stride as DeviceSize) < size_of::<DrawIndirectCommand>() as DeviceSize {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "stride".into(),
|
||||
problem: "is not greater than `size_of::<DrawIndirectCommand>()`".into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-stride-03142"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if max_draw_count >= 1
|
||||
&& stride as DeviceSize * (max_draw_count as DeviceSize - 1)
|
||||
+ size_of::<DrawIndirectCommand>() as DeviceSize
|
||||
> indirect_buffer.size()
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "`max_draw_count` is equal to or greater than 1, but \
|
||||
`stride * (max_draw_count - 1) + size_of::<DrawIndirectCommand>()` is \
|
||||
greater than `indirect_buffer.size()`"
|
||||
.into(),
|
||||
vuids: &["VUID-vkCmdDrawIndexedIndirectCount-maxDrawCount-03143"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn draw_indexed_indirect_count_unchecked(
|
||||
&mut self,
|
||||
indirect_buffer: &Subbuffer<[DrawIndexedIndirectCommand]>,
|
||||
count_buffer: &Subbuffer<u32>,
|
||||
max_draw_count: u32,
|
||||
stride: u32,
|
||||
) -> &mut Self {
|
||||
let device = self.device();
|
||||
let fns = device.fns();
|
||||
|
||||
if device.api_version() >= Version::V1_2 {
|
||||
(fns.v1_2.cmd_draw_indexed_indirect_count)(
|
||||
self.handle(),
|
||||
indirect_buffer.buffer().handle(),
|
||||
indirect_buffer.offset(),
|
||||
count_buffer.buffer().handle(),
|
||||
count_buffer.offset(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
);
|
||||
} else if device.enabled_extensions().khr_draw_indirect_count {
|
||||
(fns.khr_draw_indirect_count
|
||||
.cmd_draw_indexed_indirect_count_khr)(
|
||||
self.handle(),
|
||||
indirect_buffer.buffer().handle(),
|
||||
indirect_buffer.offset(),
|
||||
count_buffer.buffer().handle(),
|
||||
count_buffer.offset(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
);
|
||||
} else {
|
||||
debug_assert!(device.enabled_extensions().amd_draw_indirect_count);
|
||||
(fns.amd_draw_indirect_count
|
||||
.cmd_draw_indexed_indirect_count_amd)(
|
||||
self.handle(),
|
||||
indirect_buffer.buffer().handle(),
|
||||
indirect_buffer.offset(),
|
||||
count_buffer.buffer().handle(),
|
||||
count_buffer.offset(),
|
||||
max_draw_count,
|
||||
stride,
|
||||
);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
@ -3359,6 +3975,8 @@ enum VUIDType {
|
||||
DispatchIndirect,
|
||||
Draw,
|
||||
DrawIndirect,
|
||||
DrawIndirectCount,
|
||||
DrawIndexed,
|
||||
DrawIndexedIndirect,
|
||||
DrawIndexedIndirectCount,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user