use alloc::boxed::Box;
use async_trait::async_trait;
use core::fmt::Debug;
use core::ops::{Deref, Range};
use crate::descriptor::{
BindGroupDescriptor, BindGroupLayoutDescriptor, BufferDescriptor, ImageCopyExternalImage,
ImageCopyTexture, ImageDataLayout, RenderPassDescriptor, RenderPipelineDescriptor,
SamplerDescriptor, ShaderDescriptor, TextureDescriptor,
};
use crate::primitive::{BufferSize, Color, Extent2D, Extent3D, MipmapHint};
pub trait GPU: Sized + for<'s> GPURefTypes<'s, Self> {
type Features: Debug;
type Device: GPUDevice<Self>;
type Buffer: Debug;
type Texture: Debug;
type Sampler: Debug;
type Shader: Debug;
type RenderPipeline: Debug;
type RenderPass: Debug;
type BindGroup: Debug;
type BindGroupLayout: Debug;
}
pub trait GPURefTypes<'s, G: GPU> {
type RenderPassEncoder: GPURenderPassEncoder<'s, G>;
type BufferView: Debug + Deref<Target = [u8]> + 's;
}
pub trait GPUWebExt: GPU {
type ImageSource: Debug;
type Device: GPUDevice<Self> + GPUDeviceWebExt<Self>;
}
pub trait GPUDeviceWebExt<G: GPUWebExt>: GPUDevice<G> {
fn generate_mipmap(&self, texture: &G::Texture, hint: MipmapHint);
fn copy_external_image_to_texture(
&self,
src: ImageCopyExternalImage<G>,
dst: ImageCopyTexture<G>,
size: Extent2D,
);
}
#[async_trait(?Send)]
pub trait GPUDevice<G: GPU> {
fn features(&self) -> G::Features;
fn create_buffer(&self, descriptor: BufferDescriptor) -> G::Buffer;
fn create_texture(&self, descriptor: TextureDescriptor) -> G::Texture;
fn create_sampler(&self, descriptor: SamplerDescriptor) -> G::Sampler;
fn create_shader(&self, descriptor: ShaderDescriptor) -> G::Shader;
fn create_render_pipeline(&self, descriptor: RenderPipelineDescriptor<G>) -> G::RenderPipeline;
fn create_render_pass(&self, descriptor: RenderPassDescriptor<G>) -> G::RenderPass;
fn create_bind_group_layout(&self, descriptor: BindGroupLayoutDescriptor)
-> G::BindGroupLayout;
fn create_bind_group(&self, descriptor: BindGroupDescriptor<G>) -> G::BindGroup;
fn render<'a>(
&'a self,
pass: &'a G::RenderPass,
) -> <G as GPURefTypes<'a, G>>::RenderPassEncoder;
async fn read_buffer<'a>(
&self,
buffer: &'a G::Buffer,
range: Range<BufferSize>,
) -> Result<<G as GPURefTypes<'a, G>>::BufferView, ()>;
fn write_buffer(&self, buffer: &G::Buffer, buffer_offset: BufferSize, data: &[u8]);
fn copy_buffer(
&self,
src: &G::Buffer,
src_offset: BufferSize,
dst: &G::Buffer,
dst_offset: BufferSize,
size: BufferSize,
);
fn write_texture(
&self,
texture: ImageCopyTexture<G>,
data: &[u8],
layout: ImageDataLayout,
size: Extent3D,
);
fn copy_texture(&self, src: ImageCopyTexture<G>, dst: ImageCopyTexture<G>, size: Extent3D);
fn copy_texture_to_buffer(
&self,
src: ImageCopyTexture<G>,
dst: &G::Buffer,
layout: ImageDataLayout,
size: Extent3D,
);
fn is_lost(&self) -> bool;
fn flush(&self);
fn present(&self);
fn resize_surface(&self, size: Extent2D);
}
pub trait GPURenderPassEncoder<'a, G: GPU> {
fn pipeline(&self, pipeline: &'a G::RenderPipeline);
fn index(&self, buffer: &'a G::Buffer);
fn vertex(&self, slot: u32, buffer: &'a G::Buffer, offset: BufferSize);
fn bind_group(&self, slot: u32, bind_group: &'a G::BindGroup, offsets: &[u32]);
fn draw(&self, vertices: Range<u32>, instances: Range<u32>);
fn draw_indexed(&self, indices: Range<u32>, instances: Range<u32>);
fn viewport(&self, x: f32, y: f32, width: f32, height: f32, min_depth: f32, max_depth: f32);
fn scissor_rect(&self, x: u32, y: u32, width: u32, height: u32);
fn blend_const(&self, color: Color);
fn stencil_ref(&self, reference: u32);
fn submit(self);
}