From 83e643c234a4f25ab632324ba1a849c757379f71 Mon Sep 17 00:00:00 2001 From: tomaka Date: Sat, 5 Aug 2017 10:33:30 +0200 Subject: [PATCH] Work on support for queries (#718) * Move query.rs to query/mod.rs * Remove genericity over Device * Replace device() with DeviceOwned impls * Add unsafe query methods to UnsafeCommandBufferBuilder --- vulkano/src/command_buffer/sys.rs | 60 ++++++++++++++ vulkano/src/{query.rs => query/mod.rs} | 110 +++++++++++++++++++++---- 2 files changed, 153 insertions(+), 17 deletions(-) rename vulkano/src/{query.rs => query/mod.rs} (82%) diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index b6790376..10da9711 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -46,6 +46,8 @@ use pipeline::input_assembly::IndexType; use pipeline::viewport::Scissor; use pipeline::viewport::Viewport; use query::QueryPipelineStatisticFlags; +use query::UnsafeQueriesRange; +use query::UnsafeQuery; use sampler::Filter; use sync::AccessFlagBits; use sync::Event; @@ -343,6 +345,19 @@ impl

UnsafeCommandBufferBuilder

{ } } + /// Calls `vkCmdBeginQuery` on the builder. + #[inline] + pub unsafe fn begin_query(&mut self, query: UnsafeQuery, precise: bool) { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + let flags = if precise { + vk::QUERY_CONTROL_PRECISE_BIT + } else { + 0 + }; + vk.CmdBeginQuery(cmd, query.pool().internal_object(), query.index(), flags); + } + /// Calls `vkCmdBeginRenderPass` on the builder. #[inline] pub unsafe fn begin_render_pass(&mut self, framebuffer: &F, @@ -893,6 +908,25 @@ impl

UnsafeCommandBufferBuilder

{ regions.as_ptr()); } + /// Calls `vkCmdCopyQueryPoolResults` on the builder. + #[inline] + pub unsafe fn copy_query_pool_results(&mut self, queries: UnsafeQueriesRange, + destination: &BufferAccess, stride: usize) + { + let destination = destination.inner(); + debug_assert!(destination.offset < destination.buffer.size()); + debug_assert!(destination.buffer.usage_transfer_destination()); + + let flags = 0; // FIXME: + + let vk = self.device().pointers(); + let cmd = self.internal_object(); + vk.CmdCopyQueryPoolResults(cmd, queries.pool().internal_object(), queries.first_index(), + queries.count(), destination.buffer.internal_object(), + destination.offset as vk::DeviceSize, + stride as vk::DeviceSize, flags); + } + /// Calls `vkCmdDispatch` on the builder. #[inline] pub unsafe fn dispatch(&mut self, dimensions: [u32; 3]) { @@ -997,6 +1031,14 @@ impl

UnsafeCommandBufferBuilder

{ stride); } + /// Calls `vkCmdEndQuery` on the builder. + #[inline] + pub unsafe fn end_query(&mut self, query: UnsafeQuery) { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + vk.CmdEndQuery(cmd, query.pool().internal_object(), query.index()); + } + /// Calls `vkCmdEndRenderPass` on the builder. #[inline] pub unsafe fn end_render_pass(&mut self) { @@ -1120,6 +1162,15 @@ impl

UnsafeCommandBufferBuilder

{ vk.CmdResetEvent(cmd, event.internal_object(), stages.into_vulkan_bits()); } + /// Calls `vkCmdResetQueryPool` on the builder. + #[inline] + pub unsafe fn reset_query_pool(&mut self, queries: UnsafeQueriesRange) { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + vk.CmdResetQueryPool(cmd, queries.pool().internal_object(), queries.first_index(), + queries.count()); + } + /// Calls `vkCmdSetBlendConstants` on the builder. #[inline] pub unsafe fn set_blend_constants(&mut self, constants: [f32; 4]) { @@ -1281,6 +1332,15 @@ impl

UnsafeCommandBufferBuilder

{ size as vk::DeviceSize, data as *const D as *const _); } + + /// Calls `vkCmdWriteTimestamp` on the builder. + #[inline] + pub unsafe fn write_timestamp(&mut self, query: UnsafeQuery, stages: PipelineStages) { + let vk = self.device().pointers(); + let cmd = self.internal_object(); + vk.CmdWriteTimestamp(cmd, stages.into_vulkan_bits(), query.pool().internal_object(), + query.index()); + } } unsafe impl

DeviceOwned for UnsafeCommandBufferBuilder

{ diff --git a/vulkano/src/query.rs b/vulkano/src/query/mod.rs similarity index 82% rename from vulkano/src/query.rs rename to vulkano/src/query/mod.rs index a288188d..c9559147 100644 --- a/vulkano/src/query.rs +++ b/vulkano/src/query/mod.rs @@ -20,28 +20,24 @@ use std::ptr; use std::sync::Arc; use device::Device; +use device::DeviceOwned; use Error; use OomError; -use SafeDeref; use VulkanObject; use check_errors; use vk; -pub struct UnsafeQueryPool

> - where P: SafeDeref -{ +pub struct UnsafeQueryPool { pool: vk::QueryPool, - device: P, + device: Arc, num_slots: u32, } -impl

UnsafeQueryPool

- where P: SafeDeref -{ +impl UnsafeQueryPool { /// Builds a new query pool. - pub fn new(device: P, ty: QueryType, num_slots: u32) - -> Result, QueryPoolCreationError> { + pub fn new(device: Arc, ty: QueryType, num_slots: u32) + -> Result { let (vk_ty, statistics) = match ty { QueryType::Occlusion => (vk::QUERY_TYPE_OCCLUSION, 0), QueryType::Timestamp => (vk::QUERY_TYPE_TIMESTAMP, 0), @@ -86,13 +82,94 @@ impl

UnsafeQueryPool

self.num_slots } - /// Returns the device used to create the pool. #[inline] - pub fn device(&self) -> &P { + pub fn query(&self, index: u32) -> Option { + if index < self.num_slots() { + Some(UnsafeQuery { + pool: self, + index, + }) + } else { + None + } + } + + /// + /// # Panic + /// + /// Panicks if `count` is 0. + #[inline] + pub fn queries_range(&self, first_index: u32, count: u32) -> Option { + assert!(count >= 1); + + if first_index + count < self.num_slots() { + Some(UnsafeQueriesRange { + pool: self, + first: first_index, + count, + }) + } else { + None + } + } +} + +unsafe impl VulkanObject for UnsafeQueryPool { + type Object = vk::QueryPool; + + #[inline] + fn internal_object(&self) -> vk::QueryPool { + self.pool + } +} + +unsafe impl DeviceOwned for UnsafeQueryPool { + #[inline] + fn device(&self) -> &Arc { &self.device } } +pub struct UnsafeQuery<'a> { + pool: &'a UnsafeQueryPool, + index: u32, +} + +impl<'a> UnsafeQuery<'a> { + #[inline] + pub fn pool(&self) -> &'a UnsafeQueryPool { + &self.pool + } + + #[inline] + pub fn index(&self) -> u32 { + self.index + } +} + +pub struct UnsafeQueriesRange<'a> { + pool: &'a UnsafeQueryPool, + first: u32, + count: u32, +} + +impl<'a> UnsafeQueriesRange<'a> { + #[inline] + pub fn pool(&self) -> &'a UnsafeQueryPool { + &self.pool + } + + #[inline] + pub fn first_index(&self) -> u32 { + self.first + } + + #[inline] + pub fn count(&self) -> u32 { + self.count + } +} + #[derive(Debug, Copy, Clone)] pub enum QueryType { Occlusion, @@ -174,9 +251,7 @@ impl Into for QueryPipelineStatisticFlags { } } -impl

Drop for UnsafeQueryPool

- where P: SafeDeref -{ +impl Drop for UnsafeQueryPool { #[inline] fn drop(&mut self) { unsafe { @@ -275,10 +350,11 @@ impl OcclusionQueriesPool { pub fn num_slots(&self) -> u32 { self.inner.num_slots() } +} - /// Returns the device that was used to create this pool. +unsafe impl DeviceOwned for OcclusionQueriesPool { #[inline] - pub fn device(&self) -> &Arc { + fn device(&self) -> &Arc { self.inner.device() } }