mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-24 15:55:07 +00:00
Make QueryType
a regular Vulkan enum (#2438)
* Make `QueryType` a regular Vulkan enum * More consistency with Vulkan
This commit is contained in:
parent
d08d9f587d
commit
9e82527698
@ -27,7 +27,7 @@ use crate::{
|
||||
},
|
||||
ComputePipeline, DynamicState, GraphicsPipeline, PipelineBindPoint, PipelineLayout,
|
||||
},
|
||||
query::{QueryControlFlags, QueryPool},
|
||||
query::{QueryControlFlags, QueryPool, QueryType},
|
||||
range_map::RangeMap,
|
||||
range_set::RangeSet,
|
||||
render_pass::{Framebuffer, Subpass},
|
||||
@ -108,7 +108,7 @@ impl RecordingCommandBuffer {
|
||||
let &CommandBufferInheritanceInfo {
|
||||
ref render_pass,
|
||||
occlusion_query: _,
|
||||
query_statistics_flags: _,
|
||||
pipeline_statistics: _,
|
||||
_ne: _,
|
||||
} = inheritance_info;
|
||||
|
||||
@ -1209,7 +1209,7 @@ pub(in crate::command_buffer) struct CommandBufferBuilderState {
|
||||
pub(in crate::command_buffer) viewport_with_count: Option<SmallVec<[Viewport; 2]>>,
|
||||
|
||||
// Active queries
|
||||
pub(in crate::command_buffer) queries: HashMap<ash::vk::QueryType, QueryState>,
|
||||
pub(in crate::command_buffer) queries: HashMap<QueryType, QueryState>,
|
||||
}
|
||||
|
||||
impl CommandBufferBuilderState {
|
||||
|
@ -2308,7 +2308,7 @@ impl RecordingCommandBuffer {
|
||||
if self
|
||||
.builder_state
|
||||
.queries
|
||||
.contains_key(&ash::vk::QueryType::MESH_PRIMITIVES_GENERATED_EXT)
|
||||
.contains_key(&QueryType::MeshPrimitivesGenerated)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "a `MeshPrimitivesGenerated` query is currently active".into(),
|
||||
@ -2320,17 +2320,15 @@ impl RecordingCommandBuffer {
|
||||
if let Some(query_state) = self
|
||||
.builder_state
|
||||
.queries
|
||||
.get(&ash::vk::QueryType::PIPELINE_STATISTICS)
|
||||
.get(&QueryType::PipelineStatistics)
|
||||
{
|
||||
let &QueryType::PipelineStatistics(pipeline_statistics_flags) =
|
||||
query_state.query_pool.query_type()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if pipeline_statistics_flags.is_mesh_shading_graphics() {
|
||||
if query_state
|
||||
.query_pool
|
||||
.pipeline_statistics()
|
||||
.is_mesh_shading_graphics()
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "a pipeline statistics query is currently active, and its \
|
||||
problem: "a `PipelineStatistics` query is currently active, and its \
|
||||
pipeline statistics flags include statistics for mesh shading"
|
||||
.into(),
|
||||
vuids: vuids!(vuid_type, "stage-07073"),
|
||||
@ -2385,17 +2383,15 @@ impl RecordingCommandBuffer {
|
||||
if let Some(query_state) = self
|
||||
.builder_state
|
||||
.queries
|
||||
.get(&ash::vk::QueryType::PIPELINE_STATISTICS)
|
||||
.get(&QueryType::PipelineStatistics)
|
||||
{
|
||||
let &QueryType::PipelineStatistics(pipeline_statistics_flags) =
|
||||
query_state.query_pool.query_type()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if pipeline_statistics_flags.is_primitive_shading_graphics() {
|
||||
if query_state
|
||||
.query_pool
|
||||
.pipeline_statistics()
|
||||
.is_primitive_shading_graphics()
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "a pipeline statistics query is currently active, and its \
|
||||
problem: "a `PipelineStatistics` query is currently active, and its \
|
||||
pipeline statistics flags include statistics for primitive shading"
|
||||
.into(),
|
||||
vuids: vuids!(vuid_type, "pipelineStatistics-07076"),
|
||||
|
@ -44,7 +44,7 @@ impl RecordingCommandBuffer {
|
||||
if self
|
||||
.builder_state
|
||||
.queries
|
||||
.contains_key(&query_pool.query_type().into())
|
||||
.contains_key(&query_pool.query_type())
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "a query with the same type as `query_pool.query_type()` is \
|
||||
@ -85,7 +85,7 @@ impl RecordingCommandBuffer {
|
||||
flags: QueryControlFlags,
|
||||
) -> &mut Self {
|
||||
self.builder_state.queries.insert(
|
||||
query_pool.query_type().into(),
|
||||
query_pool.query_type(),
|
||||
QueryState {
|
||||
query_pool: query_pool.clone(),
|
||||
query,
|
||||
@ -126,7 +126,7 @@ impl RecordingCommandBuffer {
|
||||
if !self
|
||||
.builder_state
|
||||
.queries
|
||||
.get(&query_pool.query_type().into())
|
||||
.get(&query_pool.query_type())
|
||||
.map_or(false, |state| {
|
||||
*state.query_pool == *query_pool && state.query == query
|
||||
})
|
||||
@ -163,8 +163,7 @@ impl RecordingCommandBuffer {
|
||||
query_pool: Arc<QueryPool>,
|
||||
query: u32,
|
||||
) -> &mut Self {
|
||||
let raw_ty = query_pool.query_type().into();
|
||||
self.builder_state.queries.remove(&raw_ty);
|
||||
self.builder_state.queries.remove(&query_pool.query_type());
|
||||
|
||||
self.add_command(
|
||||
"end_query",
|
||||
@ -470,16 +469,15 @@ impl RawRecordingCommandBuffer {
|
||||
}));
|
||||
}
|
||||
}
|
||||
QueryType::PipelineStatistics(statistic_flags) => {
|
||||
if statistic_flags.is_graphics()
|
||||
QueryType::PipelineStatistics => {
|
||||
if query_pool.pipeline_statistics().is_graphics()
|
||||
&& !queue_family_properties
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_pool.query_type()".into(),
|
||||
problem: "is `QueryType::PipelineStatistics`, and the \
|
||||
pipeline statistics flags include a graphics flag, but \
|
||||
problem: "`query_pool.query_type()` is `QueryType::PipelineStatistics`, \
|
||||
and `query_pool.pipeline_statistics()` includes a graphics flag, but \
|
||||
the queue family of the command buffer does not support \
|
||||
graphics operations"
|
||||
.into(),
|
||||
@ -488,15 +486,14 @@ impl RawRecordingCommandBuffer {
|
||||
}));
|
||||
}
|
||||
|
||||
if statistic_flags.is_compute()
|
||||
if query_pool.pipeline_statistics().is_compute()
|
||||
&& !queue_family_properties
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::COMPUTE)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_pool.query_type()".into(),
|
||||
problem: "is `QueryType::PipelineStatistics`, and the \
|
||||
pipeline statistics flags include a compute flag, but \
|
||||
problem: "`query_pool.query_type()` is `QueryType::PipelineStatistics`, \
|
||||
and `query_pool.pipeline_statistics()` includes a compute flag, but \
|
||||
the queue family of the command buffer does not support \
|
||||
compute operations"
|
||||
.into(),
|
||||
@ -965,8 +962,7 @@ impl RawRecordingCommandBuffer {
|
||||
}
|
||||
|
||||
let count = queries.end - queries.start;
|
||||
let per_query_len = query_pool.query_type().result_len()
|
||||
+ flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize;
|
||||
let per_query_len = query_pool.result_len(flags);
|
||||
let required_len = per_query_len * count as DeviceSize;
|
||||
|
||||
if destination.len() < required_len {
|
||||
@ -1017,8 +1013,7 @@ impl RawRecordingCommandBuffer {
|
||||
where
|
||||
T: QueryResultElement,
|
||||
{
|
||||
let per_query_len = query_pool.query_type().result_len()
|
||||
+ flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize;
|
||||
let per_query_len = query_pool.result_len(flags);
|
||||
let stride = per_query_len * std::mem::size_of::<T>() as DeviceSize;
|
||||
|
||||
let fns = self.device().fns();
|
||||
|
@ -422,18 +422,18 @@ impl RecordingCommandBuffer {
|
||||
}));
|
||||
}
|
||||
}
|
||||
&QueryType::PipelineStatistics(state_flags) => {
|
||||
let inherited_flags = inheritance_info.query_statistics_flags;
|
||||
QueryType::PipelineStatistics => {
|
||||
let inherited_flags = inheritance_info.pipeline_statistics;
|
||||
|
||||
if !inherited_flags.contains(state_flags) {
|
||||
if !inherited_flags.contains(state.query_pool.pipeline_statistics()) {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: format!(
|
||||
"command_buffers[{}].inheritance_info().query_statistics_flags",
|
||||
"command_buffers[{}].inheritance_info().pipeline_statistics",
|
||||
command_buffer_index
|
||||
)
|
||||
.into(),
|
||||
problem: "is not a superset of the flags of the active \
|
||||
pipeline statistics query"
|
||||
`PipelineStatistics` query"
|
||||
.into(),
|
||||
vuids: &["VUID-vkCmdExecuteCommands-commandBuffer-00104"],
|
||||
..Default::default()
|
||||
|
@ -285,7 +285,7 @@ pub struct CommandBufferInheritanceInfo {
|
||||
/// The default value is `None`.
|
||||
pub occlusion_query: Option<QueryControlFlags>,
|
||||
|
||||
/// Which pipeline statistics queries are allowed to be active on the primary command buffer
|
||||
/// Which `PipelineStatistics` queries are allowed to be active on the primary command buffer
|
||||
/// when this secondary command buffer is executed.
|
||||
///
|
||||
/// If this value is not empty, the [`pipeline_statistics_query`] feature must be enabled on
|
||||
@ -294,7 +294,7 @@ pub struct CommandBufferInheritanceInfo {
|
||||
/// The default value is [`QueryPipelineStatisticFlags::empty()`].
|
||||
///
|
||||
/// [`pipeline_statistics_query`]: crate::device::Features::pipeline_statistics_query
|
||||
pub query_statistics_flags: QueryPipelineStatisticFlags,
|
||||
pub pipeline_statistics: QueryPipelineStatisticFlags,
|
||||
|
||||
pub _ne: crate::NonExhaustive,
|
||||
}
|
||||
@ -305,7 +305,7 @@ impl Default for CommandBufferInheritanceInfo {
|
||||
Self {
|
||||
render_pass: None,
|
||||
occlusion_query: None,
|
||||
query_statistics_flags: QueryPipelineStatisticFlags::empty(),
|
||||
pipeline_statistics: QueryPipelineStatisticFlags::empty(),
|
||||
_ne: crate::NonExhaustive(()),
|
||||
}
|
||||
}
|
||||
@ -316,7 +316,7 @@ impl CommandBufferInheritanceInfo {
|
||||
let &Self {
|
||||
ref render_pass,
|
||||
occlusion_query,
|
||||
query_statistics_flags,
|
||||
pipeline_statistics,
|
||||
_ne: _,
|
||||
} = self;
|
||||
|
||||
@ -370,18 +370,14 @@ impl CommandBufferInheritanceInfo {
|
||||
}
|
||||
}
|
||||
|
||||
query_statistics_flags
|
||||
.validate_device(device)
|
||||
.map_err(|err| {
|
||||
err.add_context("query_statistics_flags")
|
||||
.set_vuids(&["VUID-VkCommandBufferInheritanceInfo-pipelineStatistics-02789"])
|
||||
})?;
|
||||
pipeline_statistics.validate_device(device).map_err(|err| {
|
||||
err.add_context("pipeline_statistics")
|
||||
.set_vuids(&["VUID-VkCommandBufferInheritanceInfo-pipelineStatistics-02789"])
|
||||
})?;
|
||||
|
||||
if query_statistics_flags.count() > 0
|
||||
&& !device.enabled_features().pipeline_statistics_query
|
||||
{
|
||||
if pipeline_statistics.count() > 0 && !device.enabled_features().pipeline_statistics_query {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_statistics_flags".into(),
|
||||
context: "pipeline_statistics".into(),
|
||||
problem: "is not empty".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"pipeline_statistics_query",
|
||||
|
@ -98,7 +98,7 @@ impl RawRecordingCommandBuffer {
|
||||
let &CommandBufferInheritanceInfo {
|
||||
ref render_pass,
|
||||
occlusion_query,
|
||||
query_statistics_flags,
|
||||
pipeline_statistics,
|
||||
_ne: _,
|
||||
} = inheritance_info;
|
||||
|
||||
@ -109,7 +109,7 @@ impl RawRecordingCommandBuffer {
|
||||
framebuffer: ash::vk::Framebuffer::null(),
|
||||
occlusion_query_enable: ash::vk::FALSE,
|
||||
query_flags: ash::vk::QueryControlFlags::empty(),
|
||||
pipeline_statistics: query_statistics_flags.into(),
|
||||
pipeline_statistics: pipeline_statistics.into(),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
buffer::BufferContents,
|
||||
device::{Device, DeviceOwned},
|
||||
instance::InstanceOwnedDebugWrapper,
|
||||
macros::{impl_id_counter, vulkan_bitflags},
|
||||
macros::{impl_id_counter, vulkan_bitflags, vulkan_enum},
|
||||
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError,
|
||||
VulkanObject,
|
||||
};
|
||||
@ -30,6 +30,7 @@ pub struct QueryPool {
|
||||
|
||||
query_type: QueryType,
|
||||
query_count: u32,
|
||||
pipeline_statistics: QueryPipelineStatisticFlags,
|
||||
}
|
||||
|
||||
impl QueryPool {
|
||||
@ -61,22 +62,17 @@ impl QueryPool {
|
||||
create_info: QueryPoolCreateInfo,
|
||||
) -> Result<Arc<QueryPool>, VulkanError> {
|
||||
let &QueryPoolCreateInfo {
|
||||
ref query_type,
|
||||
query_type,
|
||||
query_count,
|
||||
pipeline_statistics,
|
||||
_ne: _,
|
||||
} = &create_info;
|
||||
|
||||
let pipeline_statistics = if let &QueryType::PipelineStatistics(flags) = query_type {
|
||||
flags.into()
|
||||
} else {
|
||||
ash::vk::QueryPipelineStatisticFlags::empty()
|
||||
};
|
||||
|
||||
let create_info_vk = ash::vk::QueryPoolCreateInfo {
|
||||
flags: ash::vk::QueryPoolCreateFlags::empty(),
|
||||
query_type: query_type.into(),
|
||||
query_count,
|
||||
pipeline_statistics,
|
||||
pipeline_statistics: pipeline_statistics.into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@ -112,6 +108,7 @@ impl QueryPool {
|
||||
let QueryPoolCreateInfo {
|
||||
query_type,
|
||||
query_count,
|
||||
pipeline_statistics,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
|
||||
@ -121,13 +118,14 @@ impl QueryPool {
|
||||
id: Self::next_id(),
|
||||
query_type,
|
||||
query_count,
|
||||
pipeline_statistics,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the query type of the pool.
|
||||
#[inline]
|
||||
pub fn query_type(&self) -> &QueryType {
|
||||
&self.query_type
|
||||
pub fn query_type(&self) -> QueryType {
|
||||
self.query_type
|
||||
}
|
||||
|
||||
/// Returns the number of query slots of this query pool.
|
||||
@ -136,6 +134,28 @@ impl QueryPool {
|
||||
self.query_count
|
||||
}
|
||||
|
||||
/// Returns the pipeline statistics flags of this query pool.
|
||||
#[inline]
|
||||
pub fn pipeline_statistics(&self) -> QueryPipelineStatisticFlags {
|
||||
self.pipeline_statistics
|
||||
}
|
||||
|
||||
/// Returns the number of [`QueryResultElement`]s that are needed to hold the result of a
|
||||
/// single query of this type.
|
||||
#[inline]
|
||||
pub const fn result_len(&self, result_flags: QueryResultFlags) -> DeviceSize {
|
||||
(match self.query_type {
|
||||
QueryType::Occlusion
|
||||
| QueryType::Timestamp
|
||||
| QueryType::AccelerationStructureCompactedSize
|
||||
| QueryType::AccelerationStructureSerializationSize
|
||||
| QueryType::AccelerationStructureSerializationBottomLevelPointers
|
||||
| QueryType::AccelerationStructureSize
|
||||
| QueryType::MeshPrimitivesGenerated => 1,
|
||||
QueryType::PipelineStatistics => self.pipeline_statistics.count() as DeviceSize,
|
||||
}) + result_flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize
|
||||
}
|
||||
|
||||
/// Copies the results of a range of queries to a buffer on the CPU.
|
||||
///
|
||||
/// [`self.ty().result_len()`] will be written for each query in the range, plus 1 extra
|
||||
@ -215,8 +235,7 @@ impl QueryPool {
|
||||
// VUID-vkGetQueryPoolResults-stride-08993
|
||||
// Ensured by choosing the stride ourselves.
|
||||
|
||||
let per_query_len = self.query_type.result_len()
|
||||
+ flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize;
|
||||
let per_query_len = self.result_len(flags);
|
||||
let required_len = per_query_len * range.len() as DeviceSize;
|
||||
|
||||
if (destination.len() as DeviceSize) < required_len {
|
||||
@ -230,25 +249,16 @@ impl QueryPool {
|
||||
}));
|
||||
}
|
||||
|
||||
match &self.query_type {
|
||||
QueryType::Timestamp => {
|
||||
if flags.intersects(QueryResultFlags::PARTIAL) {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "`self.query_type()` is `QueryType::Timestamp`, but \
|
||||
`flags` contains `QueryResultFlags::PARTIAL`"
|
||||
.into(),
|
||||
vuids: &["VUID-vkGetQueryPoolResults-queryType-00818"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
if self.query_type == QueryType::Timestamp {
|
||||
if flags.intersects(QueryResultFlags::PARTIAL) {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "`self.query_type()` is `QueryType::Timestamp`, but \
|
||||
`flags` contains `QueryResultFlags::PARTIAL`"
|
||||
.into(),
|
||||
vuids: &["VUID-vkGetQueryPoolResults-queryType-00818"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
QueryType::Occlusion
|
||||
| QueryType::PipelineStatistics(_)
|
||||
| QueryType::AccelerationStructureCompactedSize
|
||||
| QueryType::AccelerationStructureSerializationSize
|
||||
| QueryType::AccelerationStructureSerializationBottomLevelPointers
|
||||
| QueryType::AccelerationStructureSize
|
||||
| QueryType::MeshPrimitivesGenerated => (),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -264,8 +274,7 @@ impl QueryPool {
|
||||
where
|
||||
T: QueryResultElement,
|
||||
{
|
||||
let per_query_len = self.query_type.result_len()
|
||||
+ flags.intersects(QueryResultFlags::WITH_AVAILABILITY) as DeviceSize;
|
||||
let per_query_len = self.result_len(flags);
|
||||
let stride = per_query_len * std::mem::size_of::<T>() as DeviceSize;
|
||||
|
||||
let result = unsafe {
|
||||
@ -331,6 +340,13 @@ pub struct QueryPoolCreateInfo {
|
||||
/// The default value is `0`, which must be overridden.
|
||||
pub query_count: u32,
|
||||
|
||||
/// If `query_type` is [`QueryType::PipelineStatistics`], the statistics to query.
|
||||
///
|
||||
/// For any other value of `query_type`, this must be empty.
|
||||
///
|
||||
/// The default value is empty.
|
||||
pub pipeline_statistics: QueryPipelineStatisticFlags,
|
||||
|
||||
pub _ne: crate::NonExhaustive,
|
||||
}
|
||||
|
||||
@ -341,14 +357,16 @@ impl QueryPoolCreateInfo {
|
||||
Self {
|
||||
query_type,
|
||||
query_count: 0,
|
||||
pipeline_statistics: QueryPipelineStatisticFlags::empty(),
|
||||
_ne: crate::NonExhaustive(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
|
||||
let &Self {
|
||||
ref query_type,
|
||||
query_type,
|
||||
query_count,
|
||||
pipeline_statistics,
|
||||
_ne: _,
|
||||
} = self;
|
||||
|
||||
@ -357,61 +375,6 @@ impl QueryPoolCreateInfo {
|
||||
.set_vuids(&["VUID-VkQueryPoolCreateInfo-queryType-parameter"])
|
||||
})?;
|
||||
|
||||
match query_type {
|
||||
QueryType::PipelineStatistics(flags) => {
|
||||
if !device.enabled_features().pipeline_statistics_query {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_type".into(),
|
||||
problem: "is `QueryType::PipelineStatistics`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"pipeline_statistics_query",
|
||||
)])]),
|
||||
vuids: &["VUID-VkQueryPoolCreateInfo-queryType-00791"],
|
||||
}));
|
||||
}
|
||||
|
||||
flags.validate_device(device).map_err(|err| {
|
||||
err.add_context("query_type.flags")
|
||||
.set_vuids(&["VUID-VkQueryPoolCreateInfo-queryType-00792"])
|
||||
})?;
|
||||
|
||||
if flags.intersects(
|
||||
QueryPipelineStatisticFlags::TASK_SHADER_INVOCATIONS
|
||||
| QueryPipelineStatisticFlags::MESH_SHADER_INVOCATIONS,
|
||||
) && !device.enabled_features().mesh_shader_queries
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_type.flags".into(),
|
||||
problem: "contains `TASK_SHADER_INVOCATIONS` or \
|
||||
`MESH_SHADER_INVOCATIONS`"
|
||||
.into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"mesh_shader_queries",
|
||||
)])]),
|
||||
vuids: &["VUID-VkQueryPoolCreateInfo-meshShaderQueries-07069"],
|
||||
}));
|
||||
}
|
||||
}
|
||||
QueryType::MeshPrimitivesGenerated => {
|
||||
if !device.enabled_features().mesh_shader_queries {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_type".into(),
|
||||
problem: "is `QueryType::MeshPrimitivesGenerated`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"mesh_shader_queries",
|
||||
)])]),
|
||||
vuids: &["VUID-VkQueryPoolCreateInfo-meshShaderQueries-07068"],
|
||||
}));
|
||||
}
|
||||
}
|
||||
QueryType::Occlusion
|
||||
| QueryType::Timestamp
|
||||
| QueryType::AccelerationStructureCompactedSize
|
||||
| QueryType::AccelerationStructureSerializationSize
|
||||
| QueryType::AccelerationStructureSerializationBottomLevelPointers
|
||||
| QueryType::AccelerationStructureSize => (),
|
||||
};
|
||||
|
||||
if query_count == 0 {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_count".into(),
|
||||
@ -421,22 +384,78 @@ impl QueryPoolCreateInfo {
|
||||
}));
|
||||
}
|
||||
|
||||
if query_type == QueryType::PipelineStatistics {
|
||||
if !device.enabled_features().pipeline_statistics_query {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_type".into(),
|
||||
problem: "is `QueryType::PipelineStatistics`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"pipeline_statistics_query",
|
||||
)])]),
|
||||
vuids: &["VUID-VkQueryPoolCreateInfo-queryType-00791"],
|
||||
}));
|
||||
}
|
||||
|
||||
pipeline_statistics.validate_device(device).map_err(|err| {
|
||||
err.add_context("pipeline_statistics")
|
||||
.set_vuids(&["VUID-VkQueryPoolCreateInfo-queryType-00792"])
|
||||
})?;
|
||||
|
||||
if pipeline_statistics.intersects(
|
||||
QueryPipelineStatisticFlags::TASK_SHADER_INVOCATIONS
|
||||
| QueryPipelineStatisticFlags::MESH_SHADER_INVOCATIONS,
|
||||
) && !device.enabled_features().mesh_shader_queries
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "pipeline_statistics".into(),
|
||||
problem: "contains `TASK_SHADER_INVOCATIONS` or \
|
||||
`MESH_SHADER_INVOCATIONS`"
|
||||
.into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"mesh_shader_queries",
|
||||
)])]),
|
||||
vuids: &["VUID-VkQueryPoolCreateInfo-meshShaderQueries-07069"],
|
||||
}));
|
||||
}
|
||||
} else if !pipeline_statistics.is_empty() {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "`query_type` is not `QueryType::PipelineStatistics`, but \
|
||||
`pipeline_statistics` is not empty"
|
||||
.into(),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if query_type == QueryType::MeshPrimitivesGenerated
|
||||
&& !device.enabled_features().mesh_shader_queries
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "query_type".into(),
|
||||
problem: "is `QueryType::MeshPrimitivesGenerated`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"mesh_shader_queries",
|
||||
)])]),
|
||||
vuids: &["VUID-VkQueryPoolCreateInfo-meshShaderQueries-07068"],
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of query that a query pool should perform.
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(i32)]
|
||||
#[non_exhaustive]
|
||||
pub enum QueryType {
|
||||
vulkan_enum! {
|
||||
#[non_exhaustive]
|
||||
|
||||
/// The type of query that a query pool should perform.
|
||||
QueryType = QueryType(i32);
|
||||
|
||||
/// Tracks the number of samples that pass per-fragment tests (e.g. the depth test).
|
||||
///
|
||||
/// Used with the [`begin_query`] and [`end_query`] commands.
|
||||
///
|
||||
/// [`begin_query`]: crate::command_buffer::RecordingCommandBuffer::begin_query
|
||||
/// [`end_query`]: crate::command_buffer::RecordingCommandBuffer::end_query
|
||||
Occlusion = ash::vk::QueryType::OCCLUSION.as_raw(),
|
||||
Occlusion = OCCLUSION,
|
||||
|
||||
/// Tracks statistics on pipeline invocations and their input data.
|
||||
///
|
||||
@ -444,15 +463,14 @@ pub enum QueryType {
|
||||
///
|
||||
/// [`begin_query`]: crate::command_buffer::RecordingCommandBuffer::begin_query
|
||||
/// [`end_query`]: crate::command_buffer::RecordingCommandBuffer::end_query
|
||||
PipelineStatistics(QueryPipelineStatisticFlags) =
|
||||
ash::vk::QueryType::PIPELINE_STATISTICS.as_raw(),
|
||||
PipelineStatistics = PIPELINE_STATISTICS,
|
||||
|
||||
/// Writes timestamps at chosen points in a command buffer.
|
||||
///
|
||||
/// Used with the [`write_timestamp`] command.
|
||||
///
|
||||
/// [`write_timestamp`]: crate::command_buffer::RecordingCommandBuffer::write_timestamp
|
||||
Timestamp = ash::vk::QueryType::TIMESTAMP.as_raw(),
|
||||
Timestamp = TIMESTAMP,
|
||||
|
||||
/// Queries the size of data resulting from a
|
||||
/// [`CopyAccelerationStructureMode::Compact`] operation.
|
||||
@ -461,8 +479,10 @@ pub enum QueryType {
|
||||
///
|
||||
/// [`CopyAccelerationStructureMode::Compact`]: crate::acceleration_structure::CopyAccelerationStructureMode::Compact
|
||||
/// [`write_acceleration_structures_properties`]: crate::command_buffer::RecordingCommandBuffer::write_acceleration_structures_properties
|
||||
AccelerationStructureCompactedSize =
|
||||
ash::vk::QueryType::ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR.as_raw(),
|
||||
AccelerationStructureCompactedSize = ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR
|
||||
RequiresOneOf([
|
||||
RequiresAllOf([DeviceExtension(khr_acceleration_structure)]),
|
||||
]),
|
||||
|
||||
/// Queries the size of data resulting from a
|
||||
/// [`CopyAccelerationStructureMode::Serialize`] operation.
|
||||
@ -471,8 +491,10 @@ pub enum QueryType {
|
||||
///
|
||||
/// [`CopyAccelerationStructureMode::Serialize`]: crate::acceleration_structure::CopyAccelerationStructureMode::Serialize
|
||||
/// [`write_acceleration_structures_properties`]: crate::command_buffer::RecordingCommandBuffer::write_acceleration_structures_properties
|
||||
AccelerationStructureSerializationSize =
|
||||
ash::vk::QueryType::ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR.as_raw(),
|
||||
AccelerationStructureSerializationSize = ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR
|
||||
RequiresOneOf([
|
||||
RequiresAllOf([DeviceExtension(khr_acceleration_structure)]),
|
||||
]),
|
||||
|
||||
/// For a top-level acceleration structure, queries the number of bottom-level acceleration
|
||||
/// structure handles that will be written during a
|
||||
@ -482,143 +504,32 @@ pub enum QueryType {
|
||||
///
|
||||
/// [`CopyAccelerationStructureMode::Serialize`]: crate::acceleration_structure::CopyAccelerationStructureMode::Serialize
|
||||
/// [`write_acceleration_structures_properties`]: crate::command_buffer::RecordingCommandBuffer::write_acceleration_structures_properties
|
||||
AccelerationStructureSerializationBottomLevelPointers =
|
||||
ash::vk::QueryType::ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR.as_raw(),
|
||||
AccelerationStructureSerializationBottomLevelPointers = ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR
|
||||
RequiresOneOf([
|
||||
RequiresAllOf([DeviceExtension(khr_ray_tracing_maintenance1)]),
|
||||
]),
|
||||
|
||||
/// Queries the total size of an acceleration structure.
|
||||
///
|
||||
/// Used with the [`write_acceleration_structures_properties`] command.
|
||||
///
|
||||
/// [`write_acceleration_structures_properties`]: crate::command_buffer::RecordingCommandBuffer::write_acceleration_structures_properties
|
||||
AccelerationStructureSize = ash::vk::QueryType::ACCELERATION_STRUCTURE_SIZE_KHR.as_raw(),
|
||||
AccelerationStructureSize = ACCELERATION_STRUCTURE_SIZE_KHR
|
||||
RequiresOneOf([
|
||||
RequiresAllOf([DeviceExtension(khr_ray_tracing_maintenance1)]),
|
||||
]),
|
||||
|
||||
/// Queries the number of primitives emitted from a mesh shader that reach the fragment shader.
|
||||
///
|
||||
/// Used with the [`begin_query`] and [`end_query`] commands.
|
||||
///
|
||||
|
||||
/// [`begin_query`]: crate::command_buffer::RecordingCommandBuffer::begin_query
|
||||
/// [`end_query`]: crate::command_buffer::RecordingCommandBuffer::end_query
|
||||
MeshPrimitivesGenerated = ash::vk::QueryType::MESH_PRIMITIVES_GENERATED_EXT.as_raw(),
|
||||
}
|
||||
|
||||
impl QueryType {
|
||||
/// Returns the number of [`QueryResultElement`]s that are needed to hold the result of a
|
||||
/// single query of this type.
|
||||
///
|
||||
/// - For [`Occlusion`] and [`Timestamp`] queries, this returns 1.
|
||||
/// - For [`PipelineStatistics`] queries, this returns the number of statistics flags enabled.
|
||||
///
|
||||
/// If the results are retrieved with [`WITH_AVAILABILITY`] enabled, then an additional element
|
||||
/// is required per query.
|
||||
///
|
||||
/// [`Occlusion`]: QueryType::Occlusion
|
||||
/// [`Timestamp`]: QueryType::Timestamp
|
||||
/// [`PipelineStatistics`]: QueryType::PipelineStatistics
|
||||
/// [`WITH_AVAILABILITY`]: QueryResultFlags::WITH_AVAILABILITY
|
||||
#[inline]
|
||||
pub const fn result_len(&self) -> DeviceSize {
|
||||
match self {
|
||||
Self::Occlusion
|
||||
| Self::Timestamp
|
||||
| Self::AccelerationStructureCompactedSize
|
||||
| Self::AccelerationStructureSerializationSize
|
||||
| Self::AccelerationStructureSerializationBottomLevelPointers
|
||||
| Self::AccelerationStructureSize
|
||||
| Self::MeshPrimitivesGenerated => 1,
|
||||
Self::PipelineStatistics(flags) => flags.count() as DeviceSize,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn validate_device(&self, device: &Device) -> Result<(), Box<ValidationError>> {
|
||||
match self {
|
||||
QueryType::Occlusion => (),
|
||||
QueryType::PipelineStatistics(_) => (),
|
||||
QueryType::Timestamp => (),
|
||||
QueryType::AccelerationStructureCompactedSize => {
|
||||
if !device.enabled_extensions().khr_acceleration_structure {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "is `QueryType::AccelerationStructureCompactedSize`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
|
||||
Requires::DeviceExtension("khr_acceleration_structure"),
|
||||
])]),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
QueryType::AccelerationStructureSerializationSize => {
|
||||
if !device.enabled_extensions().khr_acceleration_structure {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "is `QueryType::AccelerationStructureSerializationSize`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
|
||||
Requires::DeviceExtension("khr_acceleration_structure"),
|
||||
])]),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
QueryType::AccelerationStructureSerializationBottomLevelPointers => {
|
||||
if !device.enabled_extensions().khr_ray_tracing_maintenance1 {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem:
|
||||
"is `QueryType::AccelerationStructureSerializationBottomLevelPointers`"
|
||||
.into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
|
||||
Requires::DeviceExtension("khr_ray_tracing_maintenance1"),
|
||||
])]),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
QueryType::AccelerationStructureSize => {
|
||||
if !device.enabled_extensions().khr_ray_tracing_maintenance1 {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "is `QueryType::AccelerationStructureSize`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
|
||||
Requires::DeviceExtension("khr_ray_tracing_maintenance1"),
|
||||
])]),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
QueryType::MeshPrimitivesGenerated => {
|
||||
if !device.enabled_extensions().ext_mesh_shader {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "is `QueryType::MeshPrimitivesGenerated`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
|
||||
Requires::DeviceExtension("ext_mesh_shader"),
|
||||
])]),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&QueryType> for ash::vk::QueryType {
|
||||
#[inline]
|
||||
fn from(value: &QueryType) -> Self {
|
||||
match value {
|
||||
QueryType::Occlusion => ash::vk::QueryType::OCCLUSION,
|
||||
QueryType::PipelineStatistics(_) => ash::vk::QueryType::PIPELINE_STATISTICS,
|
||||
QueryType::Timestamp => ash::vk::QueryType::TIMESTAMP,
|
||||
QueryType::AccelerationStructureCompactedSize => {
|
||||
ash::vk::QueryType::ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR
|
||||
}
|
||||
QueryType::AccelerationStructureSerializationSize => {
|
||||
ash::vk::QueryType::ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR
|
||||
}
|
||||
QueryType::AccelerationStructureSerializationBottomLevelPointers => {
|
||||
ash::vk::QueryType::ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR
|
||||
}
|
||||
QueryType::AccelerationStructureSize => {
|
||||
ash::vk::QueryType::ACCELERATION_STRUCTURE_SIZE_KHR
|
||||
}
|
||||
QueryType::MeshPrimitivesGenerated => ash::vk::QueryType::MESH_PRIMITIVES_GENERATED_EXT,
|
||||
}
|
||||
}
|
||||
MeshPrimitivesGenerated = MESH_PRIMITIVES_GENERATED_EXT
|
||||
RequiresOneOf([
|
||||
RequiresAllOf([DeviceExtension(ext_mesh_shader)]),
|
||||
]),
|
||||
}
|
||||
|
||||
vulkan_bitflags! {
|
||||
@ -636,7 +547,7 @@ vulkan_bitflags! {
|
||||
vulkan_bitflags! {
|
||||
#[non_exhaustive]
|
||||
|
||||
/// For pipeline statistics queries, the statistics that should be gathered.
|
||||
/// For `PipelineStatistics` queries, the statistics that should be gathered.
|
||||
QueryPipelineStatisticFlags impl {
|
||||
/// Returns `true` if `self` contains any flags referring to compute operations.
|
||||
#[inline]
|
||||
@ -777,20 +688,19 @@ vulkan_bitflags! {
|
||||
mod tests {
|
||||
use super::QueryPoolCreateInfo;
|
||||
use crate::{
|
||||
query::{QueryPipelineStatisticFlags, QueryPool, QueryType},
|
||||
query::{QueryPool, QueryType},
|
||||
Validated,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn pipeline_statistics_feature() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
let query_type = QueryType::PipelineStatistics(QueryPipelineStatisticFlags::empty());
|
||||
assert!(matches!(
|
||||
QueryPool::new(
|
||||
device,
|
||||
QueryPoolCreateInfo {
|
||||
query_count: 256,
|
||||
..QueryPoolCreateInfo::query_type(query_type)
|
||||
..QueryPoolCreateInfo::query_type(QueryType::PipelineStatistics)
|
||||
},
|
||||
),
|
||||
Err(Validated::ValidationError(_)),
|
||||
|
Loading…
Reference in New Issue
Block a user