hal/vk: hook up gpu-descriptor

This commit is contained in:
Dzmitry Malyshau 2021-06-12 01:04:15 -04:00
parent 006c1baaf2
commit 4eae5a38d0
10 changed files with 219 additions and 21 deletions

View File

@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"dummy",
"player",
@ -18,15 +19,6 @@ default-members = ["wgpu", "player", "wgpu-hal"]
[patch."https://github.com/zakarumych/gpu-alloc"]
#gpu-alloc = { path = "../gpu-alloc/gpu-alloc" }
[patch."https://github.com/gfx-rs/gfx"]
#gfx-hal = { path = "../gfx/src/hal" }
#gfx-backend-empty = { path = "../gfx/src/backend/empty" }
#gfx-backend-vulkan = { path = "../gfx/src/backend/vulkan" }
#gfx-backend-gl = { path = "../gfx/src/backend/gl" }
#gfx-backend-dx12 = { path = "../gfx/src/backend/dx12" }
#gfx-backend-dx11 = { path = "../gfx/src/backend/dx11" }
#gfx-backend-metal = { path = "../gfx/src/backend/metal" }
[patch.crates-io]
#web-sys = { path = "../wasm-bindgen/crates/web-sys" }
#js-sys = { path = "../wasm-bindgen/crates/js-sys" }

View File

@ -53,7 +53,7 @@ version = "0.1"
hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["metal"] }
#Note: could also enable "vulkan" for Vulkan Portability
[target.'cfg(all(not(target_arch = "wasm32"), all(unix, not(target_os = "ios"), not(target_os = "macos"))))'.dependencies]
[target.'cfg(all(not(target_arch = "wasm32"), unix, not(target_os = "ios"), not(target_os = "macos")))'.dependencies]
hal = { path = "../wgpu-hal", package = "wgpu-hal", features = ["vulkan"] }
[dev-dependencies]

View File

@ -11,7 +11,7 @@ fn main() {
unix_wo_apple: {all(unix, not(apple))},
// Backends
vulkan: { all(false, not(wasm), any(windows, unix_wo_apple)) },
vulkan: { all(not(wasm), any(windows, unix_wo_apple)) },
metal: { all(not(wasm), apple) },
dx12: { all(false, not(wasm), windows) },
dx11: { all(false, not(wasm), windows) },

View File

@ -234,8 +234,8 @@ macro_rules! gfx_select {
// Note: For some reason the cfg aliases defined in build.rs don't succesfully apply in this
// macro so we must specify their equivalents manually
match $id.backend() {
//#[cfg(all(not(target_arch = "wasm32"), not(target_os = "ios"), not(target_os = "macos")))]
//wgt::Backend::Vulkan => $global.$method::<$crate::backend::Vulkan>( $($param),* ),
#[cfg(all(not(target_arch = "wasm32"), not(target_os = "ios"), not(target_os = "macos")))]
wgt::Backend::Vulkan => $global.$method::<$crate::backend::Vulkan>( $($param),* ),
#[cfg(all(not(target_arch = "wasm32"), any(target_os = "ios", target_os = "macos")))]
wgt::Backend::Metal => $global.$method::<$crate::api::Metal>( $($param),* ),
/*

View File

@ -52,8 +52,13 @@ struct Example<A: hal::Api> {
impl<A: hal::Api> Example<A> {
fn init(window: &winit::window::Window) -> Result<Self, hal::InstanceError> {
let instance = unsafe { A::Instance::init()? };
let instance_desc = hal::InstanceDescriptor {
name: "example",
flags: hal::InstanceFlag::all(),
};
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)?;
@ -330,6 +335,7 @@ impl<A: hal::Api> Example<A> {
label: None,
format: texture_desc.format,
dimension: wgt::TextureViewDimension::D2,
usage: hal::TextureUse::SAMPLED,
range: wgt::ImageSubresourceRange::default(),
};
let view = unsafe { device.create_texture_view(&texture, &view_desc).unwrap() };
@ -500,6 +506,7 @@ impl<A: hal::Api> Example<A> {
label: None,
format: self.surface_format,
dimension: wgt::TextureViewDimension::D2,
usage: hal::TextureUse::COLOR_TARGET,
range: wgt::ImageSubresourceRange::default(),
};
let surface_tex_view = unsafe {

View File

@ -741,6 +741,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
};
gpu_alloc::GpuAllocator::new(config, properties)
};
let desc_allocator = gpu_descriptor::DescriptorAllocator::new(0);
let device = super::Device {
shared: Arc::new(super::DeviceShared {
@ -756,6 +757,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
timestamp_period: self.phd_capabilities.properties.limits.timestamp_period,
}),
mem_allocator: Mutex::new(mem_allocator),
desc_allocator: Mutex::new(desc_allocator),
valid_ash_memory_types,
naga_options,
};

View File

@ -75,7 +75,7 @@ impl crate::CommandBuffer<super::Api> for super::Encoder {
&mut self,
layout: &super::PipelineLayout,
index: u32,
group: &Resource,
group: &super::BindGroup,
dynamic_offsets: &[wgt::DynamicOffset],
) {
}

View File

@ -1,5 +1,6 @@
use super::conv;
use arrayvec::ArrayVec;
use ash::{extensions::khr, version::DeviceV1_0, vk};
use inplace_it::inplace_or_alloc_from_iter;
use parking_lot::Mutex;
@ -134,6 +135,138 @@ impl gpu_alloc::MemoryDevice<vk::DeviceMemory> for super::DeviceShared {
}
}
impl
gpu_descriptor::DescriptorDevice<vk::DescriptorSetLayout, vk::DescriptorPool, vk::DescriptorSet>
for super::DeviceShared
{
unsafe fn create_descriptor_pool(
&self,
descriptor_count: &gpu_descriptor::DescriptorTotalCount,
max_sets: u32,
flags: gpu_descriptor::DescriptorPoolCreateFlags,
) -> Result<vk::DescriptorPool, gpu_descriptor::CreatePoolError> {
//Note: ignoring other types, since they can't appear here
let unfiltered_counts = [
(vk::DescriptorType::SAMPLER, descriptor_count.sampler),
(
vk::DescriptorType::SAMPLED_IMAGE,
descriptor_count.sampled_image,
),
(
vk::DescriptorType::STORAGE_IMAGE,
descriptor_count.storage_image,
),
(
vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count.uniform_buffer,
),
(
vk::DescriptorType::UNIFORM_BUFFER_DYNAMIC,
descriptor_count.uniform_buffer_dynamic,
),
(
vk::DescriptorType::STORAGE_BUFFER,
descriptor_count.storage_buffer,
),
(
vk::DescriptorType::STORAGE_BUFFER_DYNAMIC,
descriptor_count.storage_buffer_dynamic,
),
];
let filtered_counts = unfiltered_counts
.iter()
.cloned()
.filter(|&(_, count)| count != 0)
.map(|(ty, count)| vk::DescriptorPoolSize {
ty,
descriptor_count: count,
})
.collect::<ArrayVec<[_; 8]>>();
let mut vk_flags = vk::DescriptorPoolCreateFlags::empty();
if flags.contains(gpu_descriptor::DescriptorPoolCreateFlags::FREE_DESCRIPTOR_SET) {
vk_flags |= vk::DescriptorPoolCreateFlags::FREE_DESCRIPTOR_SET;
}
let vk_info = vk::DescriptorPoolCreateInfo::builder()
.max_sets(max_sets)
.flags(vk_flags)
.pool_sizes(&filtered_counts)
.build();
match self.raw.create_descriptor_pool(&vk_info, None) {
Ok(pool) => Ok(pool),
Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => {
Err(gpu_descriptor::CreatePoolError::OutOfHostMemory)
}
Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => {
Err(gpu_descriptor::CreatePoolError::OutOfDeviceMemory)
}
Err(vk::Result::ERROR_FRAGMENTATION) => {
Err(gpu_descriptor::CreatePoolError::Fragmentation)
}
Err(other) => {
log::error!("create_descriptor_pool: {:?}", other);
Err(gpu_descriptor::CreatePoolError::OutOfHostMemory)
}
}
}
unsafe fn destroy_descriptor_pool(&self, pool: vk::DescriptorPool) {
self.raw.destroy_descriptor_pool(pool, None)
}
unsafe fn alloc_descriptor_sets<'a>(
&self,
pool: &mut vk::DescriptorPool,
layouts: impl ExactSizeIterator<Item = &'a vk::DescriptorSetLayout>,
sets: &mut impl Extend<vk::DescriptorSet>,
) -> Result<(), gpu_descriptor::DeviceAllocationError> {
let result = inplace_or_alloc_from_iter(layouts.cloned(), |layouts_slice| {
let vk_info = vk::DescriptorSetAllocateInfo::builder()
.descriptor_pool(*pool)
.set_layouts(layouts_slice)
.build();
self.raw.allocate_descriptor_sets(&vk_info)
});
match result {
Ok(vk_sets) => {
sets.extend(vk_sets);
Ok(())
}
Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY)
| Err(vk::Result::ERROR_OUT_OF_POOL_MEMORY) => {
Err(gpu_descriptor::DeviceAllocationError::OutOfHostMemory)
}
Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => {
Err(gpu_descriptor::DeviceAllocationError::OutOfDeviceMemory)
}
Err(vk::Result::ERROR_FRAGMENTED_POOL) => {
Err(gpu_descriptor::DeviceAllocationError::FragmentedPool)
}
Err(other) => {
log::error!("allocate_descriptor_sets: {:?}", other);
Err(gpu_descriptor::DeviceAllocationError::OutOfHostMemory)
}
}
}
unsafe fn dealloc_descriptor_sets<'a>(
&self,
pool: &mut vk::DescriptorPool,
sets: impl Iterator<Item = vk::DescriptorSet>,
) {
let result = inplace_or_alloc_from_iter(sets, |sets_slice| {
self.raw.free_descriptor_sets(*pool, sets_slice)
});
match result {
Ok(()) => {}
Err(err) => log::error!("free_descriptor_sets: {:?}", err),
}
}
}
impl super::Device {
pub(super) unsafe fn create_swapchain(
&self,
@ -483,6 +616,42 @@ impl crate::Device<super::Api> for super::Device {
&self,
desc: &crate::BindGroupLayoutDescriptor,
) -> Result<super::BindGroupLayout, crate::DeviceError> {
let mut desc_count = gpu_descriptor::DescriptorTotalCount::default();
for entry in desc.entries {
let count = entry.count.map_or(1, |c| c.get());
match entry.ty {
wgt::BindingType::Buffer {
ty,
has_dynamic_offset,
..
} => match ty {
wgt::BufferBindingType::Uniform => {
if has_dynamic_offset {
desc_count.uniform_buffer_dynamic += count;
} else {
desc_count.uniform_buffer += count;
}
}
wgt::BufferBindingType::Storage { .. } => {
if has_dynamic_offset {
desc_count.storage_buffer_dynamic += count;
} else {
desc_count.storage_buffer += count;
}
}
},
wgt::BindingType::Sampler { .. } => {
desc_count.sampler += count;
}
wgt::BindingType::Texture { .. } => {
desc_count.sampled_image += count;
}
wgt::BindingType::StorageTexture { .. } => {
desc_count.storage_image += count;
}
}
}
//Note: not bothering with inplace_or_alloc_from_iter her as it's low frequency
let vk_bindings = desc
.entries
@ -510,7 +679,7 @@ impl crate::Device<super::Api> for super::Device {
.set_object_name(vk::ObjectType::DESCRIPTOR_SET_LAYOUT, raw, label);
}
Ok(super::BindGroupLayout { raw })
Ok(super::BindGroupLayout { raw, desc_count })
}
unsafe fn destroy_bind_group_layout(&self, bg_layout: super::BindGroupLayout) {
self.shared
@ -561,10 +730,23 @@ impl crate::Device<super::Api> for super::Device {
unsafe fn create_bind_group(
&self,
desc: &crate::BindGroupDescriptor<super::Api>,
) -> DeviceResult<Resource> {
Ok(Resource)
) -> Result<super::BindGroup, crate::DeviceError> {
let mut vk_sets = self.desc_allocator.lock().allocate(
&*self.shared,
&desc.layout.raw,
gpu_descriptor::DescriptorSetLayoutCreateFlags::empty(),
&desc.layout.desc_count,
1,
)?;
Ok(super::BindGroup {
raw: vk_sets.pop().unwrap(),
})
}
unsafe fn destroy_bind_group(&self, group: super::BindGroup) {
self.desc_allocator
.lock()
.free(&*self.shared, Some(group.raw));
}
unsafe fn destroy_bind_group(&self, group: Resource) {}
unsafe fn create_shader_module(
&self,
@ -627,7 +809,6 @@ impl From<gpu_alloc::AllocationError> for crate::DeviceError {
}
}
}
impl From<gpu_alloc::MapError> for crate::DeviceError {
fn from(error: gpu_alloc::MapError) -> Self {
use gpu_alloc::MapError as Me;
@ -640,3 +821,9 @@ impl From<gpu_alloc::MapError> for crate::DeviceError {
}
}
}
impl From<gpu_descriptor::AllocationError> for crate::DeviceError {
fn from(error: gpu_descriptor::AllocationError) -> Self {
log::error!("descriptor allocation: {:?}", error);
Self::OutOfMemory
}
}

View File

@ -503,6 +503,7 @@ impl crate::Instance<super::Api> for super::Instance {
unix,
not(target_os = "android"),
not(target_os = "macos"),
not(target_os = "ios"),
not(target_os = "solaris")
))]
RawWindowHandle::Wayland(handle)
@ -514,6 +515,7 @@ impl crate::Instance<super::Api> for super::Instance {
unix,
not(target_os = "android"),
not(target_os = "macos"),
not(target_os = "ios"),
not(target_os = "solaris")
))]
RawWindowHandle::Xlib(handle)

View File

@ -42,7 +42,7 @@ impl crate::Api for Api {
type Fence = Resource;
type BindGroupLayout = BindGroupLayout;
type BindGroup = Resource;
type BindGroup = BindGroup;
type PipelineLayout = PipelineLayout;
type ShaderModule = Resource;
type RenderPipeline = Resource;
@ -147,6 +147,8 @@ struct DeviceShared {
pub struct Device {
shared: Arc<DeviceShared>,
mem_allocator: Mutex<gpu_alloc::GpuAllocator<vk::DeviceMemory>>,
desc_allocator:
Mutex<gpu_descriptor::DescriptorAllocator<vk::DescriptorPool, vk::DescriptorSet>>,
valid_ash_memory_types: u32,
naga_options: naga::back::spv::Options,
}
@ -183,6 +185,7 @@ pub struct Sampler {
#[derive(Debug)]
pub struct BindGroupLayout {
raw: vk::DescriptorSetLayout,
desc_count: gpu_descriptor::DescriptorTotalCount,
}
#[derive(Debug)]
@ -190,6 +193,11 @@ pub struct PipelineLayout {
raw: vk::PipelineLayout,
}
#[derive(Debug)]
pub struct BindGroup {
raw: gpu_descriptor::DescriptorSet<vk::DescriptorSet>,
}
impl crate::Queue<Api> for Queue {
unsafe fn submit<I>(
&mut self,