From fb662dfbec5d7c0867c6c84097e07b5cb897b7b4 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 16 Jun 2021 17:15:34 -0400 Subject: [PATCH] hal/vk: polishing to run halmark with no validation issues --- Cargo.lock | 1 + wgpu-hal/Cargo.toml | 1 + wgpu-hal/examples/halmark/main.rs | 101 +++++++++++++++++++++++------- wgpu-hal/src/lib.rs | 1 + wgpu-hal/src/vulkan/adapter.rs | 16 ++--- wgpu-hal/src/vulkan/command.rs | 74 ++++++++++++---------- wgpu-hal/src/vulkan/conv.rs | 12 +++- wgpu-hal/src/vulkan/device.rs | 37 ++++++----- wgpu-hal/src/vulkan/instance.rs | 30 ++++----- wgpu-hal/src/vulkan/mod.rs | 44 ++++++++++--- wgpu/examples/mipmap/main.rs | 2 + 11 files changed, 212 insertions(+), 107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04c2a2eb6e..715ba754bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1997,6 +1997,7 @@ dependencies = [ "bitflags", "block", "core-graphics-types", + "env_logger", "foreign-types", "fxhash", "gpu-alloc", diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 2124b99776..295fbbddd6 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -56,4 +56,5 @@ tag = "gfx-25" features = ["wgsl-in"] [dev-dependencies] +env_logger = "0.8" winit = "0.24" diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index 46acef8214..3cd9902130 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -36,13 +36,17 @@ struct UsedResources { #[allow(dead_code)] struct Example { 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, local_buffer: A::Buffer, @@ -67,15 +71,20 @@ impl Example { 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 Example { ], }; - 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 Example { }], 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 Example { }; 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 Example { }; 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 Example { 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 Example { }) } + 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 Example { } } - 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::::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(); } _ => {} } diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 7c97f29585..fe266b450c 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -200,6 +200,7 @@ pub trait Device: Send + Sync { /// The initial usage is `BufferUse::empty()`. unsafe fn create_buffer(&self, desc: &BufferDescriptor) -> Result; unsafe fn destroy_buffer(&self, buffer: A::Buffer); + //TODO: clarify if zero-sized mapping is allowed unsafe fn map_buffer( &self, buffer: &A::Buffer, diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 621fa95002..7e1720ca44 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -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 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 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 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 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(); } diff --git a/wgpu-hal/src/vulkan/command.rs b/wgpu-hal/src/vulkan/command.rs index 7959cd16d9..f37aef2be1 100644 --- a/wgpu-hal/src/vulkan/command.rs +++ b/wgpu-hal/src/vulkan/command.rs @@ -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 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 for super::CommandEncoder { where I: Iterator, { - 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 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 for super::CommandEncoder { vk_barriers, &[], ); - }); + } } unsafe fn transition_textures<'a, T>(&mut self, barriers: T) @@ -142,7 +151,10 @@ impl crate::CommandEncoder 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 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 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 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); } } diff --git a/wgpu-hal/src/vulkan/conv.rs b/wgpu-hal/src/vulkan/conv.rs index 21ca5b99fc..1dae8cdd09 100644 --- a/wgpu-hal/src/vulkan/conv.rs +++ b/wgpu-hal/src/vulkan/conv.rs @@ -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 { diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index f04451891f..d245ccb1d7 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -828,7 +828,7 @@ impl crate::Device 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 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 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 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 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 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) diff --git a/wgpu-hal/src/vulkan/instance.rs b/wgpu-hal/src/vulkan/instance.rs index 37e04c5d6f..aa0708df8b 100644 --- a/wgpu-hal/src/vulkan/instance.rs +++ b/wgpu-hal/src/vulkan/instance.rs @@ -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::>(); - 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::>(); - 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::>(); - 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 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 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), } } diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index c53b7a9b60..7e4fafa058 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -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, } +#[derive(Default)] +struct Temp { + marker: Vec, + buffer_barriers: Vec, + image_barriers: Vec, +} + +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, active: vk::CommandBuffer, bind_point: vk::PipelineBindPoint, - marker: Vec, + temp: Temp, free: Vec, discarded: Vec, } @@ -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(()) } diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index 8faa30b51b..0bda5fafb9 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -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,