mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
hal/vk: render passes and queries
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)]
|
||||
|
||||
Reference in New Issue
Block a user