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 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 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}