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
This commit is contained in:
tomaka 2017-08-05 10:33:30 +02:00 committed by GitHub
parent 9e65c250e1
commit 83e643c234
2 changed files with 153 additions and 17 deletions

View File

@ -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<P> UnsafeCommandBufferBuilder<P> {
}
}
/// 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<F, I>(&mut self, framebuffer: &F,
@ -893,6 +908,25 @@ impl<P> UnsafeCommandBufferBuilder<P> {
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<P> UnsafeCommandBufferBuilder<P> {
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<P> UnsafeCommandBufferBuilder<P> {
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<P> UnsafeCommandBufferBuilder<P> {
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<P> DeviceOwned for UnsafeCommandBufferBuilder<P> {

View File

@ -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<P = Arc<Device>>
where P: SafeDeref<Target = Device>
{
pub struct UnsafeQueryPool {
pool: vk::QueryPool,
device: P,
device: Arc<Device>,
num_slots: u32,
}
impl<P> UnsafeQueryPool<P>
where P: SafeDeref<Target = Device>
{
impl UnsafeQueryPool {
/// Builds a new query pool.
pub fn new(device: P, ty: QueryType, num_slots: u32)
-> Result<UnsafeQueryPool<P>, QueryPoolCreationError> {
pub fn new(device: Arc<Device>, ty: QueryType, num_slots: u32)
-> Result<UnsafeQueryPool, QueryPoolCreationError> {
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<P> UnsafeQueryPool<P>
self.num_slots
}
/// Returns the device used to create the pool.
#[inline]
pub fn device(&self) -> &P {
pub fn query(&self, index: u32) -> Option<UnsafeQuery> {
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<UnsafeQueriesRange> {
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<Device> {
&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<vk::QueryPipelineStatisticFlags> for QueryPipelineStatisticFlags {
}
}
impl<P> Drop for UnsafeQueryPool<P>
where P: SafeDeref<Target = Device>
{
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<Device> {
fn device(&self) -> &Arc<Device> {
self.inner.device()
}
}