hal/vk: draws and dispatches. Refactor query set descriptor

This commit is contained in:
Dzmitry Malyshau 2021-06-16 14:17:37 -04:00
parent 1952ecb99c
commit c53addac8a
14 changed files with 257 additions and 38 deletions

View File

@ -2222,7 +2222,7 @@ impl<A: HalApi> Device<A> {
fn create_query_set(
&self,
self_id: id::DeviceId,
desc: &wgt::QuerySetDescriptor,
desc: &resource::QuerySetDescriptor,
) -> Result<resource::QuerySet<A>, resource::CreateQuerySetError> {
use resource::CreateQuerySetError as Error;
@ -2247,14 +2247,15 @@ impl<A: HalApi> Device<A> {
});
}
let hal_desc = desc.map_label(super::LabelHelpers::borrow_option);
Ok(resource::QuerySet {
raw: unsafe { self.raw.create_query_set(desc).unwrap() },
raw: unsafe { self.raw.create_query_set(&hal_desc).unwrap() },
device_id: Stored {
value: id::Valid(self_id),
ref_count: self.life_guard.add_ref(),
},
life_guard: LifeGuard::new(""),
desc: desc.clone(),
desc: desc.map_label(|_| ()),
})
}
}
@ -3636,7 +3637,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_create_query_set<A: HalApi>(
&self,
device_id: id::DeviceId,
desc: &wgt::QuerySetDescriptor,
desc: &resource::QuerySetDescriptor,
id_in: Input<G, id::QuerySetId>,
) -> (id::QuerySetId, Option<resource::CreateQuerySetError>) {
profiling::scope!("create_query_set", "Device");

View File

@ -98,7 +98,7 @@ pub enum Action<'a> {
DestroyRenderBundle(id::RenderBundleId),
CreateQuerySet {
id: id::QuerySetId,
desc: wgt::QuerySetDescriptor,
desc: crate::resource::QuerySetDescriptor<'a>,
},
DestroyQuerySet(id::QuerySetId),
WriteBuffer {

View File

@ -426,12 +426,14 @@ pub enum CreateQuerySetError {
MissingFeatures(#[from] MissingFeatures),
}
pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor<Label<'a>>;
#[derive(Debug)]
pub struct QuerySet<A: hal::Api> {
pub(crate) raw: A::QuerySet,
pub(crate) device_id: Stored<DeviceId>,
pub(crate) life_guard: LifeGuard,
pub(crate) desc: wgt::QuerySetDescriptor,
pub(crate) desc: wgt::QuerySetDescriptor<()>,
}
impl<A: hal::Api> Resource for QuerySet<A> {

View File

@ -194,7 +194,10 @@ impl crate::Device<Api> for Context {
}
unsafe fn destroy_compute_pipeline(&self, pipeline: Resource) {}
unsafe fn create_query_set(&self, desc: &wgt::QuerySetDescriptor) -> DeviceResult<Resource> {
unsafe fn create_query_set(
&self,
desc: &wgt::QuerySetDescriptor<crate::Label>,
) -> DeviceResult<Resource> {
Ok(Resource)
}
unsafe fn destroy_query_set(&self, set: Resource) {}

View File

@ -268,7 +268,7 @@ pub trait Device<A: Api>: Send + Sync {
unsafe fn create_query_set(
&self,
desc: &wgt::QuerySetDescriptor,
desc: &wgt::QuerySetDescriptor<Label>,
) -> Result<A::QuerySet, DeviceError>;
unsafe fn destroy_query_set(&self, set: A::QuerySet);
unsafe fn create_fence(&self) -> Result<A::Fence, DeviceError>;

View File

@ -850,7 +850,7 @@ impl crate::Device<super::Api> for super::Device {
unsafe fn create_query_set(
&self,
desc: &wgt::QuerySetDescriptor,
desc: &wgt::QuerySetDescriptor<crate::Label>,
) -> DeviceResult<super::QuerySet> {
match desc.ty {
wgt::QueryType::Occlusion => {
@ -858,7 +858,9 @@ impl crate::Device<super::Api> for super::Device {
let options = mtl::MTLResourceOptions::empty();
//TODO: HazardTrackingModeUntracked
let raw_buffer = self.shared.device.lock().new_buffer(size, options);
raw_buffer.set_label("_QuerySet");
if let Some(label) = desc.label {
raw_buffer.set_label(label);
}
Ok(super::QuerySet {
raw_buffer,
ty: desc.ty,
@ -900,7 +902,7 @@ impl crate::Device<super::Api> for super::Device {
let cmd_buf = match fence
.pending_command_buffers
.iter()
.find(|&&(value, _)| value == wait_value)
.find(|&&(value, _)| value >= wait_value)
{
Some(&(_, ref cmd_buf)) => cmd_buf,
None => {

View File

@ -777,17 +777,67 @@ impl crate::Adapter<super::Api> for super::Adapter {
}
unsafe fn close(&self, device: super::Device) {
for &raw in device.shared.render_passes.lock().values() {
device.shared.raw.destroy_render_pass(raw, None);
}
device.shared.raw.destroy_device(None);
device.shared.free_resources();
}
unsafe fn texture_format_capabilities(
&self,
format: wgt::TextureFormat,
) -> crate::TextureFormatCapability {
crate::TextureFormatCapability::empty()
use crate::TextureFormatCapability as Tfc;
let vk_format = self.private_caps.map_texture_format(format);
let properties = self
.instance
.raw
.get_physical_device_format_properties(self.raw, vk_format);
let features = properties.linear_tiling_features;
let mut flags = Tfc::empty();
flags.set(
Tfc::SAMPLED,
features.contains(vk::FormatFeatureFlags::SAMPLED_IMAGE),
);
flags.set(
Tfc::SAMPLED_LINEAR,
features.contains(vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_LINEAR),
);
flags.set(
Tfc::SAMPLED_MINMAX,
features.contains(vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_MINMAX),
);
flags.set(
Tfc::STORAGE | Tfc::STORAGE_READ_WRITE,
features.contains(vk::FormatFeatureFlags::STORAGE_IMAGE),
);
flags.set(
Tfc::STORAGE_ATOMIC,
features.contains(vk::FormatFeatureFlags::STORAGE_IMAGE_ATOMIC),
);
flags.set(
Tfc::COLOR_ATTACHMENT,
features.contains(vk::FormatFeatureFlags::COLOR_ATTACHMENT),
);
flags.set(
Tfc::COLOR_ATTACHMENT_BLEND,
features.contains(vk::FormatFeatureFlags::COLOR_ATTACHMENT_BLEND),
);
flags.set(
Tfc::DEPTH_STENCIL_ATTACHMENT,
features.contains(vk::FormatFeatureFlags::DEPTH_STENCIL_ATTACHMENT),
);
flags.set(
Tfc::COPY_SRC,
features.intersects(
vk::FormatFeatureFlags::TRANSFER_SRC | vk::FormatFeatureFlags::BLIT_SRC,
),
);
flags.set(
Tfc::COPY_DST,
features.intersects(
vk::FormatFeatureFlags::TRANSFER_DST | vk::FormatFeatureFlags::BLIT_DST,
),
);
flags
}
unsafe fn surface_capabilities(

View File

@ -1,7 +1,11 @@
use super::conv;
use arrayvec::ArrayVec;
use ash::{extensions::ext, version::DeviceV1_0, vk};
use ash::{
extensions::ext,
version::{DeviceV1_0, DeviceV1_2},
vk,
};
use inplace_it::inplace_or_alloc_from_iter;
use std::{ffi::CStr, mem, ops::Range, slice};
@ -56,6 +60,14 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
}
let raw = self.free.pop().unwrap();
// Set the name unconditionally, since there might be a
// previous name assigned to this.
self.device.set_object_name(
vk::ObjectType::COMMAND_BUFFER,
raw,
label.unwrap_or_default(),
);
let vk_info = vk::CommandBufferBeginInfo::builder()
.flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT)
.build();
@ -567,6 +579,13 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
start_instance: u32,
instance_count: u32,
) {
self.device.raw.cmd_draw(
self.active,
vertex_count,
instance_count,
start_vertex,
start_instance,
);
}
unsafe fn draw_indexed(
&mut self,
@ -576,6 +595,14 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
start_instance: u32,
instance_count: u32,
) {
self.device.raw.cmd_draw_indexed(
self.active,
index_count,
instance_count,
start_index,
base_vertex,
start_instance,
);
}
unsafe fn draw_indirect(
&mut self,
@ -583,6 +610,9 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
offset: wgt::BufferAddress,
draw_count: u32,
) {
self.device
.raw
.cmd_draw_indirect(self.active, buffer.raw, offset, draw_count, 0);
}
unsafe fn draw_indexed_indirect(
&mut self,
@ -590,6 +620,9 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
offset: wgt::BufferAddress,
draw_count: u32,
) {
self.device
.raw
.cmd_draw_indexed_indirect(self.active, buffer.raw, offset, draw_count, 0);
}
unsafe fn draw_indirect_count(
&mut self,
@ -599,6 +632,36 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
count_offset: wgt::BufferAddress,
max_count: u32,
) {
match self
.device
.extension_fns
.draw_indirect_count
.as_ref()
.expect("Feature `DRAW_INDIRECT_COUNT` must be enabled")
{
super::ExtensionFn::Extension(t) => {
t.cmd_draw_indirect_count(
self.active,
buffer.raw,
offset,
count_buffer.raw,
count_offset,
max_count,
0,
);
}
super::ExtensionFn::Promoted => {
self.device.raw.cmd_draw_indirect_count(
self.active,
buffer.raw,
offset,
count_buffer.raw,
count_offset,
max_count,
0,
);
}
}
}
unsafe fn draw_indexed_indirect_count(
&mut self,
@ -608,14 +671,47 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
count_offset: wgt::BufferAddress,
max_count: u32,
) {
match self
.device
.extension_fns
.draw_indirect_count
.as_ref()
.expect("Feature `DRAW_INDIRECT_COUNT` must be enabled")
{
super::ExtensionFn::Extension(t) => {
t.cmd_draw_indexed_indirect_count(
self.active,
buffer.raw,
offset,
count_buffer.raw,
count_offset,
max_count,
0,
);
}
super::ExtensionFn::Promoted => {
self.device.raw.cmd_draw_indexed_indirect_count(
self.active,
buffer.raw,
offset,
count_buffer.raw,
count_offset,
max_count,
0,
);
}
}
}
// compute
unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {
self.bind_point = vk::PipelineBindPoint::COMPUTE;
self.begin_debug_marker(desc.label.unwrap_or_default());
}
unsafe fn end_compute_pass(&mut self) {
self.end_debug_marker();
}
unsafe fn end_compute_pass(&mut self) {}
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
self.device.raw.cmd_bind_pipeline(
@ -625,8 +721,16 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
);
}
unsafe fn dispatch(&mut self, count: [u32; 3]) {}
unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) {}
unsafe fn dispatch(&mut self, count: [u32; 3]) {
self.device
.raw
.cmd_dispatch(self.active, count[0], count[1], count[2]);
}
unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) {
self.device
.raw
.cmd_dispatch_indirect(self.active, buffer.raw, offset)
}
}
#[test]

View File

@ -8,7 +8,7 @@ use parking_lot::Mutex;
use std::{cmp, collections::hash_map::Entry, ffi::CString, ptr, sync::Arc};
impl super::DeviceShared {
unsafe fn set_object_name(
pub(super) unsafe fn set_object_name(
&self,
object_type: vk::ObjectType,
object: impl vk::Handle,
@ -121,6 +121,8 @@ impl super::DeviceShared {
.samples(samples)
.load_op(load_op)
.store_op(store_op)
.stencil_load_op(stencil_load_op)
.stencil_store_op(stencil_store_op)
.initial_layout(ds.base.layout_pre)
.final_layout(ds.base.layout_post)
.build();
@ -216,6 +218,16 @@ impl super::DeviceShared {
}
})
}
pub(super) unsafe fn free_resources(&self) {
for &raw in self.render_passes.lock().values() {
self.raw.destroy_render_pass(raw, None);
}
for &raw in self.framebuffers.lock().values() {
self.raw.destroy_framebuffer(raw, None);
}
self.raw.destroy_device(None);
}
}
impl gpu_alloc::MemoryDevice<vk::DeviceMemory> for super::DeviceShared {
@ -741,6 +753,15 @@ impl crate::Device<super::Api> for super::Device {
})
}
unsafe fn destroy_texture_view(&self, view: super::TextureView) {
if !self.shared.private_caps.imageless_framebuffers {
let mut fbuf_lock = self.shared.framebuffers.lock();
for (key, &raw_fbuf) in fbuf_lock.iter() {
if key.attachments.iter().any(|at| at.raw == view.raw) {
self.shared.raw.destroy_framebuffer(raw_fbuf, None);
}
}
fbuf_lock.retain(|key, _| !key.attachments.iter().any(|at| at.raw == view.raw));
}
self.shared.raw.destroy_image_view(view.raw, None);
}
@ -963,6 +984,11 @@ impl crate::Device<super::Api> for super::Device {
)?;
let set = vk_sets.pop().unwrap();
if let Some(label) = desc.label {
self.shared
.set_object_name(vk::ObjectType::DESCRIPTOR_SET, *set.raw(), label);
}
let mut writes = Vec::with_capacity(desc.entries.len());
let mut buffer_infos = Vec::with_capacity(desc.buffers.len());
let mut sampler_infos = Vec::with_capacity(desc.samplers.len());
@ -1037,6 +1063,11 @@ impl crate::Device<super::Api> for super::Device {
.create_shader_module(&vk_info, None)
.map_err(crate::DeviceError::from)?;
if let Some(label) = desc.label {
self.shared
.set_object_name(vk::ObjectType::SHADER_MODULE, raw, label);
}
Ok(super::ShaderModule { raw })
}
unsafe fn destroy_shader_module(&self, module: super::ShaderModule) {
@ -1188,8 +1219,8 @@ impl crate::Device<super::Api> for super::Device {
.src_color_blend_factor(color_src)
.dst_color_blend_factor(color_dst)
.alpha_blend_op(alpha_op)
.src_alpha_blend_factor(color_src)
.dst_alpha_blend_factor(color_dst);
.src_alpha_blend_factor(alpha_src)
.dst_alpha_blend_factor(alpha_dst);
}
vk_attachments.push(vk_attachment.build());
}
@ -1229,9 +1260,13 @@ impl crate::Device<super::Api> for super::Device {
.create_graphics_pipelines(vk::PipelineCache::null(), &vk_infos, None)
.map_err(|(_, e)| crate::DeviceError::from(e))?;
Ok(super::RenderPipeline {
raw: raw_vec.pop().unwrap(),
})
let raw = raw_vec.pop().unwrap();
if let Some(label) = desc.label {
self.shared
.set_object_name(vk::ObjectType::PIPELINE, raw, label);
}
Ok(super::RenderPipeline { raw })
}
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
self.shared.raw.destroy_pipeline(pipeline.raw, None);
@ -1261,9 +1296,13 @@ impl crate::Device<super::Api> for super::Device {
.create_compute_pipelines(vk::PipelineCache::null(), &vk_infos, None)
.map_err(|(_, e)| crate::DeviceError::from(e))?;
Ok(super::ComputePipeline {
raw: raw_vec.pop().unwrap(),
})
let raw = raw_vec.pop().unwrap();
if let Some(label) = desc.label {
self.shared
.set_object_name(vk::ObjectType::PIPELINE, raw, label);
}
Ok(super::ComputePipeline { raw })
}
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
self.shared.raw.destroy_pipeline(pipeline.raw, None);
@ -1271,7 +1310,7 @@ impl crate::Device<super::Api> for super::Device {
unsafe fn create_query_set(
&self,
desc: &wgt::QuerySetDescriptor,
desc: &wgt::QuerySetDescriptor<crate::Label>,
) -> Result<super::QuerySet, crate::DeviceError> {
let (vk_type, pipeline_statistics) = match desc.ty {
wgt::QueryType::Occlusion => (
@ -1295,6 +1334,11 @@ impl crate::Device<super::Api> for super::Device {
.build();
let raw = self.shared.raw.create_query_pool(&vk_info, None)?;
if let Some(label) = desc.label {
self.shared
.set_object_name(vk::ObjectType::QUERY_POOL, raw, label);
}
Ok(super::QuerySet { raw })
}
unsafe fn destroy_query_set(&self, set: super::QuerySet) {

View File

@ -1,5 +1,3 @@
#![allow(unused_variables)]
mod adapter;
mod command;
mod conv;

View File

@ -3052,7 +3052,9 @@ pub enum SamplerBorderColor {
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct QuerySetDescriptor {
pub struct QuerySetDescriptor<L> {
/// Debug label for the query set.
pub label: L,
/// Kind of query that this query set should contain.
pub ty: QueryType,
/// Total count of queries the set contains. Must not be zero.
@ -3060,6 +3062,17 @@ pub struct QuerySetDescriptor {
pub count: u32,
}
impl<L> QuerySetDescriptor<L> {
///
pub fn map_label<'a, K>(&'a self, fun: impl FnOnce(&'a L) -> K) -> QuerySetDescriptor<K> {
QuerySetDescriptor {
label: fun(&self.label),
ty: self.ty,
count: self.count,
}
}
}
/// Type of query contained in a QuerySet.
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]

View File

@ -1207,12 +1207,12 @@ impl crate::Context for Context {
fn device_create_query_set(
&self,
device: &Self::DeviceId,
desc: &wgt::QuerySetDescriptor,
desc: &wgt::QuerySetDescriptor<Label>,
) -> Self::QuerySetId {
let global = &self.0;
let (id, error) = wgc::gfx_select!(device.id => global.device_create_query_set(
device.id,
&desc,
&desc.map_label(|l| l.map(Borrowed)),
PhantomData
));
if let Some(cause) = error {

View File

@ -1490,7 +1490,7 @@ impl crate::Context for Context {
fn device_create_query_set(
&self,
_device: &Self::DeviceId,
_desc: &wgt::QuerySetDescriptor,
_desc: &wgt::QuerySetDescriptor<crate::Label>,
) -> Self::QuerySetId {
()
}

View File

@ -32,8 +32,8 @@ pub use wgt::{
DownlevelFlags, DynamicOffset, Extent3d, Face, Features, FilterMode, FrontFace,
ImageDataLayout, IndexFormat, InputStepMode, Limits, MultisampleState, Origin3d,
PipelineStatisticsTypes, PolygonMode, PowerPreference, PresentMode, PrimitiveState,
PrimitiveTopology, PushConstantRange, QuerySetDescriptor, QueryType, SamplerBorderColor,
ShaderLocation, ShaderModel, ShaderStage, StencilFaceState, StencilOperation, StencilState,
PrimitiveTopology, PushConstantRange, QueryType, SamplerBorderColor, ShaderLocation,
ShaderModel, ShaderStage, StencilFaceState, StencilOperation, StencilState,
StorageTextureAccess, SwapChainDescriptor, SwapChainStatus, TextureAspect, TextureDimension,
TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType,
TextureUsage, TextureViewDimension, VertexAttribute, VertexFormat, BIND_BUFFER_ALIGNMENT,
@ -1078,6 +1078,8 @@ pub type CommandEncoderDescriptor<'a> = wgt::CommandEncoderDescriptor<Label<'a>>
pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Label<'a>>;
/// Describes a [`Texture`].
pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>>;
/// Describes a [`QuerySet`].
pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor<Label<'a>>;
/// Describes a [`TextureView`].
#[derive(Clone, Debug, Default, PartialEq)]