From 00fc35b3d444248795a57527fd47abfc46efc1ed Mon Sep 17 00:00:00 2001 From: Rua Date: Tue, 2 Jan 2024 14:08:02 +0100 Subject: [PATCH] Make `QueryType` a regular Vulkan enum (#2438) * Make `QueryType` a regular Vulkan enum * More consistency with Vulkan --- vulkano/src/command_buffer/auto/builder.rs | 6 +- .../src/command_buffer/commands/pipeline.rs | 34 +- vulkano/src/command_buffer/commands/query.rs | 31 +- .../src/command_buffer/commands/secondary.rs | 10 +- vulkano/src/command_buffer/mod.rs | 24 +- vulkano/src/command_buffer/sys.rs | 4 +- vulkano/src/query.rs | 370 +++++++----------- 7 files changed, 188 insertions(+), 291 deletions(-) diff --git a/vulkano/src/command_buffer/auto/builder.rs b/vulkano/src/command_buffer/auto/builder.rs index cedf1e3687..ff8727143d 100644 --- a/vulkano/src/command_buffer/auto/builder.rs +++ b/vulkano/src/command_buffer/auto/builder.rs @@ -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>, // Active queries - pub(in crate::command_buffer) queries: HashMap, + pub(in crate::command_buffer) queries: HashMap, } impl CommandBufferBuilderState { diff --git a/vulkano/src/command_buffer/commands/pipeline.rs b/vulkano/src/command_buffer/commands/pipeline.rs index 1dc6945dda..09b8d9b34a 100644 --- a/vulkano/src/command_buffer/commands/pipeline.rs +++ b/vulkano/src/command_buffer/commands/pipeline.rs @@ -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"), diff --git a/vulkano/src/command_buffer/commands/query.rs b/vulkano/src/command_buffer/commands/query.rs index 488fc06f56..de7a66903a 100644 --- a/vulkano/src/command_buffer/commands/query.rs +++ b/vulkano/src/command_buffer/commands/query.rs @@ -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, 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::() as DeviceSize; let fns = self.device().fns(); diff --git a/vulkano/src/command_buffer/commands/secondary.rs b/vulkano/src/command_buffer/commands/secondary.rs index b78bf3e6ab..68a756b0ae 100644 --- a/vulkano/src/command_buffer/commands/secondary.rs +++ b/vulkano/src/command_buffer/commands/secondary.rs @@ -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() diff --git a/vulkano/src/command_buffer/mod.rs b/vulkano/src/command_buffer/mod.rs index 2a227ebddf..d8dc48f88d 100644 --- a/vulkano/src/command_buffer/mod.rs +++ b/vulkano/src/command_buffer/mod.rs @@ -285,7 +285,7 @@ pub struct CommandBufferInheritanceInfo { /// The default value is `None`. pub occlusion_query: Option, - /// 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", diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index 4f3bc045a4..1355d263f3 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -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() }); diff --git a/vulkano/src/query.rs b/vulkano/src/query.rs index bd3f78d870..49cfe7d9c9 100644 --- a/vulkano/src/query.rs +++ b/vulkano/src/query.rs @@ -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, 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::() 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> { 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> { - 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(_)),