wgn: command pools and buffer creation

This commit is contained in:
Dzmitry Malyshau 2018-09-27 15:43:19 -04:00
parent 3c583160d4
commit 212cc386f3
8 changed files with 143 additions and 16 deletions

View File

@ -0,0 +1,101 @@
use super::CommandBuffer;
use hal::{self, Device};
use hal::command::RawCommandBuffer;
use hal::pool::RawCommandPool;
use std::collections::HashMap;
//TODO: use `parking_lot::Mutex`?
use std::sync::Mutex;
use std::thread;
struct CommandPool<B: hal::Backend> {
raw: B::CommandPool,
available: Vec<CommandBuffer<B>>,
}
pub struct Inner<B: hal::Backend> {
pools: HashMap<thread::ThreadId, CommandPool<B>>,
pending: Vec<CommandBuffer<B>>,
}
pub struct CommandAllocator<B: hal::Backend> {
queue_family: hal::queue::QueueFamilyId,
inner: Mutex<Inner<B>>,
}
impl<B: hal::Backend> CommandAllocator<B> {
pub fn new(queue_family: hal::queue::QueueFamilyId) -> Self {
CommandAllocator {
queue_family,
inner: Mutex::new(Inner {
pools: HashMap::new(),
pending: Vec::new(),
}),
}
}
pub fn allocate(&self, device: &B::Device) -> CommandBuffer<B> {
let thread_id = thread::current().id();
let mut inner = self.inner.lock().unwrap();
let pool = inner.pools
.entry(thread_id)
.or_insert_with(|| CommandPool {
raw: device.create_command_pool(
self.queue_family,
hal::pool::CommandPoolCreateFlags::RESET_INDIVIDUAL,
),
available: Vec::new(),
});
if let Some(cmd_buf) = pool.available.pop() {
device.reset_fence(&cmd_buf.fence);
return cmd_buf;
}
for raw in pool.raw.allocate(20, hal::command::RawLevel::Primary) {
pool.available.push(CommandBuffer {
raw,
fence: device.create_fence(false),
recorded_thread_id: thread_id,
});
}
pool.available.pop().unwrap()
}
pub fn submit(&self, cmd_buf: CommandBuffer<B>) {
self.inner
.lock()
.unwrap()
.pending
.push(cmd_buf);
}
pub fn recycle(&self, mut cmd_buf: CommandBuffer<B>) {
cmd_buf.raw.reset(false);
self.inner
.lock()
.unwrap()
.pools
.get_mut(&cmd_buf.recorded_thread_id)
.unwrap()
.available
.push(cmd_buf);
}
pub fn maintain(&self, device: &B::Device) {
let mut inner = self.inner.lock().unwrap();
for i in (0 .. inner.pending.len()).rev() {
if device.get_fence_status(&inner.pending[i].fence) {
let cmd_buf = inner.pending.swap_remove(i);
inner
.pools
.get_mut(&cmd_buf.recorded_thread_id)
.unwrap()
.available
.push(cmd_buf);
}
}
}
}

View File

@ -1,6 +1,6 @@
use hal;
use {CommandBuffer, CommandBufferId, ComputePassId};
//use {CommandBuffer, CommandBufferId, ComputePassId};
pub struct ComputePass<B: hal::Backend> {
raw: B::CommandBuffer,

View File

@ -1,6 +1,8 @@
mod allocator;
mod compute;
mod render;
pub use self::allocator::*;
pub use self::compute::*;
pub use self::render::*;
@ -11,6 +13,9 @@ use {
TextureViewId,
};
use std::thread::ThreadId;
#[repr(C)]
pub enum LoadOp {
Clear = 0,
@ -66,14 +71,16 @@ pub struct TextureCopyView {
pub struct CommandBuffer<B: hal::Backend> {
raw: B::CommandBuffer,
fence: B::Fence,
recorded_thread_id: ThreadId,
}
#[repr(C)]
pub struct CommandBufferDescriptor;
pub struct CommandBufferDescriptor {}
#[no_mangle]
pub extern "C" fn wgpu_command_buffer_begin_render_pass(
command_buffer: CommandBufferId,
_command_buffer: CommandBufferId,
) -> RenderPassId {
unimplemented!()
}

View File

@ -1,6 +1,6 @@
use hal;
use {CommandBuffer, CommandBufferId, RenderPassId};
//use {CommandBuffer, CommandBufferId, RenderPassId};
pub struct RenderPass<B: hal::Backend> {
raw: B::CommandBuffer,

View File

@ -1,16 +1,17 @@
use hal::{self, Device as _Device, QueueGroup};
use {conv, memory, pipeline, resource};
use {command, conv, memory, pipeline, resource};
use registry::{self, Registry};
use {BufferId, CommandBufferId, DeviceId, ShaderModuleId};
#[repr(C)]
pub struct CommandBufferDescriptor {}
use std::slice;
pub struct Device<B: hal::Backend> {
device: B::Device,
queue_group: QueueGroup<B, hal::General>,
allocator: memory::SmartAllocator<B>,
mem_allocator: memory::SmartAllocator<B>,
com_allocator: command::CommandAllocator<B>,
}
impl<B: hal::Backend> Device<B> {
@ -21,8 +22,9 @@ impl<B: hal::Backend> Device<B> {
) -> Self {
Device {
device,
mem_allocator: memory::SmartAllocator::new(mem_props, 1, 1, 1, 1),
com_allocator: command::CommandAllocator::new(queue_group.family()),
queue_group,
allocator: memory::SmartAllocator::new(mem_props, 1, 1, 1, 1),
}
}
}
@ -40,7 +42,17 @@ pub extern "C" fn wgpu_device_create_shader_module(
let shader = device
.device
.create_shader_module(unsafe {
::std::slice::from_raw_parts(desc.code.bytes, desc.code.length)
slice::from_raw_parts(desc.code.bytes, desc.code.length)
}).unwrap();
registry::SHADER_MODULE_REGISTRY.register(ShaderModule { raw: shader })
}
#[no_mangle]
pub extern "C" fn wgpu_device_create_command_buffer(
device_id: DeviceId,
desc: command::CommandBufferDescriptor,
) -> CommandBufferId {
let device = registry::DEVICE_REGISTRY.get_mut(device_id);
let cmd_buf = device.com_allocator.allocate(&device.device);
registry::COMMAND_BUFFER_REGISTRY.register(cmd_buf)
}

View File

@ -71,7 +71,7 @@ pub extern "C" fn wgpu_instance_get_adapter(
#[no_mangle]
pub extern "C" fn wgpu_adapter_create_device(
adapter_id: AdapterId,
desc: DeviceDescriptor,
_desc: DeviceDescriptor,
) -> DeviceId {
let mut adapter = registry::ADAPTER_REGISTRY.get_mut(adapter_id);
let (device, queue_group) = adapter.open_with::<_, hal::General>(1, |_qf| true).unwrap();

View File

@ -40,6 +40,7 @@ pub use self::resource::*;
use back::Backend as B;
use registry::Id;
#[repr(C)]
pub struct Color {
pub r: f32,
@ -69,11 +70,11 @@ pub struct ByteArray {
}
pub type InstanceId = Id;
pub(crate) type InstanceHandle = back::Instance;
type InstanceHandle = back::Instance;
pub type AdapterId = Id;
pub(crate) type AdapterHandle = hal::Adapter<B>;
type AdapterHandle = hal::Adapter<B>;
pub type DeviceId = Id;
pub(crate) type DeviceHandle = Device<B>;
type DeviceHandle = Device<B>;
pub type BufferId = Id;
// Resource
@ -90,11 +91,12 @@ pub type BlendStateId = Id;
pub type DepthStencilStateId = Id;
pub type InputStateId = Id;
pub type ShaderModuleId = Id;
pub(crate) type ShaderModuleHandle = ShaderModule<B>;
type ShaderModuleHandle = ShaderModule<B>;
pub type AttachmentStateId = Id;
pub type ComputePipelineId = Id;
pub type RenderPipelineId = Id;
pub type CommandBufferId = Id;
type CommandBufferHandle = CommandBuffer<B>;
pub type RenderPassId = Id;
pub type ComputePassId = Id;

View File

@ -4,10 +4,14 @@ use std::os::raw::c_void;
use std::sync::Arc;
#[cfg(feature = "remote")]
use parking_lot::{Mutex, MutexGuard, MappedMutexGuard};
#[cfg(feature = "remote")]
use std::{borrow, cmp, fmt, ops, ptr};
#[cfg(feature = "remote")]
use hal::backend::FastHashMap;
use {AdapterHandle, DeviceHandle, InstanceHandle, ShaderModuleHandle};
use {AdapterHandle, CommandBufferHandle, DeviceHandle, InstanceHandle, ShaderModuleHandle};
#[cfg(not(feature = "remote"))]
pub(crate) type Id = *mut c_void;
@ -99,4 +103,5 @@ lazy_static! {
pub(crate) static ref DEVICE_REGISTRY: ConcreteRegistry<DeviceHandle> = ConcreteRegistry::new();
pub(crate) static ref INSTANCE_REGISTRY: ConcreteRegistry<InstanceHandle> = ConcreteRegistry::new();
pub(crate) static ref SHADER_MODULE_REGISTRY: ConcreteRegistry<ShaderModuleHandle> = ConcreteRegistry::new();
pub(crate) static ref COMMAND_BUFFER_REGISTRY: ConcreteRegistry<CommandBufferHandle> = ConcreteRegistry::new();
}