mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
hal/vk: polishing to run halmark with no validation issues
This commit is contained in:
parent
c53addac8a
commit
fb662dfbec
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1997,6 +1997,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"core-graphics-types",
|
||||
"env_logger",
|
||||
"foreign-types",
|
||||
"fxhash",
|
||||
"gpu-alloc",
|
||||
|
@ -56,4 +56,5 @@ tag = "gfx-25"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.8"
|
||||
winit = "0.24"
|
||||
|
@ -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();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user