mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-01-09 14:48:08 -05:00
Rename custom_backend example
This commit is contained in:
committed by
Erich Gubler
parent
a48387756c
commit
f109a6966a
18
examples/standalone/custom_backend/Cargo.toml
Normal file
18
examples/standalone/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
|
||||
345
examples/standalone/custom_backend/src/custom.rs
Normal file
345
examples/standalone/custom_backend/src/custom.rs
Normal file
@@ -0,0 +1,345 @@
|
||||
#![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(Ok(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<'_>,
|
||||
) -> 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!()
|
||||
}
|
||||
}
|
||||
42
examples/standalone/custom_backend/src/main.rs
Normal file
42
examples/standalone/custom_backend/src/main.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
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()
|
||||
})
|
||||
.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);
|
||||
}
|
||||
Reference in New Issue
Block a user