used pipeline statistics to check compute shader invocations

working
Nathan Buck 6 months ago
parent 348e33df5e
commit 54d7ced9df

8255
out.txt

File diff suppressed because it is too large Load Diff

2113
rnd.rs

File diff suppressed because it is too large Load Diff

@ -173,7 +173,7 @@ pub fn find_memory_type(
panic!("Failed to find suitable memory type!") panic!("Failed to find suitable memory type!")
} }
pub struct App { pub struct App<'a> {
pub window: winit::window::Window, pub window: winit::window::Window,
// vulkan stuff // vulkan stuff
@ -245,9 +245,13 @@ pub struct App {
pub last_time: f64, pub last_time: f64,
pub physical_device_memory_properties: vk::PhysicalDeviceMemoryProperties, pub physical_device_memory_properties: vk::PhysicalDeviceMemoryProperties,
pub query_pool: vk::QueryPool,
pub query_memory: vk::DeviceMemory,
pub query_mapped: &'a mut [u64],
} }
impl App { impl<'a> App<'a> {
pub fn new(event_loop: &winit::event_loop::EventLoop<()>) -> Self { pub fn new(event_loop: &winit::event_loop::EventLoop<()>) -> Self {
let window = init_window(&event_loop, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT); let window = init_window(&event_loop, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT);
@ -328,6 +332,84 @@ impl App {
let sync_objects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT); let sync_objects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT);
//setup logging of compute shader invocations
// Define the buffer to hold query results
let mut query_results_data: [u64; 1] = [0]; // Assuming we're querying one result
// Create a buffer to hold the query results
let buffer_info = vk::BufferCreateInfo {
s_type: vk::StructureType::BUFFER_CREATE_INFO,
size: 8,
usage: vk::BufferUsageFlags::TRANSFER_DST,
sharing_mode: vk::SharingMode::EXCLUSIVE,
..Default::default()
};
let query_result_buffer = unsafe {
device
.create_buffer(&buffer_info, None)
.expect("Failed to create query result buffer")
};
// Allocate memory for the buffer
let mem_requirements = unsafe { device.get_buffer_memory_requirements(query_result_buffer) };
let memory_type_index = find_memory_type(
mem_requirements.memory_type_bits,
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
&physical_device_memory_properties,
);
let allocate_info = vk::MemoryAllocateInfo {
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
allocation_size: mem_requirements.size,
memory_type_index,
..Default::default()
};
let query_memory = unsafe {
device
.allocate_memory(&allocate_info, None)
.expect("Failed to allocate query result memory")
};
unsafe {
// Bind the buffer with allocated memory
device
.bind_buffer_memory(query_result_buffer, query_memory, 0)
.expect("Failed to bind buffer memory")
};
// Now we can use this buffer to store query results
let query_mapped = unsafe {
let raw_ptr = device
.map_memory(
query_memory,
0,
std::mem::size_of_val(&query_results_data) as u64,
vk::MemoryMapFlags::empty(),
)
.expect("Failed to map memory");
std::slice::from_raw_parts_mut(raw_ptr as *mut u64, 1)
};
// Create a query pool
let query_pool_info = vk::QueryPoolCreateInfo {
s_type: vk::StructureType::QUERY_POOL_CREATE_INFO,
query_type: vk::QueryType::PIPELINE_STATISTICS,
query_count: 1, // We're only querying one statistic
pipeline_statistics: vk::QueryPipelineStatisticFlags::COMPUTE_SHADER_INVOCATIONS,
..Default::default()
};
let query_pool = unsafe {
device
.create_query_pool(&query_pool_info, None)
.expect("Failed to create query pool")
};
Self { Self {
window, window,
@ -381,6 +463,11 @@ impl App {
last_time: 0.0, last_time: 0.0,
physical_device_memory_properties, physical_device_memory_properties,
query_pool,
query_memory,
query_mapped,
} }
} }
@ -673,25 +760,35 @@ impl App {
fn record_compute_command_buffer( fn record_compute_command_buffer(
&self, &mut self,
device: &ash::Device,
command_buffer: vk::CommandBuffer command_buffer: vk::CommandBuffer
) { ) {
let begin_info = vk::CommandBufferBeginInfo::default(); let begin_info = vk::CommandBufferBeginInfo::default();
unsafe { unsafe {
device self.device
.begin_command_buffer(command_buffer, &begin_info) .begin_command_buffer(command_buffer, &begin_info)
.expect("failed to begin recording compute command buffer"); .expect("failed to begin recording compute command buffer");
device println!("resetting query pool for command buffer: {}", self.current_frame);
self.device
.cmd_reset_query_pool(
self.compute_command_buffers[self.current_frame],
self.query_pool,
0,
1,
);
self.device.cmd_begin_query(self.compute_command_buffers[self.current_frame], self.query_pool, 0, vk::QueryControlFlags::empty());
self.device
.cmd_bind_pipeline( .cmd_bind_pipeline(
command_buffer, command_buffer,
vk::PipelineBindPoint::COMPUTE, vk::PipelineBindPoint::COMPUTE,
self.compute_pipeline, self.compute_pipeline,
); );
device self.device
.cmd_bind_descriptor_sets( .cmd_bind_descriptor_sets(
command_buffer, command_buffer,
vk::PipelineBindPoint::COMPUTE, vk::PipelineBindPoint::COMPUTE,
@ -701,14 +798,33 @@ impl App {
&[], &[],
); );
device self.device
.cmd_dispatch( .cmd_dispatch(
command_buffer, command_buffer,
(PARTICLE_COUNT / 256) as u32, (PARTICLE_COUNT / 256) as u32,
1, 1,
1, 1,
); );
device
//log compute shader invocations
self.device.cmd_end_query(self.compute_command_buffers[self.current_frame], self.query_pool, 0);
/*let query_results = unsafe {
self.device.get_query_pool_results::<u64>(
self.query_pool,
0, // Starting query index
1, // Number of queries to retrieve (1 in this case)
self.query_mapped, // Results will be stored here
//0, // Query results stride (optional)
vk::QueryResultFlags::TYPE_64, // Flags specifying the type of query results
)
.expect("Failed to retrieve query pool results"
)};
println!("Compute shader invocations: {:?}", self.query_mapped[0]);*/
self.device
.end_command_buffer(command_buffer) .end_command_buffer(command_buffer)
.expect("failed ending compute command buffer"); .expect("failed ending compute command buffer");
} }
@ -1012,6 +1128,7 @@ impl App {
let physical_device_features = vk::PhysicalDeviceFeatures { let physical_device_features = vk::PhysicalDeviceFeatures {
sampler_anisotropy: vk::TRUE, // enable anisotropy device feature from Chapter-24. sampler_anisotropy: vk::TRUE, // enable anisotropy device feature from Chapter-24.
pipeline_statistics_query: vk::TRUE,
..Default::default() ..Default::default()
}; };
@ -1586,7 +1703,7 @@ impl App {
range: size_of::<UniformBufferObject>() as u64, range: size_of::<UniformBufferObject>() as u64,
}; };
println!("STORAGE BUFFERS INDEXES: {}, {}", i, (i as i32 - 1) as usize % MAX_FRAMES_IN_FLIGHT); println!("STORAGE BUFFERS INDEXES: {}, {}", (i as i32 - 1) as usize % MAX_FRAMES_IN_FLIGHT, i);
let storage_buffer_info_last_frame = vk::DescriptorBufferInfo { let storage_buffer_info_last_frame = vk::DescriptorBufferInfo {
buffer: shader_storage_buffers[(i as i32 - 1) as usize % MAX_FRAMES_IN_FLIGHT], buffer: shader_storage_buffers[(i as i32 - 1) as usize % MAX_FRAMES_IN_FLIGHT],
@ -1745,7 +1862,7 @@ impl App {
} }
} }
impl VulkanApp for App { impl VulkanApp for App<'_> {
fn wait_device_idle(&self) { fn wait_device_idle(&self) {
unsafe { unsafe {
@ -1772,28 +1889,8 @@ impl VulkanApp for App {
} }
fn draw_frame(&mut self) { fn draw_frame(&mut self) {
//log shader storage buffers with Particle positions for debugging and recording purposes
let mut buffer_size: u64 = std::mem::size_of::<Particle>() as u64 * PARTICLE_COUNT as u64; let mut buffer_size: u64 = std::mem::size_of::<Particle>() as u64 * PARTICLE_COUNT as u64;
for (i, memory) in (&self.shader_storage_buffers_memory).iter().enumerate() {
let mut data = unsafe { self.device
.map_memory(
*memory,
0,
buffer_size,
vk::MemoryMapFlags::empty(),
)
.expect("failed to map shader storage buffer memory") };
println!("DATA INSIDE PARTICLES BUFFER #{}: {}", i, ParticlesList::from_raw_ptr(data as *const Particle, PARTICLE_COUNT as usize));
unsafe {
self.device
.unmap_memory(*memory);
}
}
//compute submission //compute submission
let mut submit_infos; let mut submit_infos;
@ -1816,46 +1913,20 @@ impl VulkanApp for App {
.reset_command_buffer(self.compute_command_buffers[self.current_frame], vk::CommandBufferResetFlags::empty()); .reset_command_buffer(self.compute_command_buffers[self.current_frame], vk::CommandBufferResetFlags::empty());
} }
self.record_compute_command_buffer(&self.device, self.compute_command_buffers[self.current_frame]); //RESET query pool for compute shader statistics
/*unsafe {
/*for i in 0..MAX_FRAMES_IN_FLIGHT { self.device
self.record_compute_command_buffer(&self.device, self.compute_command_buffers[i]); .cmd_reset_query_pool(
}*/ self.compute_command_buffers[self.current_frame],
self.query_pool,
/*for (i, memory) in (&self.shader_storage_buffers_memory).iter().enumerate() {
let mut data = unsafe { self.device
.map_memory(
*memory,
0, 0,
buffer_size, 1,
vk::MemoryMapFlags::empty(), );
)
.expect("failed to map shader storage buffer memory") };
println!("DATA INSIDE PARTICLES BUFFER #{}: {}", i, ParticlesList::from_raw_ptr(data as *const Particle, PARTICLE_COUNT as usize));
unsafe {
self.device
.unmap_memory(*memory);
}
}*/ }*/
self.record_compute_command_buffer(self.compute_command_buffers[self.current_frame]);
self.update_uniform_buffer(self.current_frame); self.update_uniform_buffer(self.current_frame);
unsafe {
self.device
.reset_fences(&[self.sync_objects.compute_inflight_fences[self.current_frame]]);
self.device
.reset_command_buffer(self.compute_command_buffers[self.current_frame], vk::CommandBufferResetFlags::empty());
}
//self.record_compute_command_buffer(&self.device, self.compute_command_buffers[self.current_frame]);
for i in 0..MAX_FRAMES_IN_FLIGHT {
self.record_compute_command_buffer(&self.device, self.compute_command_buffers[self.current_frame]);
}
submit_infos = [vk::SubmitInfo { submit_infos = [vk::SubmitInfo {
s_type: vk::StructureType::SUBMIT_INFO, s_type: vk::StructureType::SUBMIT_INFO,
p_next: ptr::null(), p_next: ptr::null(),
@ -1876,58 +1947,25 @@ impl VulkanApp for App {
); );
} }
/*log compute shader invocations
let mem_requirements = unsafe { self.device.get_buffer_memory_requirements(self.shader_storage_buffers[0]) }; unsafe {
println!("current frame: {}", self.current_frame); self.device.cmd_end_query(self.compute_command_buffers[self.current_frame], query_pool, 0);
}
for (i, memory) in (&self.shader_storage_buffers_memory).iter().enumerate() {
//if i != self.current_frame { continue; }
let is_current_buffer = i != self.current_frame;
let mut data = unsafe { self.device
.map_memory(
*memory,
0,
buffer_size,
vk::MemoryMapFlags::empty(),
)
.expect("failed to map shader storage buffer memory") };
let particles_list = ParticlesList::from_raw_ptr(data as *const Particle, PARTICLE_COUNT as usize);
let mut particles_vec = particles_list.0;
if !is_current_buffer {
particles_vec[0].color = (0.0, 0.0, 0.0, 0.0);
particles_vec[1].color = (0.0, 0.0, 0.0, 0.0);
particles_vec[2].color = (0.0, 0.0, 0.0, 0.0);
particles_vec[3].color = (0.0, 0.0, 0.0, 0.0);
particles_vec[4].color = (0.0, 0.0, 0.0, 0.0);
} else {
particles_vec[0].color = (1.0, 0.0, 1.0, 0.0);
particles_vec[1].color = (1.0, 0.0, 1.0, 0.0);
particles_vec[2].color = (1.0, 0.0, 1.0, 0.0);
particles_vec[3].color = (1.0, 0.0, 1.0, 0.0);
particles_vec[4].color = (1.0, 0.0, 1.0, 0.0);
}
let particles_slice_data = particles_vec.as_mut_slice();
let mut buffer_size: u64 = std::mem::size_of::<Particle>() as u64 * particles_slice_data.len() as u64;
unsafe {
let mut slice = Align::new(
data,
mem::align_of::<Particle>() as u64,
mem_requirements.size,
);
slice.copy_from_slice(&particles_slice_data);
}
//println!("DATA INSIDE PARTICLES BUFFER #{}: {}", i, ParticlesList::from_raw_ptr(data as *const Particle, PARTICLE_COUNT as usize)); let query_results = unsafe {
self.device.get_query_pool_results::<u32>(
query_pool,
0, // Starting query index
1, // Number of queries to retrieve (1 in this case)
data, // Results will be stored here
//0, // Query results stride (optional)
vk::QueryResultFlags::TYPE_64, // Flags specifying the type of query results
)
.expect("Failed to retrieve query pool results"
)};
unsafe { println!("Compute shader invocations: {:?}", data[0]);*/
self.device
.unmap_memory(*memory);
}
}
//graphics submission //graphics submission
@ -2035,6 +2073,24 @@ impl VulkanApp for App {
//println!("resized {}", self.is_framebuffer_resized); //println!("resized {}", self.is_framebuffer_resized);
//log compute shader invocations
/*unsafe {
self.device.cmd_end_query(self.compute_command_buffers[self.current_frame], self.query_pool, 0);
}*/
let query_results = unsafe {
self.device.get_query_pool_results::<u64>(
self.query_pool,
0, // Starting query index
1, // Number of queries to retrieve (1 in this case)
self.query_mapped, // Results will be stored here
//0, // Query results stride (optional)
vk::QueryResultFlags::TYPE_64, // Flags specifying the type of query results
)};
println!("Compute shader invocations: {:?}", self.query_mapped[0]);
self.current_frame = (self.current_frame + 1) % MAX_FRAMES_IN_FLIGHT; self.current_frame = (self.current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
} }

@ -17,8 +17,8 @@ pub const VALIDATION: ValidationInfo = ValidationInfo {
pub const DEVICE_EXTENSIONS: DeviceExtension = DeviceExtension { pub const DEVICE_EXTENSIONS: DeviceExtension = DeviceExtension {
names: ["VK_KHR_swapchain"], names: ["VK_KHR_swapchain"],
}; };
pub const MAX_FRAMES_IN_FLIGHT: usize = 4; pub const MAX_FRAMES_IN_FLIGHT: usize = 2;
pub const IS_PAINT_FPS_COUNTER: bool = true; pub const IS_PAINT_FPS_COUNTER: bool = false;
impl DeviceExtension { impl DeviceExtension {
pub fn get_extensions_raw_names(&self) -> [*const c_char; 1] { pub fn get_extensions_raw_names(&self) -> [*const c_char; 1] {

Loading…
Cancel
Save