use crate::capabilities::Capabilities;
use crate::descriptors::{
BindGroupDesc, BindGroupLayoutDesc, BufferDesc, ComputePipelineDesc, RenderPipelineDesc,
SamplerDesc, ShaderModuleDesc, TextureDesc, TextureViewDesc,
};
use crate::encoder::CommandEncoder;
use crate::error::GpuError;
use crate::queue::Queue;
use crate::surface::Surface;
use crate::{
BlasDesc, RayQueryBindGroupDesc, RayQueryBindGroupLayoutDesc, RayQueryLimits, TlasDesc,
TlasInstance,
};
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::future::Future;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use std::sync::Arc;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
pub trait WindowSource: HasWindowHandle + HasDisplayHandle + std::fmt::Debug + Send + Sync {}
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
impl<T: HasWindowHandle + HasDisplayHandle + std::fmt::Debug + Send + Sync> WindowSource for T {}
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub trait WindowSource: HasWindowHandle + HasDisplayHandle + std::fmt::Debug {}
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
impl<T: HasWindowHandle + HasDisplayHandle + std::fmt::Debug> WindowSource for T {}
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
pub type WindowTarget = Arc<dyn WindowSource>;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub type WindowTarget = web_sys::HtmlCanvasElement;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum PowerPreference {
#[default]
HighPerformance,
LowPower,
}
#[derive(Clone, Copy, Debug, Default)]
pub struct DeviceDesc {
pub power: PowerPreference,
pub resource_memory_limit_bytes: Option<u64>,
}
#[derive(Clone, Copy, Default, PartialEq, Eq, Debug)]
pub struct ResourceMemory {
pub buffer_bytes: u64,
pub texture_bytes: u64,
pub peak_bytes: u64,
}
impl ResourceMemory {
#[must_use]
pub const fn total_bytes(self) -> u64 {
self.buffer_bytes.saturating_add(self.texture_bytes)
}
}
#[derive(Debug)]
pub struct Opened<D: Device> {
pub device: D,
pub queue: D::Queue,
pub surface: Option<D::Surface>,
}
pub trait Device: Sized + 'static {
type Buffer: std::fmt::Debug;
type Texture: std::fmt::Debug;
type TextureView: std::fmt::Debug;
type Sampler: std::fmt::Debug;
type ShaderModule: std::fmt::Debug;
type BindGroupLayout: std::fmt::Debug;
type BindGroup: std::fmt::Debug;
type Pipeline: std::fmt::Debug;
type QuerySet: std::fmt::Debug;
type Blas: std::fmt::Debug;
type Tlas: std::fmt::Debug;
type CommandEncoder: CommandEncoder<Self>;
type Queue: Queue<Self>;
type Surface: Surface<Self>;
fn open_async(
desc: &DeviceDesc,
window: Option<WindowTarget>,
) -> impl Future<Output = Result<Opened<Self>, GpuError>>;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
fn open_blocking(
desc: &DeviceDesc,
window: Option<WindowTarget>,
) -> Result<Opened<Self>, GpuError>;
fn create_buffer(&self, desc: &BufferDesc) -> Result<Self::Buffer, GpuError>;
fn create_texture(&self, desc: &TextureDesc) -> Result<Self::Texture, GpuError>;
fn create_texture_view(
&self,
texture: &Self::Texture,
desc: &TextureViewDesc,
) -> Self::TextureView;
fn create_sampler(&self, desc: &SamplerDesc) -> Self::Sampler;
fn create_shader_module(
&self,
desc: &ShaderModuleDesc<'_>,
) -> Result<Self::ShaderModule, GpuError>;
fn create_bind_group_layout(&self, desc: &BindGroupLayoutDesc<'_>) -> Self::BindGroupLayout;
fn create_bind_group(&self, desc: &BindGroupDesc<'_, Self>) -> Self::BindGroup;
fn create_render_pipeline(
&self,
desc: &RenderPipelineDesc<'_, Self>,
) -> Result<Self::Pipeline, GpuError>;
fn create_compute_pipeline(
&self,
desc: &ComputePipelineDesc<'_, Self>,
) -> Result<Self::Pipeline, GpuError>;
fn create_command_encoder(&self) -> Self::CommandEncoder;
fn create_timestamp_query_set(&self, count: u32) -> Result<Self::QuerySet, GpuError>;
fn capabilities(&self) -> &Capabilities;
fn check_errors(&self) -> Result<(), GpuError> {
Ok(())
}
fn resource_memory(&self) -> ResourceMemory {
ResourceMemory::default()
}
fn ray_query_limits(&self) -> Result<RayQueryLimits, GpuError> {
Err(GpuError::Capability { name: "ray query" })
}
fn create_blas(&self, _desc: &BlasDesc<'_>) -> Result<Self::Blas, GpuError> {
Err(GpuError::Capability { name: "ray query" })
}
fn create_tlas(&self, _desc: &TlasDesc) -> Result<Self::Tlas, GpuError> {
Err(GpuError::Capability { name: "ray query" })
}
fn set_tlas_instance(
&self,
_tlas: &mut Self::Tlas,
_index: u32,
_instance: Option<TlasInstance<'_, Self>>,
) -> Result<(), GpuError> {
Err(GpuError::Capability { name: "ray query" })
}
fn create_ray_query_bind_group_layout(
&self,
_desc: &RayQueryBindGroupLayoutDesc<'_>,
) -> Result<Self::BindGroupLayout, GpuError> {
Err(GpuError::Capability { name: "ray query" })
}
fn create_ray_query_bind_group(
&self,
_desc: &RayQueryBindGroupDesc<'_, Self>,
) -> Result<Self::BindGroup, GpuError> {
Err(GpuError::Capability { name: "ray query" })
}
}
pub trait RayQueryDevice: Device {
fn ray_query_limits(&self) -> Result<RayQueryLimits, GpuError> {
Device::ray_query_limits(self)
}
fn create_blas(&self, desc: &BlasDesc<'_>) -> Result<Self::Blas, GpuError> {
Device::create_blas(self, desc)
}
fn create_tlas(&self, desc: &TlasDesc) -> Result<Self::Tlas, GpuError> {
Device::create_tlas(self, desc)
}
fn set_tlas_instance(
&self,
tlas: &mut Self::Tlas,
index: u32,
instance: Option<TlasInstance<'_, Self>>,
) -> Result<(), GpuError> {
Device::set_tlas_instance(self, tlas, index, instance)
}
fn create_ray_query_bind_group_layout(
&self,
desc: &RayQueryBindGroupLayoutDesc<'_>,
) -> Result<Self::BindGroupLayout, GpuError> {
Device::create_ray_query_bind_group_layout(self, desc)
}
fn create_ray_query_bind_group(
&self,
desc: &RayQueryBindGroupDesc<'_, Self>,
) -> Result<Self::BindGroup, GpuError> {
Device::create_ray_query_bind_group(self, desc)
}
}
impl<D: Device> RayQueryDevice for D {}