mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Support extern context impl (#6658)
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
parent
7eb69f43b6
commit
7e66495049
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -963,6 +963,14 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
|
||||
|
||||
[[package]]
|
||||
name = "custom-backend"
|
||||
version = "24.0.0"
|
||||
dependencies = [
|
||||
"pollster",
|
||||
"wgpu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.8.0"
|
||||
@ -3074,6 +3082,20 @@ name = "pollster"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
|
||||
dependencies = [
|
||||
"pollster-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pollster-macro"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac5da421106a50887c5b51d20806867db377fbb86bacf478ee0500a912e0c113"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
|
||||
@ -16,6 +16,7 @@ be cloned out of the repository to serve as a starting point for your own projec
|
||||
|--------|-------------|-----------|
|
||||
| [hello compute](standalone/01_hello_compute/) | Simplest example and shows how to run a compute shader on a given set of input data and get the results back. | Native-Only |
|
||||
| [hello window](standalone/02_hello_window/) | Shows how to create a window and render into it. | Native-Only |
|
||||
| [custom backend](standalone/03_custom_backend/) | Shows how to implement and use custom wgpu context | Any |
|
||||
|
||||
You can also use [`cargo-generate`](https://github.com/cargo-generate/cargo-generate) to easily use these as a basis for your own projects.
|
||||
|
||||
|
||||
18
examples/standalone/03_custom_backend/Cargo.toml
Normal file
18
examples/standalone/03_custom_backend/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "custom-backend"
|
||||
description = "Example of creating and loading custom wgpu backend"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[dependencies]
|
||||
wgpu = { workspace = true, features = ["custom"], default-features = false }
|
||||
pollster = { workspace = true, features = ["macro"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
346
examples/standalone/03_custom_backend/src/custom.rs
Normal file
346
examples/standalone/03_custom_backend/src/custom.rs
Normal file
@ -0,0 +1,346 @@
|
||||
#![allow(dead_code)]
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use wgpu::custom::{
|
||||
AdapterInterface, DeviceInterface, DispatchAdapter, DispatchDevice, DispatchQueue,
|
||||
DispatchShaderModule, DispatchSurface, InstanceInterface, QueueInterface, RequestAdapterFuture,
|
||||
ShaderModuleInterface,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Counter(Arc<()>);
|
||||
|
||||
impl Counter {
|
||||
pub fn new() -> Self {
|
||||
Self(Arc::new(()))
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize {
|
||||
Arc::strong_count(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CustomInstance(pub Counter);
|
||||
|
||||
impl InstanceInterface for CustomInstance {
|
||||
fn new(__desc: &wgpu::InstanceDescriptor) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Self(Counter::new())
|
||||
}
|
||||
|
||||
unsafe fn create_surface(
|
||||
&self,
|
||||
_target: wgpu::SurfaceTargetUnsafe,
|
||||
) -> Result<DispatchSurface, wgpu::CreateSurfaceError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn request_adapter(
|
||||
&self,
|
||||
_options: &wgpu::RequestAdapterOptions<'_, '_>,
|
||||
) -> std::pin::Pin<Box<dyn RequestAdapterFuture>> {
|
||||
Box::pin(std::future::ready(Some(DispatchAdapter::custom(
|
||||
CustomAdapter(self.0.clone()),
|
||||
))))
|
||||
}
|
||||
|
||||
fn poll_all_devices(&self, _force_wait: bool) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn wgsl_language_features(&self) -> wgpu::WgslLanguageFeatures {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CustomAdapter(Counter);
|
||||
|
||||
impl AdapterInterface for CustomAdapter {
|
||||
fn request_device(
|
||||
&self,
|
||||
desc: &wgpu::DeviceDescriptor<'_>,
|
||||
_trace_dir: Option<&std::path::Path>,
|
||||
) -> Pin<Box<dyn wgpu::custom::RequestDeviceFuture>> {
|
||||
assert_eq!(desc.label, Some("device"));
|
||||
let res: Result<_, wgpu::RequestDeviceError> = Ok((
|
||||
DispatchDevice::custom(CustomDevice(self.0.clone())),
|
||||
DispatchQueue::custom(CustomQueue(self.0.clone())),
|
||||
));
|
||||
Box::pin(std::future::ready(res))
|
||||
}
|
||||
|
||||
fn is_surface_supported(&self, _surface: &DispatchSurface) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn features(&self) -> wgpu::Features {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn limits(&self) -> wgpu::Limits {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn downlevel_capabilities(&self) -> wgpu::DownlevelCapabilities {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_info(&self) -> wgpu::AdapterInfo {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_texture_format_features(
|
||||
&self,
|
||||
_format: wgpu::TextureFormat,
|
||||
) -> wgpu::TextureFormatFeatures {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_presentation_timestamp(&self) -> wgpu::PresentationTimestamp {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CustomDevice(Counter);
|
||||
|
||||
impl DeviceInterface for CustomDevice {
|
||||
fn features(&self) -> wgpu::Features {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn limits(&self) -> wgpu::Limits {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_shader_module(
|
||||
&self,
|
||||
desc: wgpu::ShaderModuleDescriptor<'_>,
|
||||
_shader_bound_checks: wgpu::ShaderRuntimeChecks,
|
||||
) -> DispatchShaderModule {
|
||||
assert_eq!(desc.label, Some("shader"));
|
||||
DispatchShaderModule::custom(CustomShaderModule(self.0.clone()))
|
||||
}
|
||||
|
||||
unsafe fn create_shader_module_spirv(
|
||||
&self,
|
||||
_desc: &wgpu::ShaderModuleDescriptorSpirV<'_>,
|
||||
) -> DispatchShaderModule {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_bind_group_layout(
|
||||
&self,
|
||||
_desc: &wgpu::BindGroupLayoutDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchBindGroupLayout {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_bind_group(
|
||||
&self,
|
||||
_desc: &wgpu::BindGroupDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchBindGroup {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_pipeline_layout(
|
||||
&self,
|
||||
_desc: &wgpu::PipelineLayoutDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchPipelineLayout {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_render_pipeline(
|
||||
&self,
|
||||
_desc: &wgpu::RenderPipelineDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchRenderPipeline {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_compute_pipeline(
|
||||
&self,
|
||||
_desc: &wgpu::ComputePipelineDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchComputePipeline {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
unsafe fn create_pipeline_cache(
|
||||
&self,
|
||||
_desc: &wgpu::PipelineCacheDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchPipelineCache {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_buffer(&self, _desc: &wgpu::BufferDescriptor<'_>) -> wgpu::custom::DispatchBuffer {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_texture(&self, _desc: &wgpu::TextureDescriptor<'_>) -> wgpu::custom::DispatchTexture {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_blas(
|
||||
&self,
|
||||
_desc: &wgpu::CreateBlasDescriptor<'_>,
|
||||
_sizes: wgpu::BlasGeometrySizeDescriptors,
|
||||
) -> (Option<u64>, wgpu::custom::DispatchBlas) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_tlas(&self, _desc: &wgpu::CreateTlasDescriptor<'_>) -> wgpu::custom::DispatchTlas {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_sampler(&self, _desc: &wgpu::SamplerDescriptor<'_>) -> wgpu::custom::DispatchSampler {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_query_set(
|
||||
&self,
|
||||
_desc: &wgpu::QuerySetDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchQuerySet {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_command_encoder(
|
||||
&self,
|
||||
_desc: &wgpu::CommandEncoderDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchCommandEncoder {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_render_bundle_encoder(
|
||||
&self,
|
||||
_desc: &wgpu::RenderBundleEncoderDescriptor<'_>,
|
||||
) -> wgpu::custom::DispatchRenderBundleEncoder {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_device_lost_callback(&self, _device_lost_callback: wgpu::custom::BoxDeviceLostCallback) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn on_uncaptured_error(&self, _handler: Box<dyn wgpu::UncapturedErrorHandler>) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn push_error_scope(&self, _filter: wgpu::ErrorFilter) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn pop_error_scope(&self) -> Pin<Box<dyn wgpu::custom::PopErrorScopeFuture>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn start_capture(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stop_capture(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn poll(&self, _maintain: wgpu::PollType) -> Result<wgpu::PollStatus, wgpu::PollError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_internal_counters(&self) -> wgpu::InternalCounters {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn generate_allocator_report(&self) -> Option<wgpu::AllocatorReport> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn destroy(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CustomShaderModule(Counter);
|
||||
|
||||
impl ShaderModuleInterface for CustomShaderModule {
|
||||
fn get_compilation_info(&self) -> Pin<Box<dyn wgpu::custom::ShaderCompilationInfoFuture>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CustomQueue(Counter);
|
||||
|
||||
impl QueueInterface for CustomQueue {
|
||||
fn write_buffer(
|
||||
&self,
|
||||
_buffer: &wgpu::custom::DispatchBuffer,
|
||||
_offset: wgpu::BufferAddress,
|
||||
_data: &[u8],
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_staging_buffer(
|
||||
&self,
|
||||
_size: wgpu::BufferSize,
|
||||
) -> Option<wgpu::custom::DispatchQueueWriteBuffer> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn validate_write_buffer(
|
||||
&self,
|
||||
_buffer: &wgpu::custom::DispatchBuffer,
|
||||
_offset: wgpu::BufferAddress,
|
||||
_size: wgpu::BufferSize,
|
||||
) -> Option<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write_staging_buffer(
|
||||
&self,
|
||||
_buffer: &wgpu::custom::DispatchBuffer,
|
||||
_offset: wgpu::BufferAddress,
|
||||
_staging_buffer: &wgpu::custom::DispatchQueueWriteBuffer,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write_texture(
|
||||
&self,
|
||||
_texture: wgpu::TexelCopyTextureInfo<'_>,
|
||||
_data: &[u8],
|
||||
_data_layout: wgpu::TexelCopyBufferLayout,
|
||||
_size: wgpu::Extent3d,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn submit(
|
||||
&self,
|
||||
_command_buffers: &mut dyn Iterator<Item = wgpu::custom::DispatchCommandBuffer>,
|
||||
) -> u64 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_timestamp_period(&self) -> f32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn on_submitted_work_done(&self, _callback: wgpu::custom::BoxSubmittedWorkDoneCallback) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn copy_external_image_to_texture(
|
||||
&self,
|
||||
_source: &wgpu::CopyExternalImageSourceInfo,
|
||||
_dest: wgpu::CopyExternalImageDestInfo<&wgpu::Texture>,
|
||||
_size: wgpu::Extent3d,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
45
examples/standalone/03_custom_backend/src/main.rs
Normal file
45
examples/standalone/03_custom_backend/src/main.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use custom::Counter;
|
||||
use wgpu::{DeviceDescriptor, RequestAdapterOptions};
|
||||
|
||||
mod custom;
|
||||
|
||||
#[pollster::main]
|
||||
async fn main() {
|
||||
let counter = Counter::new();
|
||||
{
|
||||
let custom_instance = custom::CustomInstance(counter.clone());
|
||||
// wrap custom instance into wgpu abstraction
|
||||
let instance = wgpu::Instance::from_custom(custom_instance);
|
||||
assert_eq!(counter.count(), 2);
|
||||
// do work on instance (usually by passing it to other libs)
|
||||
|
||||
// here we will simulate a library and ensure that counter is incremented
|
||||
let adapter = instance
|
||||
.request_adapter(&RequestAdapterOptions::default())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(counter.count(), 3);
|
||||
|
||||
let (device, _queue) = adapter
|
||||
.request_device(
|
||||
&DeviceDescriptor {
|
||||
label: Some("device"),
|
||||
..Default::default()
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(counter.count(), 5);
|
||||
|
||||
let _module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("shader"),
|
||||
source: wgpu::ShaderSource::Dummy(PhantomData),
|
||||
});
|
||||
|
||||
assert_eq!(counter.count(), 6);
|
||||
}
|
||||
assert_eq!(counter.count(), 1);
|
||||
}
|
||||
@ -82,6 +82,8 @@ noop = ["wgpu-core/noop"]
|
||||
#! it means that the item is only available when that backend is enabled _and_ the backend
|
||||
#! is supported on the current platform.
|
||||
|
||||
custom = []
|
||||
|
||||
#! ### Shading language support
|
||||
# --------------------------------------------------------------------
|
||||
#! These features enable support for that input language on all platforms.
|
||||
|
||||
@ -45,6 +45,7 @@ fn main() {
|
||||
naga: { any(feature = "naga-ir", feature = "spirv", feature = "glsl") },
|
||||
// ⚠️ Keep in sync with target.cfg() definition in wgpu-hal/Cargo.toml and cfg_alias in `wgpu-hal` crate ⚠️
|
||||
static_dxc: { all(target_os = "windows", feature = "static-dxc", not(target_arch = "aarch64")) },
|
||||
supports_64bit_atomics: { target_has_atomic = "64" }
|
||||
supports_64bit_atomics: { target_has_atomic = "64" },
|
||||
custom: {any(feature = "custom")}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,6 +136,14 @@ impl Adapter {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(custom)]
|
||||
/// Creates Adapter from custom implementation
|
||||
pub fn from_custom<T: custom::AdapterInterface>(adapter: T) -> Self {
|
||||
Self {
|
||||
inner: dispatch::DispatchAdapter::custom(adapter),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this adapter may present to the passed surface.
|
||||
pub fn is_surface_supported(&self, surface: &Surface<'_>) -> bool {
|
||||
self.inner.is_surface_supported(&surface.inner)
|
||||
|
||||
@ -34,6 +34,14 @@ pub type DeviceDescriptor<'a> = wgt::DeviceDescriptor<Label<'a>>;
|
||||
static_assertions::assert_impl_all!(DeviceDescriptor<'_>: Send, Sync);
|
||||
|
||||
impl Device {
|
||||
#[cfg(custom)]
|
||||
/// Creates Device from custom implementation
|
||||
pub fn from_custom<T: custom::DeviceInterface>(device: T) -> Self {
|
||||
Self {
|
||||
inner: dispatch::DispatchDevice::custom(device),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check for resource cleanups and mapping callbacks. Will block if [`PollType::Wait`] is passed.
|
||||
///
|
||||
/// Return `true` if the queue is empty, or `false` if there are more queue
|
||||
|
||||
@ -200,6 +200,14 @@ impl Instance {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(custom)]
|
||||
/// Creates instance from custom context implementation
|
||||
pub fn from_custom<T: InstanceInterface>(instance: T) -> Self {
|
||||
Self {
|
||||
inner: dispatch::DispatchInstance::Custom(backend::custom::DynContext::new(instance)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves all available [`Adapter`]s that match the given [`Backends`].
|
||||
///
|
||||
/// # Arguments
|
||||
|
||||
@ -90,6 +90,14 @@ impl Drop for QueueWriteBufferView<'_> {
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
#[cfg(custom)]
|
||||
/// Creates Queue from custom implementation
|
||||
pub fn from_custom<T: custom::QueueInterface>(queue: T) -> Self {
|
||||
Self {
|
||||
inner: dispatch::DispatchQueue::custom(queue),
|
||||
}
|
||||
}
|
||||
|
||||
/// Schedule a data write into `buffer` starting at `offset`.
|
||||
///
|
||||
/// This method fails if `data` overruns the size of `buffer` starting at `offset`.
|
||||
|
||||
@ -57,6 +57,8 @@ impl<'a> RenderBundleEncoder<'a> {
|
||||
dispatch::DispatchRenderBundleEncoder::Core(b) => b.finish(desc),
|
||||
#[cfg(webgpu)]
|
||||
dispatch::DispatchRenderBundleEncoder::WebGPU(b) => b.finish(desc),
|
||||
#[cfg(custom)]
|
||||
dispatch::DispatchRenderBundleEncoder::Custom(_) => unimplemented!(),
|
||||
};
|
||||
|
||||
RenderBundle { inner: bundle }
|
||||
|
||||
89
wgpu/src/backend/custom.rs
Normal file
89
wgpu/src/backend/custom.rs
Normal file
@ -0,0 +1,89 @@
|
||||
//! Provides wrappers custom backend implementations
|
||||
|
||||
#![allow(ambiguous_wide_pointer_comparisons)]
|
||||
|
||||
pub use crate::dispatch::*;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
macro_rules! dyn_type {
|
||||
// cloning of arc forbidden
|
||||
// but we still use it to provide Eq,Ord,Hash implementations
|
||||
(pub mut struct $name:ident(dyn $interface:tt)) => {
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct $name(Arc<dyn $interface>);
|
||||
crate::cmp::impl_eq_ord_hash_arc_address!($name => .0);
|
||||
|
||||
impl $name {
|
||||
pub(crate) fn new<T: $interface>(t: T) -> Self {
|
||||
Self(Arc::new(t))
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for $name {
|
||||
type Target = dyn $interface;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::DerefMut for $name {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
Arc::get_mut(&mut self.0).expect("")
|
||||
}
|
||||
}
|
||||
};
|
||||
// cloning of arc is allowed
|
||||
(pub ref struct $name:ident(dyn $interface:tt)) => {
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct $name(Arc<dyn $interface>);
|
||||
crate::cmp::impl_eq_ord_hash_arc_address!($name => .0);
|
||||
|
||||
impl $name {
|
||||
pub(crate) fn new<T: $interface>(t: T) -> Self {
|
||||
Self(Arc::new(t))
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for $name {
|
||||
type Target = dyn $interface;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
dyn_type!(pub ref struct DynContext(dyn InstanceInterface));
|
||||
dyn_type!(pub ref struct DynAdapter(dyn AdapterInterface));
|
||||
dyn_type!(pub ref struct DynDevice(dyn DeviceInterface));
|
||||
dyn_type!(pub ref struct DynQueue(dyn QueueInterface));
|
||||
dyn_type!(pub ref struct DynShaderModule(dyn ShaderModuleInterface));
|
||||
dyn_type!(pub ref struct DynBindGroupLayout(dyn BindGroupLayoutInterface));
|
||||
dyn_type!(pub ref struct DynBindGroup(dyn BindGroupInterface));
|
||||
dyn_type!(pub ref struct DynTextureView(dyn TextureViewInterface));
|
||||
dyn_type!(pub ref struct DynSampler(dyn SamplerInterface));
|
||||
dyn_type!(pub ref struct DynBuffer(dyn BufferInterface));
|
||||
dyn_type!(pub ref struct DynTexture(dyn TextureInterface));
|
||||
dyn_type!(pub ref struct DynBlas(dyn BlasInterface));
|
||||
dyn_type!(pub ref struct DynTlas(dyn TlasInterface));
|
||||
dyn_type!(pub ref struct DynQuerySet(dyn QuerySetInterface));
|
||||
dyn_type!(pub ref struct DynPipelineLayout(dyn PipelineLayoutInterface));
|
||||
dyn_type!(pub ref struct DynRenderPipeline(dyn RenderPipelineInterface));
|
||||
dyn_type!(pub ref struct DynComputePipeline(dyn ComputePipelineInterface));
|
||||
dyn_type!(pub ref struct DynPipelineCache(dyn PipelineCacheInterface));
|
||||
dyn_type!(pub mut struct DynCommandEncoder(dyn CommandEncoderInterface));
|
||||
dyn_type!(pub mut struct DynComputePass(dyn ComputePassInterface));
|
||||
dyn_type!(pub mut struct DynRenderPass(dyn RenderPassInterface));
|
||||
dyn_type!(pub ref struct DynCommandBuffer(dyn CommandBufferInterface));
|
||||
dyn_type!(pub mut struct DynRenderBundleEncoder(dyn RenderBundleEncoderInterface));
|
||||
dyn_type!(pub ref struct DynRenderBundle(dyn RenderBundleInterface));
|
||||
dyn_type!(pub ref struct DynSurface(dyn SurfaceInterface));
|
||||
dyn_type!(pub ref struct DynSurfaceOutputDetail(dyn SurfaceOutputDetailInterface));
|
||||
dyn_type!(pub mut struct DynQueueWriteBuffer(dyn QueueWriteBufferInterface));
|
||||
dyn_type!(pub mut struct DynBufferMappedRange(dyn BufferMappedRangeInterface));
|
||||
@ -8,3 +8,6 @@ pub mod wgpu_core;
|
||||
|
||||
#[cfg(wgpu_core)]
|
||||
pub(crate) use wgpu_core::ContextWgpuCore;
|
||||
|
||||
#[cfg(custom)]
|
||||
pub mod custom;
|
||||
|
||||
@ -45,7 +45,7 @@ macro_rules! impl_send_sync {
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) struct ContextWebGpu {
|
||||
pub struct ContextWebGpu {
|
||||
/// `None` if browser does not advertise support for WebGPU.
|
||||
gpu: Option<DefinedNonNullJsValue<webgpu_sys::Gpu>>,
|
||||
/// Unique identifier for this context.
|
||||
@ -1266,13 +1266,13 @@ pub struct WebTexture {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct WebBlas {
|
||||
pub struct WebBlas {
|
||||
/// Unique identifier for this Blas.
|
||||
ident: crate::cmp::Identifier,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct WebTlas {
|
||||
pub struct WebTlas {
|
||||
/// Unique identifier for this Blas.
|
||||
ident: crate::cmp::Identifier,
|
||||
}
|
||||
@ -1306,7 +1306,7 @@ pub struct WebComputePipeline {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct WebPipelineCache {
|
||||
pub struct WebPipelineCache {
|
||||
/// Unique identifier for this PipelineCache.
|
||||
ident: crate::cmp::Identifier,
|
||||
}
|
||||
@ -1363,7 +1363,7 @@ pub struct WebSurface {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct WebSurfaceOutputDetail {
|
||||
pub struct WebSurfaceOutputDetail {
|
||||
/// Unique identifier for this SurfaceOutputDetail.
|
||||
ident: crate::cmp::Identifier,
|
||||
}
|
||||
@ -1445,37 +1445,6 @@ crate::cmp::impl_eq_ord_hash_proxy!(WebSurfaceOutputDetail => .ident);
|
||||
crate::cmp::impl_eq_ord_hash_proxy!(WebQueueWriteBuffer => .ident);
|
||||
crate::cmp::impl_eq_ord_hash_proxy!(WebBufferMappedRange => .ident);
|
||||
|
||||
impl dispatch::InterfaceTypes for ContextWebGpu {
|
||||
type Instance = ContextWebGpu;
|
||||
type Adapter = WebAdapter;
|
||||
type Device = WebDevice;
|
||||
type Queue = WebQueue;
|
||||
type ShaderModule = WebShaderModule;
|
||||
type BindGroupLayout = WebBindGroupLayout;
|
||||
type BindGroup = WebBindGroup;
|
||||
type TextureView = WebTextureView;
|
||||
type Sampler = WebSampler;
|
||||
type Buffer = WebBuffer;
|
||||
type Texture = WebTexture;
|
||||
type Blas = WebBlas;
|
||||
type Tlas = WebTlas;
|
||||
type QuerySet = WebQuerySet;
|
||||
type PipelineLayout = WebPipelineLayout;
|
||||
type RenderPipeline = WebRenderPipeline;
|
||||
type ComputePipeline = WebComputePipeline;
|
||||
type PipelineCache = WebPipelineCache;
|
||||
type CommandEncoder = WebCommandEncoder;
|
||||
type ComputePass = WebComputePassEncoder;
|
||||
type RenderPass = WebRenderPassEncoder;
|
||||
type CommandBuffer = WebCommandBuffer;
|
||||
type RenderBundleEncoder = WebRenderBundleEncoder;
|
||||
type RenderBundle = WebRenderBundle;
|
||||
type Surface = WebSurface;
|
||||
type SurfaceOutputDetail = WebSurfaceOutputDetail;
|
||||
type QueueWriteBuffer = WebQueueWriteBuffer;
|
||||
type BufferMappedRange = WebBufferMappedRange;
|
||||
}
|
||||
|
||||
impl dispatch::InstanceInterface for ContextWebGpu {
|
||||
fn new(_desc: &crate::InstanceDescriptor) -> Self
|
||||
where
|
||||
|
||||
@ -17,7 +17,7 @@ use wgt::WasmNotSendSync;
|
||||
|
||||
use crate::{
|
||||
api,
|
||||
dispatch::{self, BufferMappedRangeInterface, InterfaceTypes},
|
||||
dispatch::{self, BufferMappedRangeInterface},
|
||||
BindingResource, BufferBinding, BufferDescriptor, CompilationInfo, CompilationMessage,
|
||||
CompilationMessageType, ErrorSource, Features, Label, LoadOp, MapMode, Operations,
|
||||
ShaderSource, SurfaceTargetUnsafe, TextureDescriptor,
|
||||
@ -742,37 +742,6 @@ crate::cmp::impl_eq_ord_hash_proxy!(CoreSurfaceOutputDetail => .surface_id);
|
||||
crate::cmp::impl_eq_ord_hash_proxy!(CoreQueueWriteBuffer => .mapping.ptr);
|
||||
crate::cmp::impl_eq_ord_hash_proxy!(CoreBufferMappedRange => .ptr);
|
||||
|
||||
impl InterfaceTypes for ContextWgpuCore {
|
||||
type Instance = ContextWgpuCore;
|
||||
type Adapter = CoreAdapter;
|
||||
type Device = CoreDevice;
|
||||
type Queue = CoreQueue;
|
||||
type ShaderModule = CoreShaderModule;
|
||||
type BindGroupLayout = CoreBindGroupLayout;
|
||||
type BindGroup = CoreBindGroup;
|
||||
type TextureView = CoreTextureView;
|
||||
type Sampler = CoreSampler;
|
||||
type Buffer = CoreBuffer;
|
||||
type Texture = CoreTexture;
|
||||
type Blas = CoreBlas;
|
||||
type Tlas = CoreTlas;
|
||||
type QuerySet = CoreQuerySet;
|
||||
type PipelineLayout = CorePipelineLayout;
|
||||
type RenderPipeline = CoreRenderPipeline;
|
||||
type ComputePipeline = CoreComputePipeline;
|
||||
type PipelineCache = CorePipelineCache;
|
||||
type CommandEncoder = CoreCommandEncoder;
|
||||
type ComputePass = CoreComputePass;
|
||||
type RenderPass = CoreRenderPass;
|
||||
type CommandBuffer = CoreCommandBuffer;
|
||||
type RenderBundleEncoder = CoreRenderBundleEncoder;
|
||||
type RenderBundle = CoreRenderBundle;
|
||||
type Surface = CoreSurface;
|
||||
type SurfaceOutputDetail = CoreSurfaceOutputDetail;
|
||||
type QueueWriteBuffer = CoreQueueWriteBuffer;
|
||||
type BufferMappedRange = CoreBufferMappedRange;
|
||||
}
|
||||
|
||||
impl dispatch::InstanceInterface for ContextWgpuCore {
|
||||
fn new(desc: &wgt::InstanceDescriptor) -> Self
|
||||
where
|
||||
|
||||
@ -10,13 +10,19 @@
|
||||
|
||||
#![allow(drop_bounds)] // This exists to remind implementors to impl drop.
|
||||
#![allow(clippy::too_many_arguments)] // It's fine.
|
||||
#![allow(missing_docs, clippy::missing_safety_doc)] // Interfaces are not documented
|
||||
|
||||
use crate::{WasmNotSend, WasmNotSendSync};
|
||||
|
||||
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
||||
use core::{any::Any, fmt::Debug, future::Future, hash::Hash, ops::Range, pin::Pin};
|
||||
|
||||
use crate::backend;
|
||||
#[cfg(custom)]
|
||||
use crate::backend::custom::*;
|
||||
#[cfg(webgpu)]
|
||||
use crate::backend::webgpu::*;
|
||||
#[cfg(wgpu_core)]
|
||||
use crate::backend::wgpu_core::*;
|
||||
|
||||
/// Create a single trait with the given supertraits and a blanket impl for all types that implement them.
|
||||
///
|
||||
@ -50,43 +56,9 @@ pub type BufferMapCallback = Box<dyn FnOnce(Result<(), crate::BufferAsyncError>)
|
||||
|
||||
// Common traits on all the interface traits
|
||||
trait_alias!(CommonTraits: Any + Debug + WasmNotSendSync);
|
||||
// Non-object-safe traits that are added as a bound on InterfaceTypes.
|
||||
trait_alias!(ComparisonTraits: PartialEq + Eq + PartialOrd + Ord + Hash);
|
||||
|
||||
/// Types that represent a "Backend" for the wgpu API.
|
||||
pub trait InterfaceTypes {
|
||||
type Instance: InstanceInterface + ComparisonTraits;
|
||||
type Adapter: AdapterInterface + ComparisonTraits;
|
||||
type Device: DeviceInterface + ComparisonTraits;
|
||||
type Queue: QueueInterface + ComparisonTraits;
|
||||
type ShaderModule: ShaderModuleInterface + ComparisonTraits;
|
||||
type BindGroupLayout: BindGroupLayoutInterface + ComparisonTraits;
|
||||
type BindGroup: BindGroupInterface + ComparisonTraits;
|
||||
type TextureView: TextureViewInterface + ComparisonTraits;
|
||||
type Sampler: SamplerInterface + ComparisonTraits;
|
||||
type Buffer: BufferInterface + ComparisonTraits;
|
||||
type Texture: TextureInterface + ComparisonTraits;
|
||||
type Blas: BlasInterface + ComparisonTraits;
|
||||
type Tlas: TlasInterface + ComparisonTraits;
|
||||
type QuerySet: QuerySetInterface + ComparisonTraits;
|
||||
type PipelineLayout: PipelineLayoutInterface + ComparisonTraits;
|
||||
type RenderPipeline: RenderPipelineInterface + ComparisonTraits;
|
||||
type ComputePipeline: ComputePipelineInterface + ComparisonTraits;
|
||||
type PipelineCache: PipelineCacheInterface + ComparisonTraits;
|
||||
type CommandEncoder: CommandEncoderInterface + ComparisonTraits;
|
||||
type ComputePass: ComputePassInterface + ComparisonTraits;
|
||||
type RenderPass: RenderPassInterface + ComparisonTraits;
|
||||
type CommandBuffer: CommandBufferInterface + ComparisonTraits;
|
||||
type RenderBundleEncoder: RenderBundleEncoderInterface + ComparisonTraits;
|
||||
type RenderBundle: RenderBundleInterface + ComparisonTraits;
|
||||
type Surface: SurfaceInterface + ComparisonTraits;
|
||||
type SurfaceOutputDetail: SurfaceOutputDetailInterface + ComparisonTraits;
|
||||
type QueueWriteBuffer: QueueWriteBufferInterface + ComparisonTraits;
|
||||
type BufferMappedRange: BufferMappedRangeInterface + ComparisonTraits;
|
||||
}
|
||||
|
||||
pub trait InstanceInterface: CommonTraits {
|
||||
fn new(desc: &wgt::InstanceDescriptor) -> Self
|
||||
fn new(desc: &crate::InstanceDescriptor) -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
@ -138,7 +110,7 @@ pub trait DeviceInterface: CommonTraits {
|
||||
fn create_shader_module(
|
||||
&self,
|
||||
desc: crate::ShaderModuleDescriptor<'_>,
|
||||
shader_bound_checks: wgt::ShaderRuntimeChecks,
|
||||
shader_bound_checks: crate::ShaderRuntimeChecks,
|
||||
) -> DispatchShaderModule;
|
||||
unsafe fn create_shader_module_spirv(
|
||||
&self,
|
||||
@ -196,7 +168,7 @@ pub trait DeviceInterface: CommonTraits {
|
||||
fn poll(&self, poll_type: crate::PollType) -> Result<crate::PollStatus, crate::PollError>;
|
||||
|
||||
fn get_internal_counters(&self) -> crate::InternalCounters;
|
||||
fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport>;
|
||||
fn generate_allocator_report(&self) -> Option<crate::AllocatorReport>;
|
||||
|
||||
fn destroy(&self);
|
||||
}
|
||||
@ -208,8 +180,8 @@ pub trait QueueInterface: CommonTraits {
|
||||
fn validate_write_buffer(
|
||||
&self,
|
||||
buffer: &DispatchBuffer,
|
||||
offset: wgt::BufferAddress,
|
||||
size: wgt::BufferSize,
|
||||
offset: crate::BufferAddress,
|
||||
size: crate::BufferSize,
|
||||
) -> Option<()>;
|
||||
fn write_staging_buffer(
|
||||
&self,
|
||||
@ -258,7 +230,7 @@ pub trait BufferInterface: CommonTraits {
|
||||
#[cfg(webgpu)]
|
||||
fn get_mapped_range_as_array_buffer(
|
||||
&self,
|
||||
sub_range: Range<wgt::BufferAddress>,
|
||||
sub_range: Range<crate::BufferAddress>,
|
||||
) -> Option<js_sys::ArrayBuffer>;
|
||||
|
||||
fn unmap(&self);
|
||||
@ -523,7 +495,7 @@ pub trait CommandBufferInterface: CommonTraits {}
|
||||
pub trait RenderBundleInterface: CommonTraits {}
|
||||
|
||||
pub trait SurfaceInterface: CommonTraits {
|
||||
fn get_capabilities(&self, adapter: &DispatchAdapter) -> wgt::SurfaceCapabilities;
|
||||
fn get_capabilities(&self, adapter: &DispatchAdapter) -> crate::SurfaceCapabilities;
|
||||
|
||||
fn configure(&self, device: &DispatchDevice, config: &crate::SurfaceConfiguration);
|
||||
fn get_current_texture(
|
||||
@ -561,25 +533,26 @@ pub trait BufferMappedRangeInterface: CommonTraits {
|
||||
/// arguments. These are similarly free when there is only one backend.
|
||||
///
|
||||
/// In the future, we may want a truly generic backend, which could be extended from this enum.
|
||||
macro_rules! dispatch_types_inner {
|
||||
macro_rules! dispatch_types {
|
||||
(
|
||||
wgpu_core = $wgpu_core_context:ty;
|
||||
webgpu = $webgpu_context:ty;
|
||||
{ref type $name:ident = InterfaceTypes::$subtype:ident: $trait:ident};
|
||||
ref type $name:ident: $interface:ident = $core_type:ident,$webgpu_type:ident,$custom_type:ident
|
||||
) => {
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
|
||||
pub enum $name {
|
||||
#[cfg(wgpu_core)]
|
||||
Core(Arc<<$wgpu_core_context as InterfaceTypes>::$subtype>),
|
||||
Core(Arc<$core_type>),
|
||||
#[cfg(webgpu)]
|
||||
WebGPU(Arc<<$webgpu_context as InterfaceTypes>::$subtype>),
|
||||
WebGPU(Arc<$webgpu_type>),
|
||||
#[allow(clippy::allow_attributes, private_interfaces)]
|
||||
#[cfg(custom)]
|
||||
Custom($custom_type),
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[cfg(wgpu_core)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_core(&self) -> &<$wgpu_core_context as InterfaceTypes>::$subtype {
|
||||
pub fn as_core(&self) -> &$core_type {
|
||||
match self {
|
||||
Self::Core(value) => value,
|
||||
_ => panic!(concat!(stringify!($name), " is not core")),
|
||||
@ -589,7 +562,7 @@ macro_rules! dispatch_types_inner {
|
||||
#[cfg(wgpu_core)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_core_opt(&self) -> Option<&<$wgpu_core_context as InterfaceTypes>::$subtype> {
|
||||
pub fn as_core_opt(&self) -> Option<&$core_type> {
|
||||
match self {
|
||||
Self::Core(value) => Some(value),
|
||||
_ => None,
|
||||
@ -599,7 +572,7 @@ macro_rules! dispatch_types_inner {
|
||||
#[cfg(webgpu)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_webgpu(&self) -> &<$webgpu_context as InterfaceTypes>::$subtype {
|
||||
pub fn as_webgpu(&self) -> &$webgpu_type {
|
||||
match self {
|
||||
Self::WebGPU(value) => value,
|
||||
_ => panic!(concat!(stringify!($name), " is not webgpu")),
|
||||
@ -609,32 +582,38 @@ macro_rules! dispatch_types_inner {
|
||||
#[cfg(webgpu)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_webgpu_opt(&self) -> Option<&<$webgpu_context as InterfaceTypes>::$subtype> {
|
||||
pub fn as_webgpu_opt(&self) -> Option<&$webgpu_type> {
|
||||
match self {
|
||||
Self::WebGPU(value) => Some(value),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(custom)]
|
||||
#[inline]
|
||||
pub fn custom<T: $interface>(t: T) -> Self {
|
||||
Self::Custom($custom_type::new(t))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(wgpu_core)]
|
||||
impl From<<$wgpu_core_context as InterfaceTypes>::$subtype> for $name {
|
||||
impl From<$core_type> for $name {
|
||||
#[inline]
|
||||
fn from(value: <$wgpu_core_context as InterfaceTypes>::$subtype) -> Self {
|
||||
fn from(value: $core_type) -> Self {
|
||||
Self::Core(Arc::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(webgpu)]
|
||||
impl From<<$webgpu_context as InterfaceTypes>::$subtype> for $name {
|
||||
impl From<$webgpu_type> for $name {
|
||||
#[inline]
|
||||
fn from(value: <$webgpu_context as InterfaceTypes>::$subtype) -> Self {
|
||||
fn from(value: $webgpu_type) -> Self {
|
||||
Self::WebGPU(Arc::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for $name {
|
||||
type Target = dyn $trait;
|
||||
type Target = dyn $interface;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@ -643,6 +622,8 @@ macro_rules! dispatch_types_inner {
|
||||
Self::Core(value) => value.as_ref(),
|
||||
#[cfg(webgpu)]
|
||||
Self::WebGPU(value) => value.as_ref(),
|
||||
#[cfg(custom)]
|
||||
Self::Custom(value) => value.deref(),
|
||||
#[cfg(not(any(wgpu_core, webgpu)))]
|
||||
_ => panic!("No context available. You need to enable one of wgpu's backend feature build flags."),
|
||||
}
|
||||
@ -650,23 +631,24 @@ macro_rules! dispatch_types_inner {
|
||||
}
|
||||
};
|
||||
(
|
||||
wgpu_core = $wgpu_core_context:ty;
|
||||
webgpu = $webgpu_context:ty;
|
||||
{mut type $name:ident = InterfaceTypes::$subtype:ident: $trait:ident};
|
||||
mut type $name:ident: $interface:ident = $core_type:ident,$webgpu_type:ident,$custom_type:ident
|
||||
) => {
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum $name {
|
||||
#[cfg(wgpu_core)]
|
||||
Core(<$wgpu_core_context as InterfaceTypes>::$subtype),
|
||||
Core($core_type),
|
||||
#[cfg(webgpu)]
|
||||
WebGPU(<$webgpu_context as InterfaceTypes>::$subtype),
|
||||
WebGPU($webgpu_type),
|
||||
#[allow(clippy::allow_attributes, private_interfaces)]
|
||||
#[cfg(custom)]
|
||||
Custom($custom_type),
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[cfg(wgpu_core)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_core(&self) -> &<$wgpu_core_context as InterfaceTypes>::$subtype {
|
||||
pub fn as_core(&self) -> &$core_type {
|
||||
match self {
|
||||
Self::Core(value) => value,
|
||||
_ => panic!(concat!(stringify!($name), " is not core")),
|
||||
@ -676,7 +658,7 @@ macro_rules! dispatch_types_inner {
|
||||
#[cfg(wgpu_core)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_core_mut(&mut self) -> &mut <$wgpu_core_context as InterfaceTypes>::$subtype {
|
||||
pub fn as_core_mut(&mut self) -> &mut $core_type {
|
||||
match self {
|
||||
Self::Core(value) => value,
|
||||
_ => panic!(concat!(stringify!($name), " is not core")),
|
||||
@ -686,7 +668,7 @@ macro_rules! dispatch_types_inner {
|
||||
#[cfg(wgpu_core)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_core_opt(&self) -> Option<&<$wgpu_core_context as InterfaceTypes>::$subtype> {
|
||||
pub fn as_core_opt(&self) -> Option<&$core_type> {
|
||||
match self {
|
||||
Self::Core(value) => Some(value),
|
||||
_ => None,
|
||||
@ -698,7 +680,7 @@ macro_rules! dispatch_types_inner {
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_core_mut_opt(
|
||||
&mut self,
|
||||
) -> Option<&mut <$wgpu_core_context as InterfaceTypes>::$subtype> {
|
||||
) -> Option<&mut $core_type> {
|
||||
match self {
|
||||
Self::Core(value) => Some(value),
|
||||
_ => None,
|
||||
@ -708,7 +690,7 @@ macro_rules! dispatch_types_inner {
|
||||
#[cfg(webgpu)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_webgpu(&self) -> &<$webgpu_context as InterfaceTypes>::$subtype {
|
||||
pub fn as_webgpu(&self) -> &$webgpu_type {
|
||||
match self {
|
||||
Self::WebGPU(value) => value,
|
||||
_ => panic!(concat!(stringify!($name), " is not webgpu")),
|
||||
@ -718,7 +700,7 @@ macro_rules! dispatch_types_inner {
|
||||
#[cfg(webgpu)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_webgpu_mut(&mut self) -> &mut <$webgpu_context as InterfaceTypes>::$subtype {
|
||||
pub fn as_webgpu_mut(&mut self) -> &mut $webgpu_type {
|
||||
match self {
|
||||
Self::WebGPU(value) => value,
|
||||
_ => panic!(concat!(stringify!($name), " is not webgpu")),
|
||||
@ -728,7 +710,7 @@ macro_rules! dispatch_types_inner {
|
||||
#[cfg(webgpu)]
|
||||
#[inline]
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_webgpu_opt(&self) -> Option<&<$webgpu_context as InterfaceTypes>::$subtype> {
|
||||
pub fn as_webgpu_opt(&self) -> Option<&$webgpu_type> {
|
||||
match self {
|
||||
Self::WebGPU(value) => Some(value),
|
||||
_ => None,
|
||||
@ -740,32 +722,38 @@ macro_rules! dispatch_types_inner {
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
pub fn as_webgpu_mut_opt(
|
||||
&mut self,
|
||||
) -> Option<&mut <$webgpu_context as InterfaceTypes>::$subtype> {
|
||||
) -> Option<&mut $webgpu_type> {
|
||||
match self {
|
||||
Self::WebGPU(value) => Some(value),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(custom)]
|
||||
#[inline]
|
||||
pub fn custom<T: $interface>(t: T) -> Self {
|
||||
Self::Custom($custom_type::new(t))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(wgpu_core)]
|
||||
impl From<<$wgpu_core_context as InterfaceTypes>::$subtype> for $name {
|
||||
impl From<$core_type> for $name {
|
||||
#[inline]
|
||||
fn from(value: <$wgpu_core_context as InterfaceTypes>::$subtype) -> Self {
|
||||
fn from(value: $core_type) -> Self {
|
||||
Self::Core(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(webgpu)]
|
||||
impl From<<$webgpu_context as InterfaceTypes>::$subtype> for $name {
|
||||
impl From<$webgpu_type> for $name {
|
||||
#[inline]
|
||||
fn from(value: <$webgpu_context as InterfaceTypes>::$subtype) -> Self {
|
||||
fn from(value: $webgpu_type) -> Self {
|
||||
Self::WebGPU(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for $name {
|
||||
type Target = dyn $trait;
|
||||
type Target = dyn $interface;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@ -774,6 +762,8 @@ macro_rules! dispatch_types_inner {
|
||||
Self::Core(value) => value,
|
||||
#[cfg(webgpu)]
|
||||
Self::WebGPU(value) => value,
|
||||
#[cfg(custom)]
|
||||
Self::Custom(value) => value.deref(),
|
||||
#[cfg(not(any(wgpu_core, webgpu)))]
|
||||
_ => panic!("No context available. You need to enable one of wgpu's backend feature build flags."),
|
||||
}
|
||||
@ -788,6 +778,8 @@ macro_rules! dispatch_types_inner {
|
||||
Self::Core(value) => value,
|
||||
#[cfg(webgpu)]
|
||||
Self::WebGPU(value) => value,
|
||||
#[cfg(custom)]
|
||||
Self::Custom(value) => value.deref_mut(),
|
||||
#[cfg(not(any(wgpu_core, webgpu)))]
|
||||
_ => panic!("No context available. You need to enable one of wgpu's backend feature build flags."),
|
||||
}
|
||||
@ -796,55 +788,31 @@ macro_rules! dispatch_types_inner {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! dispatch_types {
|
||||
(
|
||||
wgpu_core = $wgpu_core_context:ty;
|
||||
webgpu = $webgpu_context:ty;
|
||||
{$(
|
||||
$type:tt;
|
||||
)*}
|
||||
) => {
|
||||
$(
|
||||
dispatch_types_inner!{
|
||||
wgpu_core = backend::ContextWgpuCore;
|
||||
webgpu = backend::ContextWebGpu;
|
||||
$type;
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
dispatch_types! {
|
||||
wgpu_core = backend::ContextWgpuCore;
|
||||
webgpu = backend::ContextWebGpu;
|
||||
{
|
||||
{ref type DispatchInstance = InterfaceTypes::Instance: InstanceInterface};
|
||||
{ref type DispatchAdapter = InterfaceTypes::Adapter: AdapterInterface};
|
||||
{ref type DispatchDevice = InterfaceTypes::Device: DeviceInterface};
|
||||
{ref type DispatchQueue = InterfaceTypes::Queue: QueueInterface};
|
||||
{ref type DispatchShaderModule = InterfaceTypes::ShaderModule: ShaderModuleInterface};
|
||||
{ref type DispatchBindGroupLayout = InterfaceTypes::BindGroupLayout: BindGroupLayoutInterface};
|
||||
{ref type DispatchBindGroup = InterfaceTypes::BindGroup: BindGroupInterface};
|
||||
{ref type DispatchTextureView = InterfaceTypes::TextureView: TextureViewInterface};
|
||||
{ref type DispatchSampler = InterfaceTypes::Sampler: SamplerInterface};
|
||||
{ref type DispatchBuffer = InterfaceTypes::Buffer: BufferInterface};
|
||||
{ref type DispatchTexture = InterfaceTypes::Texture: TextureInterface};
|
||||
{ref type DispatchBlas = InterfaceTypes::Blas: BlasInterface};
|
||||
{ref type DispatchTlas = InterfaceTypes::Tlas: TlasInterface};
|
||||
{ref type DispatchQuerySet = InterfaceTypes::QuerySet: QuerySetInterface};
|
||||
{ref type DispatchPipelineLayout = InterfaceTypes::PipelineLayout: PipelineLayoutInterface};
|
||||
{ref type DispatchRenderPipeline = InterfaceTypes::RenderPipeline: RenderPipelineInterface};
|
||||
{ref type DispatchComputePipeline = InterfaceTypes::ComputePipeline: ComputePipelineInterface};
|
||||
{ref type DispatchPipelineCache = InterfaceTypes::PipelineCache: PipelineCacheInterface};
|
||||
{mut type DispatchCommandEncoder = InterfaceTypes::CommandEncoder: CommandEncoderInterface};
|
||||
{mut type DispatchComputePass = InterfaceTypes::ComputePass: ComputePassInterface};
|
||||
{mut type DispatchRenderPass = InterfaceTypes::RenderPass: RenderPassInterface};
|
||||
{mut type DispatchCommandBuffer = InterfaceTypes::CommandBuffer: CommandBufferInterface};
|
||||
{mut type DispatchRenderBundleEncoder = InterfaceTypes::RenderBundleEncoder: RenderBundleEncoderInterface};
|
||||
{ref type DispatchRenderBundle = InterfaceTypes::RenderBundle: RenderBundleInterface};
|
||||
{ref type DispatchSurface = InterfaceTypes::Surface: SurfaceInterface};
|
||||
{ref type DispatchSurfaceOutputDetail = InterfaceTypes::SurfaceOutputDetail: SurfaceOutputDetailInterface};
|
||||
{mut type DispatchQueueWriteBuffer = InterfaceTypes::QueueWriteBuffer: QueueWriteBufferInterface};
|
||||
{mut type DispatchBufferMappedRange = InterfaceTypes::BufferMappedRange: BufferMappedRangeInterface};
|
||||
}
|
||||
}
|
||||
dispatch_types! {ref type DispatchInstance: InstanceInterface = ContextWgpuCore, ContextWebGpu, DynContext}
|
||||
dispatch_types! {ref type DispatchAdapter: AdapterInterface = CoreAdapter, WebAdapter, DynAdapter}
|
||||
dispatch_types! {ref type DispatchDevice: DeviceInterface = CoreDevice, WebDevice, DynDevice}
|
||||
dispatch_types! {ref type DispatchQueue: QueueInterface = CoreQueue, WebQueue, DynQueue}
|
||||
dispatch_types! {ref type DispatchShaderModule: ShaderModuleInterface = CoreShaderModule, WebShaderModule, DynShaderModule}
|
||||
dispatch_types! {ref type DispatchBindGroupLayout: BindGroupLayoutInterface = CoreBindGroupLayout, WebBindGroupLayout, DynBindGroupLayout}
|
||||
dispatch_types! {ref type DispatchBindGroup: BindGroupInterface = CoreBindGroup, WebBindGroup, DynBindGroup}
|
||||
dispatch_types! {ref type DispatchTextureView: TextureViewInterface = CoreTextureView, WebTextureView, DynTextureView}
|
||||
dispatch_types! {ref type DispatchSampler: SamplerInterface = CoreSampler, WebSampler, DynSampler}
|
||||
dispatch_types! {ref type DispatchBuffer: BufferInterface = CoreBuffer, WebBuffer, DynBuffer}
|
||||
dispatch_types! {ref type DispatchTexture: TextureInterface = CoreTexture, WebTexture, DynTexture}
|
||||
dispatch_types! {ref type DispatchBlas: BlasInterface = CoreBlas, WebBlas, DynBlas}
|
||||
dispatch_types! {ref type DispatchTlas: TlasInterface = CoreTlas, WebTlas, DynTlas}
|
||||
dispatch_types! {ref type DispatchQuerySet: QuerySetInterface = CoreQuerySet, WebQuerySet, DynQuerySet}
|
||||
dispatch_types! {ref type DispatchPipelineLayout: PipelineLayoutInterface = CorePipelineLayout, WebPipelineLayout, DynPipelineLayout}
|
||||
dispatch_types! {ref type DispatchRenderPipeline: RenderPipelineInterface = CoreRenderPipeline, WebRenderPipeline, DynRenderPipeline}
|
||||
dispatch_types! {ref type DispatchComputePipeline: ComputePipelineInterface = CoreComputePipeline, WebComputePipeline, DynComputePipeline}
|
||||
dispatch_types! {ref type DispatchPipelineCache: PipelineCacheInterface = CorePipelineCache, WebPipelineCache, DynPipelineCache}
|
||||
dispatch_types! {mut type DispatchCommandEncoder: CommandEncoderInterface = CoreCommandEncoder, WebCommandEncoder, DynCommandEncoder}
|
||||
dispatch_types! {mut type DispatchComputePass: ComputePassInterface = CoreComputePass, WebComputePassEncoder, DynComputePass}
|
||||
dispatch_types! {mut type DispatchRenderPass: RenderPassInterface = CoreRenderPass, WebRenderPassEncoder, DynRenderPass}
|
||||
dispatch_types! {ref type DispatchCommandBuffer: CommandBufferInterface = CoreCommandBuffer, WebCommandBuffer, DynCommandBuffer}
|
||||
dispatch_types! {mut type DispatchRenderBundleEncoder: RenderBundleEncoderInterface = CoreRenderBundleEncoder, WebRenderBundleEncoder, DynRenderBundleEncoder}
|
||||
dispatch_types! {ref type DispatchRenderBundle: RenderBundleInterface = CoreRenderBundle, WebRenderBundle, DynRenderBundle}
|
||||
dispatch_types! {ref type DispatchSurface: SurfaceInterface = CoreSurface, WebSurface, DynSurface}
|
||||
dispatch_types! {ref type DispatchSurfaceOutputDetail: SurfaceOutputDetailInterface = CoreSurfaceOutputDetail, WebSurfaceOutputDetail, DynSurfaceOutputDetail}
|
||||
dispatch_types! {mut type DispatchQueueWriteBuffer: QueueWriteBufferInterface = CoreQueueWriteBuffer, WebQueueWriteBuffer, DynQueueWriteBuffer}
|
||||
dispatch_types! {mut type DispatchBufferMappedRange: BufferMappedRangeInterface = CoreBufferMappedRange, WebBufferMappedRange, DynBufferMappedRange}
|
||||
|
||||
@ -63,12 +63,15 @@ pub mod util;
|
||||
//
|
||||
//
|
||||
|
||||
#[cfg(custom)]
|
||||
pub use backend::custom;
|
||||
|
||||
pub use api::*;
|
||||
pub use wgt::{
|
||||
AdapterInfo, AddressMode, AstcBlock, AstcChannel, Backend, BackendOptions, Backends,
|
||||
BindGroupLayoutEntry, BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState,
|
||||
BufferAddress, BufferBindingType, BufferSize, BufferTransition, BufferUsages, BufferUses,
|
||||
Color, ColorTargetState, ColorWrites, CommandBufferDescriptor, CompareFunction,
|
||||
AdapterInfo, AddressMode, AllocatorReport, AstcBlock, AstcChannel, Backend, BackendOptions,
|
||||
Backends, BindGroupLayoutEntry, BindingType, BlendComponent, BlendFactor, BlendOperation,
|
||||
BlendState, BufferAddress, BufferBindingType, BufferSize, BufferTransition, BufferUsages,
|
||||
BufferUses, Color, ColorTargetState, ColorWrites, CommandBufferDescriptor, CompareFunction,
|
||||
CompositeAlphaMode, CopyExternalImageDestInfo, CoreCounters, DepthBiasState, DepthStencilState,
|
||||
DeviceLostReason, DeviceType, DownlevelCapabilities, DownlevelFlags, DownlevelLimits,
|
||||
Dx12BackendOptions, Dx12Compiler, DxcShaderModel, DynamicOffset, Extent3d, Face, Features,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user