used pipeline statistics to check compute shader invocations

working
Nathan Buck 8 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!")
}
pub struct App {
pub struct App<'a> {
pub window: winit::window::Window,
// vulkan stuff
@ -245,9 +245,13 @@ pub struct App {
pub last_time: f64,
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 {
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);
//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 {
window,
@ -381,6 +463,11 @@ impl App {
last_time: 0.0,
physical_device_memory_properties,
query_pool,
query_memory,
query_mapped,
}
}
@ -673,25 +760,35 @@ impl App {
fn record_compute_command_buffer(
&self,
device: &ash::Device,
&mut self,
command_buffer: vk::CommandBuffer
) {
let begin_info = vk::CommandBufferBeginInfo::default();
unsafe {
device
self.device
.begin_command_buffer(command_buffer, &begin_info)
.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(
command_buffer,
vk::PipelineBindPoint::COMPUTE,
self.compute_pipeline,
);
device
self.device
.cmd_bind_descriptor_sets(
command_buffer,
vk::PipelineBindPoint::COMPUTE,
@ -701,14 +798,33 @@ impl App {
&[],
);
device
self.device
.cmd_dispatch(
command_buffer,
(PARTICLE_COUNT / 256) as u32,
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)
.expect("failed ending compute command buffer");
}
@ -1012,6 +1128,7 @@ impl App {
let physical_device_features = vk::PhysicalDeviceFeatures {
sampler_anisotropy: vk::TRUE, // enable anisotropy device feature from Chapter-24.
pipeline_statistics_query: vk::TRUE,
..Default::default()
};
@ -1586,7 +1703,7 @@ impl App {
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 {
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) {
unsafe {
@ -1772,28 +1889,8 @@ impl VulkanApp for App {
}
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;
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
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());
}
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[i]);
}*/
/*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 {
//RESET query pool for compute shader statistics
/*unsafe {
self.device
.unmap_memory(*memory);
}
.cmd_reset_query_pool(
self.compute_command_buffers[self.current_frame],
self.query_pool,
0,
1,
);
}*/
self.record_compute_command_buffer(self.compute_command_buffers[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 {
s_type: vk::StructureType::SUBMIT_INFO,
p_next: ptr::null(),
@ -1876,58 +1947,25 @@ impl VulkanApp for App {
);
}
let mem_requirements = unsafe { self.device.get_buffer_memory_requirements(self.shader_storage_buffers[0]) };
println!("current frame: {}", self.current_frame);
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;
/*log compute shader invocations
unsafe {
let mut slice = Align::new(
data,
mem::align_of::<Particle>() as u64,
mem_requirements.size,
);
slice.copy_from_slice(&particles_slice_data);
self.device.cmd_end_query(self.compute_command_buffers[self.current_frame], query_pool, 0);
}
//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 {
self.device
.unmap_memory(*memory);
}
}
println!("Compute shader invocations: {:?}", data[0]);*/
//graphics submission
@ -2035,6 +2073,24 @@ impl VulkanApp for App {
//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;
}

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

Loading…
Cancel
Save