hal/vk: polishing to run halmark with no validation issues

This commit is contained in:
Dzmitry Malyshau 2021-06-16 17:15:34 -04:00
parent c53addac8a
commit fb662dfbec
11 changed files with 212 additions and 107 deletions

1
Cargo.lock generated
View File

@ -1997,6 +1997,7 @@ dependencies = [
"bitflags",
"block",
"core-graphics-types",
"env_logger",
"foreign-types",
"fxhash",
"gpu-alloc",

View File

@ -56,4 +56,5 @@ tag = "gfx-25"
features = ["wgsl-in"]
[dev-dependencies]
env_logger = "0.8"
winit = "0.24"

View File

@ -36,13 +36,17 @@ struct UsedResources<A: hal::Api> {
#[allow(dead_code)]
struct Example<A: hal::Api> {
instance: A::Instance,
adapter: A::Adapter,
surface: A::Surface,
surface_format: wgt::TextureFormat,
device: A::Device,
queue: A::Queue,
global_group: A::BindGroup,
local_group: A::BindGroup,
global_group_layout: A::BindGroupLayout,
local_group_layout: A::BindGroupLayout,
pipeline_layout: A::PipelineLayout,
shader: A::ShaderModule,
pipeline: A::RenderPipeline,
bunnies: Vec<Locals>,
local_buffer: A::Buffer,
@ -67,15 +71,20 @@ impl<A: hal::Api> Example<A> {
let instance = unsafe { A::Instance::init(&instance_desc)? };
let mut surface = unsafe { instance.create_surface(window).unwrap() };
let hal::OpenDevice { device, mut queue } = unsafe {
let adapters = instance.enumerate_adapters();
let exposed = adapters.get(0).ok_or(hal::InstanceError)?;
let adapter = unsafe {
let mut adapters = instance.enumerate_adapters();
if adapters.is_empty() {
return Err(hal::InstanceError);
}
let exposed = adapters.swap_remove(0);
println!(
"Surface caps: {:?}",
exposed.adapter.surface_capabilities(&surface)
);
exposed.adapter.open(wgt::Features::empty()).unwrap()
exposed.adapter
};
let hal::OpenDevice { device, mut queue } =
unsafe { adapter.open(wgt::Features::empty()).unwrap() };
let window_size: (u32, u32) = window.inner_size().into();
let surface_config = hal::SurfaceConfiguration {
@ -151,7 +160,7 @@ impl<A: hal::Api> Example<A> {
],
};
let global_bind_group_layout =
let global_group_layout =
unsafe { device.create_bind_group_layout(&global_bgl_desc).unwrap() };
let local_bgl_desc = hal::BindGroupLayoutDescriptor {
@ -167,12 +176,12 @@ impl<A: hal::Api> Example<A> {
}],
label: None,
};
let local_bind_group_layout =
let local_group_layout =
unsafe { device.create_bind_group_layout(&local_bgl_desc).unwrap() };
let pipeline_layout_desc = hal::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[&global_bind_group_layout, &local_bind_group_layout],
bind_group_layouts: &[&global_group_layout, &local_group_layout],
push_constant_ranges: &[],
};
let pipeline_layout = unsafe {
@ -362,7 +371,7 @@ impl<A: hal::Api> Example<A> {
};
let global_group_desc = hal::BindGroupDescriptor {
label: Some("global"),
layout: &global_bind_group_layout,
layout: &global_group_layout,
buffers: &[global_buffer_binding],
samplers: &[&sampler],
textures: &[texture_binding],
@ -392,7 +401,7 @@ impl<A: hal::Api> Example<A> {
};
let local_group_desc = hal::BindGroupDescriptor {
label: Some("local"),
layout: &local_bind_group_layout,
layout: &local_group_layout,
buffers: &[local_buffer_binding],
samplers: &[],
textures: &[],
@ -418,12 +427,16 @@ impl<A: hal::Api> Example<A> {
instance,
surface,
surface_format: surface_config.format,
adapter,
device,
queue,
pipeline_layout,
shader,
pipeline,
global_group,
local_group,
global_group_layout,
local_group_layout,
bunnies: Vec::new(),
local_buffer,
global_buffer,
@ -439,6 +452,39 @@ impl<A: hal::Api> Example<A> {
})
}
fn exit(mut self) {
unsafe {
self.device.wait(&self.fence, self.fence_value, !0).unwrap();
let mut cmd_buffers = Vec::new();
for (_, old) in self.old_resources {
self.device.destroy_texture_view(old.view);
cmd_buffers.push(old.cmd_buf);
}
self.cmd_encoder.reset_all(cmd_buffers.into_iter());
self.surface.unconfigure(&self.device);
self.device.destroy_bind_group(self.local_group);
self.device.destroy_bind_group(self.global_group);
self.device.destroy_buffer(self.local_buffer);
self.device.destroy_buffer(self.global_buffer);
self.device.destroy_texture_view(self.view);
self.device.destroy_command_encoder(self.cmd_encoder);
self.device.destroy_fence(self.fence);
self.device.destroy_texture(self.texture);
self.device.destroy_sampler(self.sampler);
self.device.destroy_shader_module(self.shader);
self.device.destroy_render_pipeline(self.pipeline);
self.device
.destroy_bind_group_layout(self.local_group_layout);
self.device
.destroy_bind_group_layout(self.global_group_layout);
self.device.destroy_pipeline_layout(self.pipeline_layout);
self.adapter.close(self.device);
self.instance.destroy_surface(self.surface);
}
}
fn update(&mut self, event: winit::event::WindowEvent) {
if let winit::event::WindowEvent::KeyboardInput {
input:
@ -488,19 +534,21 @@ impl<A: hal::Api> Example<A> {
}
}
unsafe {
if !self.bunnies.is_empty() {
let size = self.bunnies.len() * wgt::BIND_BUFFER_ALIGNMENT as usize;
let mapping = self
.device
.map_buffer(&self.local_buffer, 0..size as wgt::BufferAddress)
.unwrap();
ptr::copy_nonoverlapping(
self.bunnies.as_ptr() as *const u8,
mapping.ptr.as_ptr(),
size,
);
assert!(mapping.is_coherent);
self.device.unmap_buffer(&self.local_buffer).unwrap();
unsafe {
let mapping = self
.device
.map_buffer(&self.local_buffer, 0..size as wgt::BufferAddress)
.unwrap();
ptr::copy_nonoverlapping(
self.bunnies.as_ptr() as *const u8,
mapping.ptr.as_ptr(),
size,
);
assert!(mapping.is_coherent);
self.device.unmap_buffer(&self.local_buffer).unwrap();
}
}
unsafe {
@ -600,6 +648,8 @@ type Api = hal::api::Vulkan;
type Api = hal::api::Empty;
fn main() {
env_logger::init();
let event_loop = winit::event_loop::EventLoop::new();
let window = winit::window::WindowBuilder::new()
.with_title("hal-bunnymark")
@ -607,7 +657,7 @@ fn main() {
.unwrap();
let example_result = Example::<Api>::init(&window);
let mut example = example_result.expect("Selected backend is not supported");
let mut example = Some(example_result.expect("Selected backend is not supported"));
let mut last_frame_inst = Instant::now();
let (mut frame_count, mut accum_time) = (0, 0.0);
@ -633,7 +683,7 @@ fn main() {
*control_flow = winit::event_loop::ControlFlow::Exit;
}
_ => {
example.update(event);
example.as_mut().unwrap().update(event);
}
},
winit::event::Event::RedrawRequested(_) => {
@ -650,7 +700,10 @@ fn main() {
frame_count = 0;
}
}
example.render();
example.as_mut().unwrap().render();
}
winit::event::Event::LoopDestroyed => {
example.take().unwrap().exit();
}
_ => {}
}

View File

@ -200,6 +200,7 @@ pub trait Device<A: Api>: Send + Sync {
/// The initial usage is `BufferUse::empty()`.
unsafe fn create_buffer(&self, desc: &BufferDescriptor) -> Result<A::Buffer, DeviceError>;
unsafe fn destroy_buffer(&self, buffer: A::Buffer);
//TODO: clarify if zero-sized mapping is allowed
unsafe fn map_buffer(
&self,
buffer: &A::Buffer,

View File

@ -58,12 +58,13 @@ impl PhysicalDeviceFeatures {
downlevel_flags: wgt::DownlevelFlags,
private_caps: &super::PrivateCapabilities,
) -> Self {
// This must follow the "Valid Usage" requirements of [`VkDeviceCreateInfo`](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkDeviceCreateInfo.html).
//TODO: make configurable
let rba = !(cfg!(target_os = "macos") || cfg!(target_os = "ios"));
Self {
// vk::PhysicalDeviceFeatures is a struct composed of Bool32's while
// Features is a bitfield so we need to map everything manually
core: vk::PhysicalDeviceFeatures::builder()
.robust_buffer_access(true) //TODO: make configurable
.robust_buffer_access(rba)
.independent_blend(true)
.sample_rate_shading(true)
.image_cube_array(
@ -642,9 +643,11 @@ impl crate::Adapter<super::Api> for super::Adapter {
});
// Create device
let family_index = 0; //TODO
let raw_device = {
let family_info = vk::DeviceQueueCreateInfo::builder()
.flags(vk::DeviceQueueCreateFlags::empty())
.queue_family_index(family_index)
.queue_priorities(&[1.0])
.build();
let family_infos = [family_info];
@ -690,11 +693,8 @@ impl crate::Adapter<super::Api> for super::Adapter {
let capabilities = [
spv::Capability::Shader,
spv::Capability::Matrix,
spv::Capability::InputAttachment,
spv::Capability::Sampled1D,
spv::Capability::Image1D,
spv::Capability::SampledBuffer,
spv::Capability::ImageBuffer,
spv::Capability::ImageQuery,
spv::Capability::DerivativeControl,
//TODO: fill out the rest
@ -712,8 +712,6 @@ impl crate::Adapter<super::Api> for super::Adapter {
};
log::info!("Private capabilities: {:?}", self.private_caps);
let family_index = 0; //TODO
let raw_queue = raw_device.get_device_queue(family_index, 0);
let shared = Arc::new(super::DeviceShared {
@ -777,6 +775,8 @@ impl crate::Adapter<super::Api> for super::Adapter {
}
unsafe fn close(&self, device: super::Device) {
device.mem_allocator.lock().cleanup(&*device.shared);
device.desc_allocator.lock().cleanup(&*device.shared);
device.shared.free_resources();
}

View File

@ -8,7 +8,7 @@ use ash::{
};
use inplace_it::inplace_or_alloc_from_iter;
use std::{ffi::CStr, mem, ops::Range, slice};
use std::{mem, ops::Range, slice};
const ALLOCATION_GRANULARITY: u32 = 16;
const DST_IMAGE_LAYOUT: vk::ImageLayout = vk::ImageLayout::TRANSFER_DST_OPTIMAL;
@ -53,6 +53,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
unsafe fn begin_encoding(&mut self, label: crate::Label) -> Result<(), crate::DeviceError> {
if self.free.is_empty() {
let vk_info = vk::CommandBufferAllocateInfo::builder()
.command_pool(self.raw)
.command_buffer_count(ALLOCATION_GRANULARITY)
.build();
let cmd_buf_vec = self.device.raw.allocate_command_buffers(&vk_info)?;
@ -93,7 +94,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
where
I: Iterator<Item = super::CommandBuffer>,
{
self.marker.clear();
self.temp.clear();
self.free
.extend(cmd_bufs.into_iter().map(|cmd_buf| cmd_buf.raw));
self.free.extend(self.discarded.drain(..));
@ -109,21 +110,29 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
{
let mut src_stages = vk::PipelineStageFlags::empty();
let mut dst_stages = vk::PipelineStageFlags::empty();
let vk_barrier_iter = barriers.map(move |bar| {
let vk_barriers = &mut self.temp.buffer_barriers;
vk_barriers.clear();
for bar in barriers {
let (src_stage, src_access) = conv::map_buffer_usage_to_barrier(bar.usage.start);
src_stages |= src_stage;
let (dst_stage, dst_access) = conv::map_buffer_usage_to_barrier(bar.usage.end);
dst_stages |= dst_stage;
vk::BufferMemoryBarrier::builder()
.buffer(bar.buffer.raw)
.size(vk::WHOLE_SIZE)
.src_access_mask(src_access)
.dst_access_mask(dst_access)
.build()
});
vk_barriers.push(
vk::BufferMemoryBarrier::builder()
.buffer(bar.buffer.raw)
.size(vk::WHOLE_SIZE)
.src_access_mask(src_access)
.dst_access_mask(dst_access)
.build(),
)
}
inplace_or_alloc_from_iter(vk_barrier_iter, |vk_barriers| {
if !vk_barriers.is_empty() {
if src_stages.is_empty() {
src_stages = vk::PipelineStageFlags::TOP_OF_PIPE;
}
self.device.raw.cmd_pipeline_barrier(
self.active,
src_stages,
@ -133,7 +142,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
vk_barriers,
&[],
);
});
}
}
unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
@ -142,7 +151,10 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
{
let mut src_stages = vk::PipelineStageFlags::empty();
let mut dst_stages = vk::PipelineStageFlags::empty();
let vk_barrier_iter = barriers.map(move |bar| {
let vk_barriers = &mut self.temp.image_barriers;
vk_barriers.clear();
for bar in barriers {
let range = conv::map_subresource_range(&bar.range, bar.texture.aspects);
let (src_stage, src_access) = conv::map_texture_usage_to_barrier(bar.usage.start);
let src_layout = conv::derive_image_layout(bar.usage.start);
@ -151,17 +163,19 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
let dst_layout = conv::derive_image_layout(bar.usage.end);
dst_stages |= dst_stage;
vk::ImageMemoryBarrier::builder()
.image(bar.texture.raw)
.subresource_range(range)
.src_access_mask(src_access)
.dst_access_mask(dst_access)
.old_layout(src_layout)
.new_layout(dst_layout)
.build()
});
vk_barriers.push(
vk::ImageMemoryBarrier::builder()
.image(bar.texture.raw)
.subresource_range(range)
.src_access_mask(src_access)
.dst_access_mask(dst_access)
.old_layout(src_layout)
.new_layout(dst_layout)
.build(),
);
}
inplace_or_alloc_from_iter(vk_barrier_iter, |vk_barriers| {
if !vk_barriers.is_empty() {
self.device.raw.cmd_pipeline_barrier(
self.active,
src_stages,
@ -171,7 +185,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
&[],
vk_barriers,
);
});
}
}
unsafe fn fill_buffer(&mut self, buffer: &super::Buffer, range: crate::MemoryRange, value: u8) {
@ -468,21 +482,15 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
unsafe fn insert_debug_marker(&mut self, label: &str) {
if let Some(ext) = self.device.debug_messenger() {
self.marker.clear();
self.marker.extend_from_slice(label.as_bytes());
self.marker.push(0);
let cstr = CStr::from_bytes_with_nul_unchecked(&self.marker);
let cstr = self.temp.make_c_str(label);
let vk_label = vk::DebugUtilsLabelEXT::builder().label_name(&cstr).build();
ext.cmd_insert_debug_utils_label(self.active, &vk_label);
}
}
unsafe fn begin_debug_marker(&mut self, group_label: &str) {
if let Some(ext) = self.device.debug_messenger() {
self.marker.clear();
self.marker.extend_from_slice(group_label.as_bytes());
self.marker.push(0);
let cstr = CStr::from_bytes_with_nul_unchecked(&self.marker);
let vk_label = vk::DebugUtilsLabelEXT::builder().label_name(&cstr).build();
let cstr = self.temp.make_c_str(group_label);
let vk_label = vk::DebugUtilsLabelEXT::builder().label_name(cstr).build();
ext.cmd_begin_debug_utils_label(self.active, &vk_label);
}
}

View File

@ -154,6 +154,7 @@ impl crate::ColorAttachment<'_, super::Api> {
pub fn derive_image_layout(usage: crate::TextureUse) -> vk::ImageLayout {
match usage {
crate::TextureUse::UNINITIALIZED => vk::ImageLayout::UNDEFINED,
crate::TextureUse::COPY_SRC => vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
crate::TextureUse::COPY_DST => vk::ImageLayout::TRANSFER_DST_OPTIMAL,
crate::TextureUse::SAMPLED => vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
@ -162,6 +163,8 @@ pub fn derive_image_layout(usage: crate::TextureUse) -> vk::ImageLayout {
_ => {
if usage.contains(crate::TextureUse::DEPTH_STENCIL_READ) {
vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL
} else if usage.is_empty() {
vk::ImageLayout::PRESENT_SRC_KHR
} else {
vk::ImageLayout::GENERAL
}
@ -239,7 +242,14 @@ pub fn map_texture_usage_to_barrier(
access |= vk::AccessFlags::SHADER_WRITE;
}
(stages, access)
if usage == crate::TextureUse::UNINITIALIZED {
(
vk::PipelineStageFlags::TOP_OF_PIPE,
vk::AccessFlags::empty(),
)
} else {
(stages, access)
}
}
pub fn map_vk_image_usage(usage: vk::ImageUsageFlags) -> crate::TextureUse {

View File

@ -828,7 +828,7 @@ impl crate::Device<super::Api> for super::Device {
device: Arc::clone(&self.shared),
active: vk::CommandBuffer::null(),
bind_point: vk::PipelineBindPoint::default(),
marker: Vec::new(),
temp: super::Temp::default(),
free: Vec::new(),
discarded: Vec::new(),
})
@ -1003,33 +1003,32 @@ impl crate::Device<super::Api> for super::Device {
vk::DescriptorType::SAMPLER => {
let index = sampler_infos.len();
let binding = desc.samplers[index];
let info = vk::DescriptorImageInfo::builder()
let vk_info = vk::DescriptorImageInfo::builder()
.sampler(binding.raw)
.build();
sampler_infos.push(info);
sampler_infos.push(vk_info);
write.image_info(&sampler_infos[index..])
}
vk::DescriptorType::SAMPLED_IMAGE | vk::DescriptorType::STORAGE_IMAGE => {
let index = image_infos.len();
let binding = &desc.textures[index];
let layout = conv::derive_image_layout(binding.usage);
let info = vk::DescriptorImageInfo::builder()
let vk_info = vk::DescriptorImageInfo::builder()
.image_view(binding.view.raw)
.image_layout(layout)
.build();
image_infos.push(info);
image_infos.push(vk_info);
write.image_info(&image_infos[index..])
}
_ => {
let index = buffer_infos.len();
let binding = &desc.buffers[index];
let mut info = vk::DescriptorBufferInfo::builder()
let vk_info = vk::DescriptorBufferInfo::builder()
.buffer(binding.buffer.raw)
.offset(binding.offset);
if let Some(size) = binding.size {
info = info.range(size.get());
}
buffer_infos.push(info.build());
.offset(binding.offset)
.range(binding.size.map_or(vk::WHOLE_SIZE, wgt::BufferSize::get))
.build();
buffer_infos.push(vk_info);
write.buffer_info(&buffer_infos[index..])
}
};
@ -1148,7 +1147,8 @@ impl crate::Device<super::Api> for super::Device {
let mut vk_rasterization = vk::PipelineRasterizationStateCreateInfo::builder()
.depth_clamp_enable(desc.primitive.clamp_depth)
.polygon_mode(vk::PolygonMode::FILL)
.front_face(conv::map_front_face(desc.primitive.front_face));
.front_face(conv::map_front_face(desc.primitive.front_face))
.line_width(1.0);
if let Some(face) = desc.primitive.cull_mode {
vk_rasterization = vk_rasterization.cull_mode(conv::map_cull_face(face))
}
@ -1156,8 +1156,13 @@ impl crate::Device<super::Api> for super::Device {
let mut vk_depth_stencil = vk::PipelineDepthStencilStateCreateInfo::builder();
if let Some(ref ds) = desc.depth_stencil {
let vk_format = self.shared.private_caps.map_texture_format(ds.format);
let vk_layout = if ds.is_read_only() {
vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL
} else {
vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL
};
compatible_rp_key.depth_stencil = Some(super::DepthStencilAttachmentKey {
base: super::AttachmentKey::compatible(vk_format),
base: super::AttachmentKey::compatible(vk_format, vk_layout),
stencil_ops: crate::AttachmentOp::empty(),
});
@ -1205,7 +1210,10 @@ impl crate::Device<super::Api> for super::Device {
for cat in desc.color_targets {
let vk_format = self.shared.private_caps.map_texture_format(cat.format);
compatible_rp_key.colors.push(super::ColorAttachmentKey {
base: super::AttachmentKey::compatible(vk_format),
base: super::AttachmentKey::compatible(
vk_format,
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
),
resolve: None,
});
@ -1215,6 +1223,7 @@ impl crate::Device<super::Api> for super::Device {
let (color_op, color_src, color_dst) = conv::map_blend_component(&blend.color);
let (alpha_op, alpha_src, alpha_dst) = conv::map_blend_component(&blend.alpha);
vk_attachment = vk_attachment
.blend_enable(true)
.color_blend_op(color_op)
.src_color_blend_factor(color_src)
.dst_color_blend_factor(color_dst)

View File

@ -38,7 +38,6 @@ unsafe extern "system" fn debug_utils_messenger_callback(
} else {
CStr::from_ptr(cd.p_message_id_name).to_string_lossy()
};
let message = if cd.p_message.is_null() {
Cow::from("")
} else {
@ -47,11 +46,11 @@ unsafe extern "system" fn debug_utils_messenger_callback(
log::log!(
message_severity,
"{:?} [{} (0x{:x})] : {}\n",
"{:?} [{} (0x{:x})]\n\t{}",
message_type,
message_id_name,
cd.message_id_number,
message
message,
);
if cd.queue_label_count != 0 {
@ -65,7 +64,7 @@ unsafe extern "system" fn debug_utils_messenger_callback(
.map(|lbl| CStr::from_ptr(lbl).to_string_lossy())
})
.collect::<Vec<_>>();
log::log!(message_severity, "\tqueues: {}\n", names.join(", "));
log::log!(message_severity, "\tqueues: {}", names.join(", "));
}
if cd.cmd_buf_label_count != 0 {
@ -79,11 +78,7 @@ unsafe extern "system" fn debug_utils_messenger_callback(
.map(|lbl| CStr::from_ptr(lbl).to_string_lossy())
})
.collect::<Vec<_>>();
log::log!(
message_severity,
"\tcommand buffers: {}\n",
names.join(", ")
);
log::log!(message_severity, "\tcommand buffers: {}", names.join(", "));
}
if cd.object_count != 0 {
@ -104,7 +99,7 @@ unsafe extern "system" fn debug_utils_messenger_callback(
)
})
.collect::<Vec<_>>();
log::log!(message_severity, "\tobjects: {}\n", names.join(", "));
log::log!(message_severity, "\tobjects: {}", names.join(", "));
}
vk::FALSE
@ -239,13 +234,6 @@ impl super::Instance {
sel, sel_impl,
};
if !self.extensions.contains(&ext::MetalSurface::name()) {
panic!(
"Vulkan Portability driver does not support {:?}",
ext::MetalSurface::name()
);
}
let layer = unsafe {
let view = view as *mut Object;
let existing: *mut Object = msg_send![view, layer];
@ -373,7 +361,7 @@ impl crate::Instance<super::Api> for super::Instance {
extensions.push(khr::Win32Surface::name());
}
if cfg!(target_os = "macos") {
extensions.push(ash::extensions::mvk::MacOSSurface::name());
extensions.push(ext::MetalSurface::name());
}
if desc.flags.contains(crate::InstanceFlag::DEBUG) {
@ -546,7 +534,11 @@ impl crate::Instance<super::Api> for super::Instance {
Ok(self.create_surface_from_hwnd(hinstance as *mut _, handle.hwnd))
}
#[cfg(target_os = "macos")]
RawWindowHandle::MacOS(handle) => Ok(self.create_surface_from_ns_view(handle.ns_view)),
RawWindowHandle::MacOS(handle)
if self.extensions.contains(&ext::MetalSurface::name()) =>
{
Ok(self.create_surface_from_ns_view(handle.ns_view))
}
_ => Err(crate::InstanceError),
}
}

View File

@ -141,12 +141,12 @@ struct AttachmentKey {
impl AttachmentKey {
/// Returns an attachment key for a compatible attachment.
fn compatible(format: vk::Format) -> Self {
fn compatible(format: vk::Format, layout_in: vk::ImageLayout) -> Self {
Self {
format,
layout_pre: vk::ImageLayout::UNDEFINED,
layout_in: vk::ImageLayout::UNDEFINED,
layout_post: vk::ImageLayout::UNDEFINED,
layout_pre: vk::ImageLayout::GENERAL,
layout_in,
layout_post: vk::ImageLayout::GENERAL,
ops: crate::AttachmentOp::empty(),
}
}
@ -277,12 +277,38 @@ pub struct BindGroup {
set: gpu_descriptor::DescriptorSet<vk::DescriptorSet>,
}
#[derive(Default)]
struct Temp {
marker: Vec<u8>,
buffer_barriers: Vec<vk::BufferMemoryBarrier>,
image_barriers: Vec<vk::ImageMemoryBarrier>,
}
unsafe impl Send for Temp {}
unsafe impl Sync for Temp {}
impl Temp {
fn clear(&mut self) {
self.marker.clear();
self.buffer_barriers.clear();
self.image_barriers.clear();
//see also - https://github.com/NotIntMan/inplace_it/issues/8
}
fn make_c_str(&mut self, name: &str) -> &CStr {
self.marker.clear();
self.marker.extend_from_slice(name.as_bytes());
self.marker.push(0);
unsafe { CStr::from_bytes_with_nul_unchecked(&self.marker) }
}
}
pub struct CommandEncoder {
raw: vk::CommandPool,
device: Arc<DeviceShared>,
active: vk::CommandBuffer,
bind_point: vk::PipelineBindPoint,
marker: Vec<u8>,
temp: Temp,
free: Vec<vk::CommandBuffer>,
discarded: Vec<vk::CommandBuffer>,
}
@ -340,9 +366,11 @@ impl Fence {
self.free.push(raw);
}
}
self.active.retain(|&(value, _)| value > latest);
unsafe {
device.reset_fences(&self.free[base_free..])?;
if self.free.len() != base_free {
self.active.retain(|&(value, _)| value > latest);
unsafe {
device.reset_fences(&self.free[base_free..])?;
}
}
Ok(())
}

View File

@ -331,6 +331,7 @@ impl framework::Example for Example {
// Create the timestamp query set. We need twice as many queries as we have passes,
// as we need a query at the beginning and at the end of the operation.
let timestamp = device.create_query_set(&wgpu::QuerySetDescriptor {
label: None,
count: mip_passes * 2,
ty: wgpu::QueryType::Timestamp,
});
@ -340,6 +341,7 @@ impl framework::Example for Example {
// We only need one pipeline statistics query per pass.
let pipeline_statistics = device.create_query_set(&wgpu::QuerySetDescriptor {
label: None,
count: mip_passes,
ty: wgpu::QueryType::PipelineStatistics(
wgpu::PipelineStatisticsTypes::FRAGMENT_SHADER_INVOCATIONS,