hal/vk: render passes and queries

This commit is contained in:
Dzmitry Malyshau
2021-06-16 01:26:14 -04:00
parent 6f655e0b14
commit bc6bb0c3df
6 changed files with 304 additions and 17 deletions

View File

@@ -715,6 +715,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
let family_index = 0; //TODO
let raw_queue = raw_device.get_device_queue(family_index, 0);
let shared = Arc::new(super::DeviceShared {
raw: raw_device,
instance: Arc::clone(&self.instance),
@@ -727,6 +728,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
private_caps: self.private_caps.clone(),
_timestamp_period: self.phd_capabilities.properties.limits.timestamp_period,
render_passes: Mutex::new(Default::default()),
framebuffers: Mutex::new(Default::default()),
});
let queue = super::Queue {
raw: raw_queue,

View File

@@ -1,9 +1,10 @@
use super::conv;
use arrayvec::ArrayVec;
use ash::{version::DeviceV1_0, vk};
use inplace_it::inplace_or_alloc_from_iter;
use std::ops::Range;
use std::{mem, ops::Range};
const ALLOCATION_GRANULARITY: u32 = 16;
const DST_IMAGE_LAYOUT: vk::ImageLayout = vk::ImageLayout::TRANSFER_DST_OPTIMAL;
@@ -267,10 +268,33 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
});
}
unsafe fn begin_query(&mut self, set: &super::QuerySet, index: u32) {}
unsafe fn end_query(&mut self, set: &super::QuerySet, index: u32) {}
unsafe fn write_timestamp(&mut self, set: &super::QuerySet, index: u32) {}
unsafe fn reset_queries(&mut self, set: &super::QuerySet, range: Range<u32>) {}
unsafe fn begin_query(&mut self, set: &super::QuerySet, index: u32) {
self.device.raw.cmd_begin_query(
self.active,
set.raw,
index,
vk::QueryControlFlags::empty(),
);
}
unsafe fn end_query(&mut self, set: &super::QuerySet, index: u32) {
self.device.raw.cmd_end_query(self.active, set.raw, index);
}
unsafe fn write_timestamp(&mut self, set: &super::QuerySet, index: u32) {
self.device.raw.cmd_write_timestamp(
self.active,
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
set.raw,
index,
);
}
unsafe fn reset_queries(&mut self, set: &super::QuerySet, range: Range<u32>) {
self.device.raw.cmd_reset_query_pool(
self.active,
set.raw,
range.start,
range.end - range.start,
);
}
unsafe fn copy_query_results(
&mut self,
set: &super::QuerySet,
@@ -278,12 +302,96 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
buffer: &super::Buffer,
offset: wgt::BufferAddress,
) {
self.device.raw.cmd_copy_query_pool_results(
self.active,
set.raw,
range.start,
range.end - range.start,
buffer.raw,
offset,
0,
vk::QueryResultFlags::TYPE_64 | vk::QueryResultFlags::WAIT,
);
}
// render
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {}
unsafe fn end_render_pass(&mut self) {}
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {
let mut vk_clear_values = ArrayVec::<[vk::ClearValue; super::MAX_TOTAL_ATTACHMENTS]>::new();
let mut vk_image_views = ArrayVec::<[vk::ImageView; super::MAX_TOTAL_ATTACHMENTS]>::new();
let mut rp_key = super::RenderPassKey::default();
let mut fb_key = super::FramebufferKey::default();
let caps = &self.device.private_caps;
for cat in desc.color_attachments {
vk_clear_values.push(vk::ClearValue {
color: cat.make_vk_clear_color(),
});
vk_image_views.push(cat.target.view.raw);
rp_key.colors.push(super::ColorAttachmentKey {
base: cat.target.make_attachment_key(cat.ops, caps),
resolve: cat
.resolve_target
.as_ref()
.map(|target| target.make_attachment_key(crate::AttachmentOp::STORE, caps)),
});
fb_key.add(cat.target.view);
if let Some(ref at) = cat.resolve_target {
vk_clear_values.push(mem::zeroed());
vk_image_views.push(at.view.raw);
fb_key.add(at.view);
}
}
if let Some(ref ds) = desc.depth_stencil_attachment {
vk_clear_values.push(vk::ClearValue {
depth_stencil: vk::ClearDepthStencilValue {
depth: ds.clear_value.0,
stencil: ds.clear_value.1,
},
});
vk_image_views.push(ds.target.view.raw);
rp_key.depth_stencil = Some(super::DepthStencilAttachmentKey {
base: ds.target.make_attachment_key(ds.depth_ops, caps),
stencil_ops: ds.stencil_ops,
});
fb_key.add(ds.target.view);
}
rp_key.sample_count = fb_key.sample_count;
let render_area = vk::Rect2D {
offset: vk::Offset2D { x: 0, y: 0 },
extent: vk::Extent2D {
width: fb_key.extent.width,
height: fb_key.extent.height,
},
};
let raw_pass = self.device.make_render_pass(rp_key).unwrap();
let raw_framebuffer = self
.device
.make_framebuffer(fb_key, raw_pass, desc.label)
.unwrap();
let mut vk_attachment_info = vk::RenderPassAttachmentBeginInfo::builder()
.attachments(&vk_image_views)
.build();
let mut vk_info = vk::RenderPassBeginInfo::builder()
.render_pass(raw_pass)
.render_area(render_area)
.clear_values(&vk_clear_values)
.framebuffer(raw_framebuffer);
if caps.imageless_framebuffers {
vk_info = vk_info.push_next(&mut vk_attachment_info);
}
self.device
.raw
.cmd_begin_render_pass(self.active, &vk_info, vk::SubpassContents::INLINE);
}
unsafe fn end_render_pass(&mut self) {
self.device.raw.cmd_end_render_pass(self.active);
}
unsafe fn set_bind_group(
&mut self,

View File

@@ -110,6 +110,48 @@ impl super::PrivateCapabilities {
}
}
impl crate::Attachment<'_, super::Api> {
pub(super) fn make_attachment_key(
&self,
ops: crate::AttachmentOp,
caps: &super::PrivateCapabilities,
) -> super::AttachmentKey {
super::AttachmentKey {
format: caps.map_texture_format(self.view.attachment.view_format),
layout_pre: derive_image_layout(self.boundary_usage.start),
layout_in: derive_image_layout(self.usage),
layout_post: derive_image_layout(self.boundary_usage.end),
ops,
}
}
}
impl crate::ColorAttachment<'_, super::Api> {
pub(super) unsafe fn make_vk_clear_color(&self) -> vk::ClearColorValue {
let cv = &self.clear_value;
match self
.target
.view
.attachment
.view_format
.describe()
.sample_type
{
wgt::TextureSampleType::Float { .. } | wgt::TextureSampleType::Depth => {
vk::ClearColorValue {
float32: [cv.r as f32, cv.g as f32, cv.b as f32, cv.a as f32],
}
}
wgt::TextureSampleType::Sint => vk::ClearColorValue {
int32: [cv.r as i32, cv.g as i32, cv.b as i32, cv.a as i32],
},
wgt::TextureSampleType::Uint => vk::ClearColorValue {
uint32: [cv.r as u32, cv.g as u32, cv.b as u32, cv.a as u32],
},
}
}
}
pub fn derive_image_layout(usage: crate::TextureUse) -> vk::ImageLayout {
match usage {
crate::TextureUse::COPY_SRC => vk::ImageLayout::TRANSFER_SRC_OPTIMAL,

View File

@@ -5,7 +5,7 @@ use ash::{extensions::khr, version::DeviceV1_0, vk};
use inplace_it::inplace_or_alloc_from_iter;
use parking_lot::Mutex;
use std::{collections::hash_map::Entry, ffi::CString, ptr, sync::Arc};
use std::{cmp, collections::hash_map::Entry, ffi::CString, ptr, sync::Arc};
impl super::DeviceShared {
unsafe fn set_object_name(
@@ -148,6 +148,74 @@ impl super::DeviceShared {
}
})
}
pub fn make_framebuffer(
&self,
key: super::FramebufferKey,
raw_pass: vk::RenderPass,
pass_label: crate::Label,
) -> Result<vk::Framebuffer, crate::DeviceError> {
Ok(match self.framebuffers.lock().entry(key) {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
let vk_views = e
.key()
.attachments
.iter()
.map(|at| at.raw)
.collect::<ArrayVec<[_; super::MAX_TOTAL_ATTACHMENTS]>>();
let vk_view_formats = e
.key()
.attachments
.iter()
.map(|at| self.private_caps.map_texture_format(at.view_format))
.collect::<ArrayVec<[_; super::MAX_TOTAL_ATTACHMENTS]>>();
let vk_image_infos = e
.key()
.attachments
.iter()
.enumerate()
.map(|(i, at)| {
vk::FramebufferAttachmentImageInfo::builder()
.usage(conv::map_texture_usage(at.texture_usage))
.flags(at.raw_image_flags)
.width(e.key().extent.width)
.height(e.key().extent.height)
.layer_count(e.key().extent.depth_or_array_layers)
.view_formats(&vk_view_formats[i..i + 1])
.build()
})
.collect::<ArrayVec<[_; super::MAX_TOTAL_ATTACHMENTS]>>();
let mut vk_attachment_info = vk::FramebufferAttachmentsCreateInfo::builder()
.attachment_image_infos(&vk_image_infos)
.build();
let mut vk_info = vk::FramebufferCreateInfo::builder()
.render_pass(raw_pass)
.width(e.key().extent.width)
.height(e.key().extent.height)
.layers(e.key().extent.depth_or_array_layers);
if self.private_caps.imageless_framebuffers {
//TODO: https://github.com/MaikKlein/ash/issues/450
vk_info = vk_info
.flags(vk::FramebufferCreateFlags::IMAGELESS_KHR)
.push_next(&mut vk_attachment_info);
vk_info.attachment_count = e.key().attachments.len() as u32;
} else {
vk_info = vk_info.attachments(&vk_views);
}
*e.insert(unsafe {
let raw = self.raw.create_framebuffer(&vk_info, None).unwrap();
if let Some(label) = pass_label {
self.set_object_name(vk::ObjectType::FRAMEBUFFER, raw, label);
}
raw
})
}
})
}
}
impl gpu_alloc::MemoryDevice<vk::DeviceMemory> for super::DeviceShared {
@@ -432,7 +500,7 @@ impl super::Device {
device: Arc::clone(&self.shared),
fence,
images,
format: config.format,
config: config.clone(),
})
}
}
@@ -562,13 +630,13 @@ impl crate::Device<super::Api> for super::Device {
desc: &crate::TextureDescriptor,
) -> Result<super::Texture, crate::DeviceError> {
let (array_layer_count, vk_extent) = conv::map_extent(desc.size, desc.dimension);
let mut flags = vk::ImageCreateFlags::empty();
let mut raw_flags = vk::ImageCreateFlags::empty();
if desc.dimension == wgt::TextureDimension::D2 && desc.size.depth_or_array_layers % 6 == 0 {
flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
raw_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
}
let vk_info = vk::ImageCreateInfo::builder()
.flags(flags)
.flags(raw_flags)
.image_type(conv::map_texture_dimension(desc.dimension))
.format(self.shared.private_caps.map_texture_format(desc.format))
.extent(vk_extent)
@@ -605,9 +673,13 @@ impl crate::Device<super::Api> for super::Device {
Ok(super::Texture {
raw,
block: Some(block),
usage: desc.usage,
dim: desc.dimension,
aspects: crate::FormatAspect::from(desc.format),
format_info: desc.format.describe(),
sample_count: desc.sample_count,
size: desc.size,
raw_flags,
})
}
unsafe fn destroy_texture(&self, texture: super::Texture) {
@@ -627,7 +699,6 @@ impl crate::Device<super::Api> for super::Device {
.image(texture.raw)
.view_type(conv::map_view_dimension(desc.dimension))
.format(self.shared.private_caps.map_texture_format(desc.format))
//.components(conv::map_swizzle(swizzle))
.subresource_range(conv::map_subresource_range(&desc.range, texture.aspects));
let mut image_view_info;
@@ -645,7 +716,29 @@ impl crate::Device<super::Api> for super::Device {
.set_object_name(vk::ObjectType::IMAGE_VIEW, raw, label);
}
Ok(super::TextureView { raw })
let attachment = super::FramebufferAttachment {
raw: if self.shared.private_caps.imageless_framebuffers {
vk::ImageView::null()
} else {
raw
},
texture_usage: texture.usage,
raw_image_flags: texture.raw_flags,
view_format: desc.format,
};
let sample_count = texture.sample_count;
let render_size = wgt::Extent3d {
width: cmp::max(1, texture.size.width >> desc.range.base_mip_level),
height: cmp::max(1, texture.size.height >> desc.range.base_mip_level),
depth_or_array_layers: 1,
};
Ok(super::TextureView {
raw,
attachment,
sample_count,
render_size,
})
}
unsafe fn destroy_texture_view(&self, view: super::TextureView) {
self.shared.raw.destroy_image_view(view.raw, None);
@@ -735,7 +828,7 @@ impl crate::Device<super::Api> for super::Device {
let mut types = Vec::new();
for entry in desc.entries {
let count = entry.count.map_or(1, |c| c.get());
if entry.binding as usize > types.len() {
if entry.binding as usize >= types.len() {
types.resize(
entry.binding as usize + 1,
vk::DescriptorType::INPUT_ATTACHMENT,

View File

@@ -639,9 +639,13 @@ impl crate::Surface<super::Api> for super::Surface {
texture: super::Texture {
raw: sc.images[index as usize],
block: None,
usage: sc.config.usage,
dim: wgt::TextureDimension::D2,
aspects: crate::FormatAspect::COLOR,
format_info: sc.format.describe(),
format_info: sc.config.format.describe(),
sample_count: 1,
size: sc.config.extent,
raw_flags: vk::ImageCreateFlags::empty(),
},
};
Ok(Some(crate::AcquiredSurfaceTexture {

View File

@@ -17,6 +17,7 @@ use ash::{
use parking_lot::Mutex;
const MILLIS_TO_NANOS: u64 = 1_000_000;
const MAX_TOTAL_ATTACHMENTS: usize = crate::MAX_COLOR_TARGETS * 2 + 1;
#[derive(Clone)]
pub struct Api;
@@ -72,7 +73,7 @@ struct Swapchain {
device: Arc<DeviceShared>,
fence: vk::Fence,
images: Vec<vk::Image>,
format: wgt::TextureFormat,
config: crate::SurfaceConfiguration,
}
pub struct Surface {
@@ -172,6 +173,35 @@ struct RenderPassKey {
sample_count: u32,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
struct FramebufferAttachment {
/// Can be NULL if the framebuffer is image-less
raw: vk::ImageView,
texture_usage: crate::TextureUse,
raw_image_flags: vk::ImageCreateFlags,
view_format: wgt::TextureFormat,
}
#[derive(Clone, Eq, Default, Hash, PartialEq)]
struct FramebufferKey {
attachments: ArrayVec<[FramebufferAttachment; MAX_TOTAL_ATTACHMENTS]>,
extent: wgt::Extent3d,
sample_count: u32,
}
impl FramebufferKey {
fn add(&mut self, view: &TextureView) {
self.extent.width = self.extent.width.max(view.render_size.width);
self.extent.height = self.extent.height.max(view.render_size.height);
self.extent.depth_or_array_layers = self
.extent
.depth_or_array_layers
.max(view.render_size.depth_or_array_layers);
self.sample_count = self.sample_count.max(view.sample_count);
self.attachments.push(view.attachment.clone());
}
}
struct DeviceShared {
raw: ash::Device,
instance: Arc<InstanceShared>,
@@ -182,6 +212,7 @@ struct DeviceShared {
downlevel_flags: wgt::DownlevelFlags,
private_caps: PrivateCapabilities,
render_passes: Mutex<fxhash::FxHashMap<RenderPassKey, vk::RenderPass>>,
framebuffers: Mutex<fxhash::FxHashMap<FramebufferKey, vk::Framebuffer>>,
}
pub struct Device {
@@ -210,14 +241,21 @@ pub struct Buffer {
pub struct Texture {
raw: vk::Image,
block: Option<gpu_alloc::MemoryBlock<vk::DeviceMemory>>,
usage: crate::TextureUse,
dim: wgt::TextureDimension,
aspects: crate::FormatAspect,
format_info: wgt::TextureFormatInfo,
sample_count: u32,
size: wgt::Extent3d,
raw_flags: vk::ImageCreateFlags,
}
#[derive(Debug)]
pub struct TextureView {
raw: vk::ImageView,
attachment: FramebufferAttachment,
sample_count: u32,
render_size: wgt::Extent3d,
}
#[derive(Debug)]