vulk_ext/vkx/
query.rs

1use super::*;
2
3#[derive(Debug)]
4pub struct TimestampQuery {
5    pub(super) query_pool: vk::QueryPool,
6    query_count: u32,
7    timestamp_period: f64,
8}
9
10impl TimestampQuery {
11    pub unsafe fn create(
12        physical_device: &PhysicalDevice,
13        device: &Device,
14        query_count: u32,
15    ) -> Result<Self> {
16        ensure!(query_count >= 2);
17        let query_pool = device.create_query_pool(&vk::QueryPoolCreateInfo {
18            s_type: vk::StructureType::QueryPoolCreateInfo,
19            p_next: null(),
20            flags: vk::QueryPoolCreateFlags::empty(),
21            query_type: vk::QueryType::Timestamp,
22            query_count,
23            pipeline_statistics: vk::QueryPipelineStatisticFlags::empty(),
24        })?;
25        device.reset_query_pool(query_pool, 0, query_count);
26        let timestamp_period = f64::from(physical_device.properties.limits.timestamp_period);
27        Ok(Self {
28            query_pool,
29            query_count,
30            timestamp_period,
31        })
32    }
33
34    pub unsafe fn destroy(self, device: &Device) {
35        device.destroy_query_pool(self.query_pool);
36    }
37
38    pub unsafe fn reset(&self, device: &Device) {
39        device.reset_query_pool(self.query_pool, 0, self.query_count);
40    }
41
42    pub unsafe fn get_raw_timestamps(&self, device: &Device) -> Result<Vec<u64>> {
43        let stride = size_of::<u64>() as u64;
44        let flags = vk::QueryResultFlagBits::Result64 | vk::QueryResultFlagBits::ResultWait;
45        let mut timestamps: Vec<u64> = Vec::with_capacity(self.query_count as _);
46        device.get_query_pool_results(
47            self.query_pool,
48            0,
49            self.query_count,
50            self.query_count as usize * size_of::<u64>(),
51            timestamps.as_mut_ptr().cast(),
52            stride,
53            flags,
54        )?;
55        timestamps.set_len(self.query_count as _);
56        Ok(timestamps)
57    }
58
59    pub unsafe fn get_differences(&self, device: &Device) -> Result<Vec<std::time::Duration>> {
60        let timestamps = self.get_raw_timestamps(device)?;
61        let differences = timestamps
62            .windows(2)
63            .map(|window| {
64                let diff = window[1] - window[0];
65                let diff = diff as f64 * self.timestamp_period;
66                let diff = diff as u64;
67                std::time::Duration::from_nanos(diff)
68            })
69            .collect();
70        Ok(differences)
71    }
72}
73
74#[repr(C)]
75#[derive(Debug)]
76pub struct Statistics {
77    pub pipeline_statistics: PipelineStatistics,
78    pub mesh_primitives_generated: MeshPrimitivesGenerated,
79}
80
81#[repr(C)]
82#[derive(Debug)]
83pub struct PipelineStatistics {
84    pub clipping_invocations: u64,
85    pub clipping_primitives: u64,
86    pub fragment_shader_invocations: u64,
87    pub compute_shader_invocations: u64,
88    pub task_shader_invocations_ext: u64,
89    pub mesh_shader_invocations_ext: u64,
90}
91
92#[repr(C)]
93#[derive(Debug)]
94pub struct MeshPrimitivesGenerated {
95    pub mesh_primitives_generated: u64,
96}
97
98#[derive(Debug)]
99pub struct StatisticsQuery {
100    pub(super) pipeline_statistic_query_pool: vk::QueryPool,
101    pub(super) mesh_primitives_generated_query_pool: vk::QueryPool,
102}
103
104impl StatisticsQuery {
105    pub unsafe fn create(device: &Device) -> Result<Self> {
106        // Pipeline statistic -query pool.
107        let pipeline_statistic_query_pool = device.create_query_pool(&vk::QueryPoolCreateInfo {
108            s_type: vk::StructureType::QueryPoolCreateInfo,
109            p_next: null(),
110            flags: vk::QueryPoolCreateFlags::empty(),
111            query_type: vk::QueryType::PipelineStatistics,
112            query_count: 1,
113            pipeline_statistics: vk::QueryPipelineStatisticFlagBits::ClippingInvocations
114                | vk::QueryPipelineStatisticFlagBits::ClippingPrimitives
115                | vk::QueryPipelineStatisticFlagBits::FragmentShaderInvocations
116                | vk::QueryPipelineStatisticFlagBits::ComputeShaderInvocations
117                | vk::QueryPipelineStatisticFlagBits::TaskShaderInvocationsEXT
118                | vk::QueryPipelineStatisticFlagBits::MeshShaderInvocationsEXT,
119        })?;
120        device.reset_query_pool(pipeline_statistic_query_pool, 0, 1);
121
122        // Mesh primitives generated -query pool.
123        let mesh_primitives_generated_query_pool =
124            device.create_query_pool(&vk::QueryPoolCreateInfo {
125                s_type: vk::StructureType::QueryPoolCreateInfo,
126                p_next: null(),
127                flags: vk::QueryPoolCreateFlags::empty(),
128                query_type: vk::QueryType::MeshPrimitivesGeneratedEXT,
129                query_count: 1,
130                pipeline_statistics: vk::QueryPipelineStatisticFlags::empty(),
131            })?;
132        device.reset_query_pool(mesh_primitives_generated_query_pool, 0, 1);
133
134        Ok(Self {
135            pipeline_statistic_query_pool,
136            mesh_primitives_generated_query_pool,
137        })
138    }
139
140    pub unsafe fn destroy(self, device: &Device) {
141        device.destroy_query_pool(self.pipeline_statistic_query_pool);
142        device.destroy_query_pool(self.mesh_primitives_generated_query_pool);
143    }
144
145    pub unsafe fn reset(&self, device: &Device) {
146        device.reset_query_pool(self.pipeline_statistic_query_pool, 0, 1);
147        device.reset_query_pool(self.mesh_primitives_generated_query_pool, 0, 1);
148    }
149
150    pub unsafe fn get_statistics(&self, device: &Device) -> Result<Statistics> {
151        let stride = size_of::<u64>() as u64;
152        let flags = vk::QueryResultFlagBits::Result64 | vk::QueryResultFlagBits::ResultWait;
153        let mut statistics: Statistics = zeroed();
154        device.get_query_pool_results(
155            self.pipeline_statistic_query_pool,
156            0,
157            1,
158            size_of_val(&statistics.pipeline_statistics),
159            addr_of_mut!(statistics.pipeline_statistics).cast(),
160            stride,
161            flags,
162        )?;
163        device.get_query_pool_results(
164            self.mesh_primitives_generated_query_pool,
165            0,
166            1,
167            size_of_val(&statistics.mesh_primitives_generated),
168            addr_of_mut!(statistics.mesh_primitives_generated).cast(),
169            stride,
170            flags,
171        )?;
172        Ok(statistics)
173    }
174}