introduce DynResource & DynBuffer as first user

This commit is contained in:
Andreas Reich 2024-07-11 00:35:36 +02:00
parent c6a3d92734
commit d2508d9ad6
7 changed files with 175 additions and 1 deletions

View File

@ -87,6 +87,25 @@ impl crate::Api for Api {
type AccelerationStructure = AccelerationStructure;
}
crate::impl_dyn_resource!(
BindGroup,
BindGroupLayout,
Buffer,
CommandBuffer,
CommandEncoder,
ComputePipeline,
Fence,
PipelineCache,
PipelineLayout,
QuerySet,
RenderPipeline,
Sampler,
ShaderModule,
Surface,
Texture,
TextureView
);
// Limited by D3D12's root signature size of 64. Each element takes 1 or 2 entries.
const MAX_ROOT_ELEMENTS: usize = 64;
const ZERO_BUFFER_SIZE: wgt::BufferAddress = 256 << 10;
@ -407,6 +426,8 @@ pub struct Buffer {
unsafe impl Send for Buffer {}
unsafe impl Sync for Buffer {}
impl crate::DynBuffer for Buffer {}
impl crate::BufferBinding<'_, Api> {
fn resolve_size(&self) -> wgt::BufferAddress {
match self.size {

View File

@ -0,0 +1,83 @@
use std::any::Any;
use wgt::WasmNotSendSync;
/// Base trait for all resources, allows downcasting via [`Any`].
pub trait DynResource: Any + WasmNotSendSync + 'static {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
/// Utility macro for implementing `DynResource` for a list of types.
macro_rules! impl_dyn_resource {
($($type:ty),*) => {
$(
impl crate::DynResource for $type {
fn as_any(&self) -> &dyn ::std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
self
}
}
)*
};
}
pub(crate) use impl_dyn_resource;
/// Extension trait for `DynResource` used by implementations of various dynamic resource traits.
trait DynResourceExt {
/// # Panics
///
/// - Panics if `self` is not downcastable to `T`.
fn expect_downcast_ref<T: DynResource>(&self) -> &T;
/// # Panics
///
/// - Panics if `self` is not downcastable to `T`.
fn expect_downcast_mut<T: DynResource>(&mut self) -> &mut T;
/// Unboxes a `Box<dyn DynResource>` to a concrete type.
///
/// # Safety
///
/// - `self` must be the correct concrete type.
unsafe fn unbox<T: DynResource + 'static>(self: Box<Self>) -> T;
}
impl<R: DynResource + ?Sized> DynResourceExt for R {
fn expect_downcast_ref<'a, T: DynResource>(&'a self) -> &'a T {
self.as_any()
.downcast_ref()
.expect("Resource doesn't have the expected backend type.")
}
fn expect_downcast_mut<'a, T: DynResource>(&'a mut self) -> &'a mut T {
self.as_any_mut()
.downcast_mut()
.expect("Resource doesn't have the expected backend type.")
}
unsafe fn unbox<T: DynResource + 'static>(self: Box<Self>) -> T {
debug_assert!(
<Self as Any>::type_id(self.as_ref()) == std::any::TypeId::of::<T>(),
"Resource doesn't have the expected type, expected {:?}, got {:?}",
std::any::TypeId::of::<T>(),
<Self as Any>::type_id(self.as_ref())
);
let casted_ptr = Box::into_raw(self).cast::<T>();
// SAFETY: This is adheres to the safety contract of `Box::from_raw` because:
//
// - We are casting the value of a previously `Box`ed value, which guarantees:
// - `casted_ptr` is not null.
// - `casted_ptr` is valid for reads and writes, though by itself this does not mean
// valid reads and writes for `T` (read on for that).
// - We don't change the allocator.
// - The contract of `Box::from_raw` requires that an initialized and aligned `T` is stored
// within `casted_ptr`.
*unsafe { Box::from_raw(casted_ptr) }
}
}
pub trait DynBuffer: DynResource + std::fmt::Debug {}

View File

@ -40,6 +40,10 @@ impl crate::Api for Api {
type ComputePipeline = Resource;
}
crate::impl_dyn_resource!(Context, Encoder, Resource);
impl crate::DynBuffer for Resource {}
impl crate::Instance for Context {
type A = Api;

View File

@ -164,6 +164,24 @@ impl crate::Api for Api {
type ComputePipeline = ComputePipeline;
}
crate::impl_dyn_resource!(
BindGroup,
BindGroupLayout,
Buffer,
CommandBuffer,
CommandEncoder,
ComputePipeline,
Fence,
PipelineLayout,
QuerySet,
RenderPipeline,
Sampler,
ShaderModule,
Surface,
Texture,
TextureView
);
bitflags::bitflags! {
/// Flags that affect internal code paths but do not
/// change the exposed feature set.
@ -307,6 +325,8 @@ unsafe impl Sync for Buffer {}
#[cfg(send_sync)]
unsafe impl Send for Buffer {}
impl crate::DynBuffer for Buffer {}
#[derive(Clone, Debug)]
pub enum TextureInner {
Renderbuffer {

View File

@ -262,6 +262,11 @@ pub mod api {
pub use super::vulkan::Api as Vulkan;
}
mod dynamic;
pub use dynamic::DynBuffer;
pub(crate) use dynamic::{impl_dyn_resource, DynResource};
use std::{
borrow::{Borrow, Cow},
fmt,
@ -399,7 +404,7 @@ pub trait Api: Clone + fmt::Debug + Sized {
/// [`CommandEncoder`]: Api::CommandEncoder
type CommandBuffer: WasmNotSendSync + fmt::Debug;
type Buffer: fmt::Debug + WasmNotSendSync + 'static;
type Buffer: DynBuffer;
type Texture: fmt::Debug + WasmNotSendSync + 'static;
type SurfaceTexture: fmt::Debug + WasmNotSendSync + Borrow<Self::Texture>;
type TextureView: fmt::Debug + WasmNotSendSync;

View File

@ -71,6 +71,24 @@ impl crate::Api for Api {
type AccelerationStructure = AccelerationStructure;
}
crate::impl_dyn_resource!(
BindGroup,
BindGroupLayout,
Buffer,
CommandBuffer,
CommandEncoder,
ComputePipeline,
Fence,
PipelineLayout,
QuerySet,
RenderPipeline,
Sampler,
ShaderModule,
Surface,
Texture,
TextureView
);
pub struct Instance {
managed_metal_layer_delegate: surface::HalManagedMetalLayerDelegate,
}
@ -460,6 +478,8 @@ pub struct Buffer {
unsafe impl Send for Buffer {}
unsafe impl Sync for Buffer {}
impl crate::DynBuffer for Buffer {}
impl Buffer {
fn as_raw(&self) -> BufferPtr {
unsafe { NonNull::new_unchecked(self.raw.as_ptr()) }

View File

@ -78,6 +78,25 @@ impl crate::Api for Api {
type ComputePipeline = ComputePipeline;
}
crate::impl_dyn_resource!(
BindGroup,
BindGroupLayout,
Buffer,
CommandBuffer,
CommandEncoder,
ComputePipeline,
Fence,
PipelineCache,
PipelineLayout,
QuerySet,
RenderPipeline,
Sampler,
ShaderModule,
Surface,
Texture,
TextureView
);
struct DebugUtils {
extension: ext::debug_utils::Instance,
messenger: vk::DebugUtilsMessengerEXT,
@ -631,6 +650,8 @@ pub struct Buffer {
block: Option<Mutex<gpu_alloc::MemoryBlock<vk::DeviceMemory>>>,
}
impl crate::DynBuffer for Buffer {}
#[derive(Debug)]
pub struct AccelerationStructure {
raw: vk::AccelerationStructureKHR,