use crate::os;
use std::any::Any;
use serde::{Deserialize, Serialize};
use std::hash::Hash;
use maths_rs::max;
#[cfg(target_os = "windows")]
pub mod d3d12;
type Error = super::Error;
#[macro_export]
macro_rules! data {
() => {
None::<&[()]>
};
($input:expr) => {
Some($input)
}
}
#[cfg(target_os = "windows")]
#[macro_export]
macro_rules! gfx_debug_name {
($object:expr, $name:expr) => {
d3d12_debug_name($object, $name);
}
}
#[derive(Copy, Clone)]
pub struct Size3 {
pub x: u32,
pub y: u32,
pub z: u32,
}
#[derive(Copy, Clone)]
pub struct Region {
pub left: u32,
pub top: u32,
pub front: u32,
pub right: u32,
pub bottom: u32,
pub back: u32
}
#[derive(Copy, Clone)]
pub struct Viewport {
pub x: f32,
pub y: f32,
pub width: f32,
pub height: f32,
pub min_depth: f32,
pub max_depth: f32,
}
#[derive(Copy, Clone)]
pub struct ScissorRect {
pub left: i32,
pub top: i32,
pub right: i32,
pub bottom: i32,
}
#[derive(Copy, Clone, Serialize, Deserialize, Hash, PartialEq)]
pub enum Format {
Unknown,
R16n,
R16u,
R16i,
R16f,
R32u,
R32i,
R32f,
RG16f,
RG16u,
RG16i,
RG32u,
RG32i,
RG32f,
RGB32u,
RGB32i,
RGB32f,
RGBA8nSRGB,
RGBA8n,
RGBA8u,
RGBA8i,
BGRA8n,
BGRX8n,
BGRA8nSRGB,
BGRX8nSRGB,
RGBA16u,
RGBA16i,
RGBA16f,
RGBA32u,
RGBA32i,
RGBA32f,
D32fS8X24u,
D32f,
D24nS8u,
D16n,
BC1n,
BC1nSRGB,
BC2n,
BC2nSRGB,
BC3n,
BC3nSRGB,
BC4n,
BC5n,
}
#[derive(Default)]
pub struct DeviceInfo {
pub adapter_name: Option<String>,
pub shader_heap_size: usize,
pub render_target_heap_size: usize,
pub depth_stencil_heap_size: usize,
}
#[derive(Clone)]
pub struct AdapterInfo {
pub name: String,
pub description: String,
pub dedicated_video_memory: usize,
pub dedicated_system_memory: usize,
pub shared_system_memory: usize,
pub available: Vec<String>,
}
pub struct HeapInfo {
pub heap_type: HeapType,
pub num_descriptors: usize,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum HeapType {
Shader,
RenderTarget,
DepthStencil,
Sampler,
}
pub struct TextureHeapInfo<'stack, D: Device> {
pub shader: Option<&'stack mut D::Heap>,
pub render_target: Option<&'stack mut D::Heap>,
pub depth_stencil: Option<&'stack mut D::Heap>,
}
pub struct QueryHeapInfo {
pub heap_type: QueryType,
pub num_queries: usize,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum QueryType {
Occlusion,
BinaryOcclusion,
Timestamp,
PipelineStatistics,
VideoDecodeStatistics,
}
pub struct PipelineStatistics {
pub input_assembler_vertices: u64,
pub input_assembler_primitives: u64,
pub vertex_shader_invocations: u64,
pub pixel_shader_primitives: u64,
pub compute_shader_invocations: u64
}
pub struct SwapChainInfo {
pub num_buffers: u32,
pub format: Format,
pub clear_colour: Option<ClearColour>,
}
#[derive(Copy, Clone)]
pub struct BufferInfo {
pub usage: BufferUsage,
pub cpu_access: CpuAccessFlags,
pub format: Format,
pub stride: usize,
pub num_elements: usize,
pub initial_state: ResourceState,
}
pub struct ShaderInfo {
pub shader_type: ShaderType,
pub compile_info: Option<ShaderCompileInfo>,
}
pub struct ShaderCompileInfo {
pub entry_point: String,
pub target: String,
pub flags: ShaderCompileFlags,
}
#[derive(Copy, Clone)]
pub enum ShaderType {
Vertex,
Fragment,
Compute,
}
bitflags! {
pub struct DeviceFeatureFlags: u32 {
const NONE = 0;
const RAYTRACING = 1<<0;
const MESH_SAHDER = 1<<1;
}
pub struct ShaderCompileFlags: u32 {
const NONE = 0b00000000;
const DEBUG = 0b00000001;
const SKIP_OPTIMIZATION = 0b00000010;
}
#[derive(Serialize, Deserialize)]
pub struct WriteMask : u8 {
const NONE = 0;
const RED = 1<<0;
const GREEN = 1<<1;
const BLUE = 1<<2;
const ALPHA = 1<<3;
const ALL = (1<<4)-1;
}
pub struct CpuAccessFlags: u8 {
const NONE = 1<<0;
const READ = 1<<1;
const WRITE = 1<<2;
const PERSISTENTLY_MAPPED = 1<<3;
}
#[derive(Serialize, Deserialize)]
pub struct TextureUsage: u32 {
const NONE = 0;
const SHADER_RESOURCE = (1 << 0);
const UNORDERED_ACCESS = (1 << 1);
const RENDER_TARGET = (1 << 2);
const DEPTH_STENCIL = (1 << 3);
const VIDEO_DECODE_TARGET = (1 << 4);
const GENERATE_MIP_MAPS = (1 << 5);
}
pub struct BufferUsage : u32 {
const NONE = 0;
const VERTEX = (1 << 0);
const INDEX = (1 << 1);
const CONSTANT_BUFFER = (1 << 2);
const SHADER_RESOURCE = (1 << 3);
const UNORDERED_ACCESS = (1 << 4);
const INDIRECT_ARGUMENT_BUFFER = (1 << 5);
const APPEND_COUNTER = (1 << 6);
}
}
#[derive(Default, Clone, Serialize, Deserialize)]
pub struct PipelineLayout {
pub bindings: Option<Vec<DescriptorBinding>>,
pub push_constants: Option<Vec<PushConstantInfo>>,
pub static_samplers: Option<Vec<SamplerBinding>>,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct DescriptorBinding {
pub visibility: ShaderVisibility,
pub shader_register: u32,
pub register_space: u32,
pub binding_type: DescriptorType,
pub num_descriptors: Option<u32>,
}
#[derive(Clone, Copy, Serialize, Deserialize, Hash)]
pub enum DescriptorType {
ShaderResource,
ConstantBuffer,
UnorderedAccess,
Sampler,
PushConstants
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum ShaderVisibility {
#[default]
All,
Vertex,
Fragment,
Compute,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct PushConstantInfo {
pub visibility: ShaderVisibility,
pub shader_register: u32,
pub register_space: u32,
pub num_values: u32,
}
#[derive(Clone)]
pub struct PipelineSlotInfo {
pub index: u32,
pub count: Option<u32>
}
pub type InputLayout = Vec<InputElementInfo>;
#[derive(Clone, Serialize, Deserialize)]
pub struct InputElementInfo {
pub semantic: String,
pub index: u32,
pub format: Format,
pub input_slot: u32,
pub aligned_byte_offset: u32,
pub input_slot_class: InputSlotClass,
pub step_rate: u32,
}
#[derive(Clone, Serialize, Deserialize)]
pub enum InputSlotClass {
PerVertex,
PerInstance,
}
#[derive(Copy, Clone, Serialize, Deserialize)]
pub struct SamplerBinding {
pub visibility: ShaderVisibility,
pub shader_register: u32,
pub register_space: u32,
pub sampler_info: SamplerInfo
}
#[derive(Copy, Clone, Serialize, Deserialize)]
pub struct SamplerInfo {
pub filter: SamplerFilter,
pub address_u: SamplerAddressMode,
pub address_v: SamplerAddressMode,
pub address_w: SamplerAddressMode,
pub comparison: Option<ComparisonFunc>,
pub border_colour: Option<u32>,
pub mip_lod_bias: f32,
pub max_aniso: u32,
pub min_lod: f32,
pub max_lod: f32,
}
#[derive(Copy, Clone, Serialize, Deserialize)]
pub enum SamplerFilter {
Point,
Linear,
Anisotropic,
}
#[derive(Copy, Clone, Serialize, Deserialize)]
pub enum SamplerAddressMode {
Wrap,
Mirror,
Clamp,
Border,
MirrorOnce,
}
#[derive(Copy, Clone, Serialize, Deserialize)]
pub enum ComparisonFunc {
Never,
Less,
Equal,
LessEqual,
Greater,
NotEqual,
GreaterEqual,
Always,
}
pub struct RenderPipelineInfo<'stack, D: Device> {
pub vs: Option<&'stack D::Shader>,
pub fs: Option<&'stack D::Shader>,
pub input_layout: InputLayout,
pub pipeline_layout: PipelineLayout,
pub raster_info: RasterInfo,
pub depth_stencil_info: DepthStencilInfo,
pub blend_info: BlendInfo,
pub topology: Topology,
pub patch_index: u32,
pub sample_mask: u32,
pub pass: Option<&'stack D::RenderPass>,
}
#[derive(Copy, Clone, Serialize, Deserialize)]
pub enum Topology {
Undefined,
PointList,
LineList,
LineStrip,
TriangleList,
TriangleStrip,
LineListAdj,
LineStripAdj,
TriangleListAdj,
TriangleStripAdj,
PatchList,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub struct RasterInfo {
pub fill_mode: FillMode,
pub cull_mode: CullMode,
pub front_ccw: bool,
pub depth_bias: i32,
pub depth_bias_clamp: f32,
pub slope_scaled_depth_bias: f32,
pub depth_clip_enable: bool,
pub multisample_enable: bool,
pub antialiased_line_enable: bool,
pub forced_sample_count: u32,
pub conservative_raster_mode: bool,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum FillMode {
Wireframe,
Solid,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum CullMode {
None,
Front,
Back,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub struct DepthStencilInfo {
pub depth_enabled: bool,
pub depth_write_mask: DepthWriteMask,
pub depth_func: ComparisonFunc,
pub stencil_enabled: bool,
pub stencil_read_mask: u8,
pub stencil_write_mask: u8,
pub front_face: StencilInfo,
pub back_face: StencilInfo,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum DepthWriteMask {
Zero,
All,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub struct StencilInfo {
pub fail: StencilOp,
pub depth_fail: StencilOp,
pub pass: StencilOp,
pub func: ComparisonFunc,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum StencilOp {
Keep,
Zero,
Replace,
IncrSat,
DecrSat,
Invert,
Incr,
Decr,
}
#[derive(Default)]
pub struct BlendInfo {
pub alpha_to_coverage_enabled: bool,
pub independent_blend_enabled: bool,
pub render_target: Vec<RenderTargetBlendInfo>,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct RenderTargetBlendInfo {
pub blend_enabled: bool,
pub logic_op_enabled: bool,
pub src_blend: BlendFactor,
pub dst_blend: BlendFactor,
pub blend_op: BlendOp,
pub src_blend_alpha: BlendFactor,
pub dst_blend_alpha: BlendFactor,
pub blend_op_alpha: BlendOp,
pub logic_op: LogicOp,
pub write_mask: WriteMask,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum BlendFactor {
Zero,
One,
SrcColour,
InvSrcColour,
SrcAlpha,
InvSrcAlpha,
DstAlpha,
InvDstAlpha,
DstColour,
InvDstColour,
SrcAlphaSat,
BlendFactor,
InvBlendFactor,
Src1Colour,
InvSrc1Colour,
Src1Alpha,
InvSrc1Alpha,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum BlendOp {
Add,
Subtract,
RevSubtract,
Min,
Max,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum LogicOp {
Clear,
Set,
Copy,
CopyInverted,
NoOp,
Invert,
And,
Nand,
Or,
Nor,
Xor,
Equiv,
AndReverse,
AndInverted,
OrReverse,
OrInverted,
}
pub struct ComputePipelineInfo<'stack, D: Device> {
pub cs: &'stack D::Shader,
pub pipeline_layout: PipelineLayout,
}
#[derive(Copy, Clone)]
pub struct TextureInfo {
pub tex_type: TextureType,
pub format: Format,
pub width: u64,
pub height: u64,
pub depth: u32,
pub array_layers: u32,
pub mip_levels: u32,
pub samples: u32,
pub usage: TextureUsage,
pub initial_state: ResourceState,
}
#[derive(Copy, Clone, Debug)]
pub enum TextureType {
Texture1D,
Texture1DArray,
Texture2D,
Texture2DArray,
Texture3D,
TextureCube,
TextureCubeArray
}
#[derive(Copy, Clone)]
pub struct ClearColour {
pub r: f32,
pub g: f32,
pub b: f32,
pub a: f32,
}
pub struct ClearDepthStencil {
pub depth: Option<f32>,
pub stencil: Option<u8>,
}
pub struct RenderPassInfo<'stack, D: Device> {
pub render_targets: Vec<&'stack D::Texture>,
pub rt_clear: Option<ClearColour>,
pub depth_stencil: Option<&'stack D::Texture>,
pub ds_clear: Option<ClearDepthStencil>,
pub resolve: bool,
pub discard: bool,
pub array_slice: usize
}
pub struct TransitionBarrier<'stack, D: Device> {
pub texture: Option<&'stack D::Texture>,
pub buffer: Option<&'stack D::Buffer>,
pub state_before: ResourceState,
pub state_after: ResourceState,
}
#[derive(Copy, Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum ResourceState {
RenderTarget,
DepthStencil,
DepthStencilReadOnly,
Present,
UnorderedAccess,
ShaderResource,
VertexConstantBuffer,
IndexBuffer,
ResolveSrc,
ResolveDst,
CopySrc,
CopyDst,
GenericRead,
IndirectArgument,
}
#[derive(Copy, Clone, Serialize, Deserialize, PartialEq)]
pub enum Subresource {
Resource,
ResolveResource
}
#[derive(Default)]
pub struct MapInfo {
pub subresource: u32,
pub read_start: usize,
pub read_end: usize,
}
pub struct UnmapInfo {
pub subresource: u32,
pub write_start: usize,
pub write_end: usize,
}
pub enum PipelineType {
Render,
Compute
}
pub trait Shader<D: Device>: Send + Sync {}
pub trait RenderPipeline<D: Device>: Send + Sync {}
pub trait RenderPass<D: Device>: Send + Sync {
fn get_format_hash(&self) -> u64;
}
pub trait ComputePipeline<D: Device>: Send + Sync {}
pub trait Pipeline {
fn get_pipeline_slot(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> Option<&PipelineSlotInfo>;
fn get_pipeline_slots(&self) -> &Vec<u32>;
fn get_pipeline_type() -> PipelineType;
}
pub trait CommandSignature<D: Device>: Send + Sync {}
#[derive(Clone, Copy)]
pub enum IndirectArgumentType {
Draw,
DrawIndexed,
Dispatch,
VertexBuffer,
IndexBuffer,
PushConstants,
ConstantBuffer,
ShaderResource,
UnorderedAccess
}
#[derive(Clone, Copy)]
pub struct IndirectPushConstantsArguments {
pub slot: u32,
pub offset: u32,
pub num_values: u32,
}
#[derive(Clone, Copy)]
pub struct IndirectBufferArguments {
pub slot: u32
}
#[derive(Clone, Copy)]
pub struct IndirectNoArguments;
pub union IndirectTypeArguments {
pub push_constants: IndirectPushConstantsArguments,
pub buffer: IndirectBufferArguments
}
pub struct IndirectArgument {
pub argument_type: IndirectArgumentType,
pub arguments: Option<IndirectTypeArguments>
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DrawArguments {
pub vertex_count_per_instance: u32,
pub instance_count: u32,
pub start_vertex_location: u32,
pub start_instance_location: u32
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DrawIndexedArguments {
pub index_count_per_instance: u32,
pub instance_count: u32,
pub start_index_location: u32,
pub base_vertex_location: i32,
pub start_instance_location: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DispatchArguments {
pub thread_group_count_x: u32,
pub thread_group_count_y: u32,
pub thread_group_count_z: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct VertexBufferView {
pub location: u64,
pub size_bytes: u32,
pub stride_bytes: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct IndexBufferView {
pub location: u64,
pub size_bytes: u32,
pub format: u32,
}
pub trait Device: 'static + Send + Sync + Sized + Any + Clone {
type SwapChain: SwapChain<Self>;
type CmdBuf: CmdBuf<Self>;
type Buffer: Buffer<Self>;
type Shader: Shader<Self>;
type RenderPipeline: RenderPipeline<Self>;
type Texture: Texture<Self>;
type ReadBackRequest: ReadBackRequest<Self>;
type RenderPass: RenderPass<Self>;
type Heap: Heap<Self>;
type QueryHeap: QueryHeap<Self>;
type ComputePipeline: ComputePipeline<Self>;
type CommandSignature: CommandSignature<Self>;
fn create(info: &DeviceInfo) -> Self;
fn create_heap(&mut self, info: &HeapInfo) -> Self::Heap;
fn create_query_heap(&self, info: &QueryHeapInfo) -> Self::QueryHeap;
fn create_swap_chain<A: os::App>(
&mut self,
info: &SwapChainInfo,
window: &A::Window,
) -> Result<Self::SwapChain, Error>;
fn create_cmd_buf(&self, num_buffers: u32) -> Self::CmdBuf;
fn create_shader<T: Sized>(&self, info: &ShaderInfo, src: &[T]) -> Result<Self::Shader, Error>;
fn create_buffer<T: Sized>(
&mut self,
info: &BufferInfo,
data: Option<&[T]>,
) -> Result<Self::Buffer, Error>;
fn create_buffer_with_heap<T: Sized>(
&mut self,
info: &BufferInfo,
data: Option<&[T]>,
heap: &mut Self::Heap
) -> Result<Self::Buffer, Error>;
fn create_read_back_buffer(
&mut self,
size: usize,
) -> Result<Self::Buffer, Error>;
fn create_texture<T: Sized>(
&mut self,
info: &TextureInfo,
data: Option<&[T]>,
) -> Result<Self::Texture, Error>;
fn create_texture_with_heaps<T: Sized>(
&mut self,
info: &TextureInfo,
heaps: TextureHeapInfo<Self>,
data: Option<&[T]>,
) -> Result<Self::Texture, Error>;
fn create_render_pipeline(
&self,
info: &RenderPipelineInfo<Self>,
) -> Result<Self::RenderPipeline, Error>;
fn create_render_pass(&self, info: &RenderPassInfo<Self>) -> Result<Self::RenderPass, Error>;
fn create_compute_pipeline(
&self,
info: &ComputePipelineInfo<Self>,
) -> Result<Self::ComputePipeline, Error>;
fn create_indirect_render_command<T: Sized>(
&mut self,
arguments: Vec<IndirectArgument>,
pipeline: Option<&Self::RenderPipeline>
) -> Result<Self::CommandSignature, super::Error>;
fn execute(&self, cmd: &Self::CmdBuf);
fn get_shader_heap(&self) -> &Self::Heap;
fn get_shader_heap_mut(&mut self) -> &mut Self::Heap;
fn cleanup_dropped_resources(&mut self, swap_chain: &Self::SwapChain);
fn get_adapter_info(&self) -> &AdapterInfo;
fn get_feature_flags(&self) -> &DeviceFeatureFlags;
fn read_buffer(&self, swap_chain: &Self::SwapChain, buffer: &Self::Buffer, size_bytes: usize, frame_written_fence: u64) -> Option<ReadBackData>;
fn read_timestamps(&self, swap_chain: &Self::SwapChain, buffer: &Self::Buffer, size_bytes: usize, frame_written_fence: u64) -> Vec<f64>;
fn read_pipeline_statistics(&self, swap_chain: &Self::SwapChain, buffer: &Self::Buffer, frame_written_fence: u64) -> Option<PipelineStatistics>;
fn report_live_objects(&self) -> Result<(), Error>;
fn get_info_queue_messages(&self) -> Result<Vec<String>, Error>;
fn get_timestamp_size_bytes() -> usize;
fn get_pipeline_statistics_size_bytes() -> usize;
fn get_indirect_command_size(argument_type: IndirectArgumentType) -> usize;
fn get_counter_alignment() -> usize;
}
pub trait SwapChain<D: Device>: 'static + Sized + Any + Send + Sync + Clone {
fn new_frame(&mut self);
fn update<A: os::App>(&mut self, device: &mut D, window: &A::Window, cmd: &mut D::CmdBuf);
fn wait_for_last_frame(&self);
fn get_frame_fence_value(&self) -> u64;
fn get_num_buffers(&self) -> u32;
fn get_backbuffer_index(&self) -> u32;
fn get_backbuffer_texture(&self) -> &D::Texture;
fn get_backbuffer_pass(&self) -> &D::RenderPass;
fn get_backbuffer_pass_mut(&mut self) -> &mut D::RenderPass;
fn get_backbuffer_pass_no_clear(&self) -> &D::RenderPass;
fn get_backbuffer_pass_no_clear_mut(&mut self) -> &mut D::RenderPass;
fn swap(&mut self, device: &D);
}
pub trait CmdBuf<D: Device>: Send + Sync + Clone {
fn reset(&mut self, swap_chain: &D::SwapChain);
fn close(&mut self) -> Result<(), Error>;
fn get_backbuffer_index(&self) -> u32;
fn begin_render_pass(&self, render_pass: &D::RenderPass);
fn end_render_pass(&self);
fn begin_event(&mut self, colour: u32, name: &str);
fn end_event(&mut self);
fn set_marker(&self, colour: u32, name: &str);
fn timestamp_query(&mut self, heap: &mut D::QueryHeap, resolve_buffer: &mut D::Buffer);
fn begin_query(&mut self, heap: &mut D::QueryHeap, query_type: QueryType) -> usize;
fn end_query(&mut self, heap: &mut D::QueryHeap, query_type: QueryType, index: usize, resolve_buffer: &mut D::Buffer);
fn transition_barrier(&mut self, barrier: &TransitionBarrier<D>);
fn transition_barrier_subresource(&mut self, barrier: &TransitionBarrier<D>, subresource: Subresource);
fn set_viewport(&self, viewport: &Viewport);
fn set_scissor_rect(&self, scissor_rect: &ScissorRect);
fn set_index_buffer(&self, buffer: &D::Buffer);
fn set_vertex_buffer(&self, buffer: &D::Buffer, slot: u32);
fn set_render_pipeline(&self, pipeline: &D::RenderPipeline);
fn set_compute_pipeline(&self, pipeline: &D::ComputePipeline);
fn set_heap<T: Pipeline>(&self, pipeline: &T, heap: &D::Heap);
fn set_binding<T: Pipeline>(&self, pipeline: &T, heap: &D::Heap, slot: u32, offset: usize);
fn push_render_constants<T: Sized>(&self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]);
fn push_compute_constants<T: Sized>(&self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]);
fn draw_instanced(
&self,
vertex_count: u32,
instance_count: u32,
start_vertex: u32,
start_instance: u32,
);
fn draw_indexed_instanced(
&self,
index_count: u32,
instance_count: u32,
start_index: u32,
base_vertex: i32,
start_instance: u32,
);
fn dispatch(&self, group_count: Size3, numthreads: Size3);
fn execute_indirect(
&self,
command: &D::CommandSignature,
max_command_count: u32,
argument_buffer: &D::Buffer,
argument_buffer_offset: usize,
counter_buffer: Option<&D::Buffer>,
counter_buffer_offset: usize
);
fn resolve_texture_subresource(&self, texture: &D::Texture, subresource: u32) -> Result<(), Error>;
fn generate_mip_maps(&mut self, texture: &D::Texture, device: &D, heap: &D::Heap) -> Result<(), Error>;
fn read_back_backbuffer(&mut self, swap_chain: &D::SwapChain) -> Result<D::ReadBackRequest, Error>;
fn copy_buffer_region(
&mut self,
dst_buffer: &D::Buffer,
dst_offset: usize,
src_buffer: &D::Buffer,
src_offset: usize,
num_bytes: usize
);
fn copy_texture_region(
&mut self,
dst_texture: &D::Texture,
subresource_index: u32,
dst_x: u32,
dst_y: u32,
dst_z: u32,
src_texture: &D::Texture,
src_region: Option<Region>
);
}
pub trait Buffer<D: Device>: Send + Sync {
fn update<T: Sized>(&mut self, offset: usize, data: &[T]) -> Result<(), Error>; fn write<T: Sized>(&mut self, offset: usize, data: &[T]) -> Result<(), Error>;
fn map(&mut self, info: &MapInfo) -> *mut u8;
fn unmap(&mut self, info: &UnmapInfo);
fn get_srv_index(&self) -> Option<usize>;
fn get_cbv_index(&self) -> Option<usize>;
fn get_uav_index(&self) -> Option<usize>;
fn get_vbv(&self) -> Option<VertexBufferView>;
fn get_ibv(&self) -> Option<IndexBufferView>;
fn get_counter_offset(&self) -> Option<usize>;
}
pub trait Texture<D: Device>: Send + Sync {
fn get_srv_index(&self) -> Option<usize>;
fn get_uav_index(&self) -> Option<usize>;
fn get_subresource_uav_index(&self, subresource: u32) -> Option<usize>;
fn get_msaa_srv_index(&self) -> Option<usize>;
fn clone_inner(&self) -> Self;
fn is_resolvable(&self) -> bool;
fn get_shader_heap_id(&self) -> Option<u16>;
}
pub trait Heap<D: Device>: Send + Sync {
fn deallocate(&mut self, index: usize);
fn cleanup_dropped_resources(&mut self, swap_chain: &D::SwapChain);
fn get_heap_id(&self) -> u16;
}
pub trait QueryHeap<D: Device>: Send + Sync {
fn reset(&mut self);
}
pub trait ReadBackRequest<D: Device> {
fn is_complete(&self, swap_chain: &D::SwapChain) -> bool;
fn map(&self, info: &MapInfo) -> Result<ReadBackData, Error>;
fn unmap(&self);
}
#[derive(Clone)]
pub struct ReadBackData {
pub data: &'static [u8],
pub format: Format,
pub size: usize,
pub row_pitch: usize,
pub slice_pitch: usize,
}
pub fn as_u8_slice<T: Sized>(p: &T) -> &[u8] {
unsafe {
::std::slice::from_raw_parts((p as *const T) as *const u8, ::std::mem::size_of::<T>())
}
}
pub fn slice_as_u8_slice<T: Sized>(p: &[T]) -> &[u8] {
unsafe {
::std::slice::from_raw_parts(
(p.as_ptr() as *const T) as *const u8,
::std::mem::size_of::<T>() * p.len(),
)
}
}
pub const fn block_size_for_format(format: Format) -> u32 {
match format {
Format::Unknown => 0,
Format::R16n => 2,
Format::R16u => 2,
Format::R16i => 2,
Format::R16f => 2,
Format::R32u => 4,
Format::R32i => 4,
Format::R32f => 4,
Format::RG16u => 4,
Format::RG16i => 4,
Format::RG16f => 4,
Format::RG32u => 8,
Format::RG32i => 8,
Format::RG32f => 8,
Format::RGBA8nSRGB => 4,
Format::RGBA8n => 4,
Format::RGBA8u => 4,
Format::RGBA8i => 4,
Format::BGRA8n => 4,
Format::BGRX8n => 4,
Format::BGRA8nSRGB => 4,
Format::BGRX8nSRGB => 4,
Format::RGB32u => 12,
Format::RGB32i => 12,
Format::RGB32f => 12,
Format::RGBA16u => 8,
Format::RGBA16i => 8,
Format::RGBA16f => 8,
Format::RGBA32u => 16,
Format::RGBA32i => 16,
Format::RGBA32f => 16,
Format::D32fS8X24u => 8,
Format::D32f => 16,
Format::D24nS8u => 32,
Format::D16n => 2,
Format::BC1n => 8,
Format::BC1nSRGB => 8,
Format::BC2n => 4,
Format::BC2nSRGB => 4,
Format::BC3n => 16,
Format::BC3nSRGB => 16,
Format::BC4n => 8,
Format::BC5n => 16,
}
}
pub const fn texels_per_block_for_format(format: Format) -> u64 {
match format {
Format::BC1n => 4,
Format::BC1nSRGB => 4,
Format::BC2n => 4,
Format::BC2nSRGB => 4,
Format::BC3n => 4,
Format::BC3nSRGB => 4,
Format::BC4n => 4,
Format::BC5n => 4,
_ => 1,
}
}
pub const fn components_for_format(format: Format) -> u32 {
match format {
Format::Unknown => 0,
Format::R16n => 1,
Format::R16u => 1,
Format::R16i => 1,
Format::R16f => 1,
Format::R32u => 1,
Format::R32i => 1,
Format::R32f => 1,
Format::RG16u => 2,
Format::RG16i => 2,
Format::RG16f => 2,
Format::RG32u => 2,
Format::RG32i => 2,
Format::RG32f => 2,
Format::RGBA8nSRGB => 4,
Format::RGBA8n => 4,
Format::RGBA8u => 4,
Format::RGBA8i => 4,
Format::BGRA8n => 4,
Format::BGRX8n => 4,
Format::BGRA8nSRGB => 4,
Format::BGRX8nSRGB => 4,
Format::RGB32u => 3,
Format::RGB32i => 3,
Format::RGB32f => 3,
Format::RGBA16u => 4,
Format::RGBA16i => 4,
Format::RGBA16f => 4,
Format::RGBA32u => 4,
Format::RGBA32i => 4,
Format::RGBA32f => 4,
Format::D32fS8X24u => 2,
Format::D32f => 1,
Format::D24nS8u => 2,
Format::D16n => 1,
Format::BC1n => 4,
Format::BC1nSRGB => 4,
Format::BC2n => 3,
Format::BC2nSRGB => 3,
Format::BC3n => 4,
Format::BC3nSRGB => 4,
Format::BC4n => 1,
Format::BC5n => 2,
}
}
pub fn row_pitch_for_format(format: Format, width: u64) -> u64 {
let tpb = texels_per_block_for_format(format);
block_size_for_format(format) as u64 * (width / tpb).max(1)
}
pub fn slice_pitch_for_format(format: Format, width: u64, height: u64) -> u64 {
let tpb = texels_per_block_for_format(format);
block_size_for_format(format) as u64 * (width / tpb).max(1) * (height / tpb).max(1)
}
pub fn size_for_format(format: Format, width: u64, height: u64, depth: u32) -> u64 {
let tpb = texels_per_block_for_format(format);
block_size_for_format(format) as u64 * (width / tpb).max(1) * (height / tpb).max(1) * depth as u64
}
pub fn size_for_format_mipped(format: Format, width: u64, height: u64, depth: u32, array_layers: u32, mips: u32) -> u64 {
let mut total = 0;
let mut mip_width = width;
let mut mip_height = height;
let mut mip_depth = depth;
for _ in 0..mips {
total += size_for_format(format, mip_width, mip_height, mip_depth) * array_layers as u64;
mip_width = max(mip_width / 2, 1);
mip_height = max(mip_height / 2, 1);
mip_depth = max(mip_depth / 2, 1);
}
total
}
pub fn mip_levels_for_dimension(width: u64, height: u64) -> u32 {
f32::log2(width.max(height) as f32) as u32 + 1
}
pub fn align_pow2(value: u64, align: u64) -> u64 {
(value + (align - 1)) & !(align - 1)
}
pub fn align(value: u64, align: u64) -> u64 {
let div = value / align;
let rem = value % align;
if rem != 0 {
return (div + 1) * align;
}
value
}
pub const fn num_32bit_constants<T: Sized>(_: &T) -> u32 {
(std::mem::size_of::<T>() / 4) as u32
}
trait NumConstants {
fn num_constants() -> u32;
}
impl<T> NumConstants for T where T: Sized {
fn num_constants() -> u32 {
(std::mem::size_of::<T>() / 4) as u32
}
}
impl From<os::Rect<i32>> for Viewport {
fn from(rect: os::Rect<i32>) -> Viewport {
Viewport {
x: rect.x as f32,
y: rect.y as f32,
width: rect.width as f32,
height: rect.height as f32,
min_depth: 0.0,
max_depth: 1.0,
}
}
}
impl From<os::Rect<i32>> for ScissorRect {
fn from(rect: os::Rect<i32>) -> ScissorRect {
ScissorRect {
left: rect.x,
top: rect.y,
right: rect.width,
bottom: rect.height,
}
}
}
impl From<WriteMask> for u8 {
fn from(mask: WriteMask) -> u8 {
mask.bits
}
}
impl std::fmt::Display for AdapterInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut available = String::from("");
for adapter in &self.available {
available += " ";
available += adapter;
available += "\n";
}
write!(
f,
"{}:
{}
Video Memory: {}(mb)
System Memory: {}(mb)
Shared System Memory: {}(mb)
Available Adapters:
{}",
self.name,
self.description,
self.dedicated_video_memory / 1024 / 1024,
self.dedicated_system_memory / 1024 / 1024,
self.shared_system_memory / 1024 / 1024,
available
)
}
}
impl Default for TextureInfo {
fn default() -> Self {
TextureInfo {
tex_type: TextureType::Texture2D,
format: Format::RGBA8n,
width: 1,
height: 1,
depth: 1,
array_layers: 1,
mip_levels: 1,
samples: 1,
usage: TextureUsage::SHADER_RESOURCE,
initial_state: ResourceState::ShaderResource
}
}
}
impl Default for RasterInfo {
fn default() -> Self {
RasterInfo {
fill_mode: FillMode::Solid,
cull_mode: CullMode::None,
front_ccw: false,
depth_bias: 0,
depth_bias_clamp: 0.0,
slope_scaled_depth_bias: 0.0,
depth_clip_enable: false,
multisample_enable: false,
antialiased_line_enable: false,
forced_sample_count: 0,
conservative_raster_mode: false,
}
}
}
impl Default for SamplerInfo {
fn default() -> Self {
SamplerInfo {
filter: SamplerFilter::Linear,
address_u: SamplerAddressMode::Wrap,
address_v: SamplerAddressMode::Wrap,
address_w: SamplerAddressMode::Wrap,
comparison: None,
border_colour: None,
mip_lod_bias: 0.0,
max_aniso: 0,
min_lod: -1.0,
max_lod: -1.0,
}
}
}
impl Default for DepthStencilInfo {
fn default() -> Self {
DepthStencilInfo {
depth_enabled: false,
depth_write_mask: DepthWriteMask::Zero,
depth_func: ComparisonFunc::Always,
stencil_enabled: false,
stencil_read_mask: 0,
stencil_write_mask: 0,
front_face: StencilInfo {
fail: StencilOp::Keep,
depth_fail: StencilOp::Keep,
pass: StencilOp::Keep,
func: ComparisonFunc::Always,
},
back_face: StencilInfo {
fail: StencilOp::Keep,
depth_fail: StencilOp::Keep,
pass: StencilOp::Keep,
func: ComparisonFunc::Always,
},
}
}
}
impl Default for RenderTargetBlendInfo {
fn default() -> Self {
RenderTargetBlendInfo {
blend_enabled: false,
logic_op_enabled: false,
src_blend: BlendFactor::Zero,
dst_blend: BlendFactor::Zero,
blend_op: BlendOp::Add,
src_blend_alpha: BlendFactor::Zero,
dst_blend_alpha: BlendFactor::Zero,
blend_op_alpha: BlendOp::Add,
logic_op: LogicOp::Clear,
write_mask: WriteMask::ALL,
}
}
}
impl<'stack, D> Default for RenderPipelineInfo<'stack, D> where D: Device {
fn default() -> Self {
Self {
vs: None,
fs: None,
input_layout: Vec::new(),
pipeline_layout: PipelineLayout::default(),
raster_info: RasterInfo::default(),
depth_stencil_info: DepthStencilInfo::default(),
blend_info: BlendInfo::default(),
topology: Topology::TriangleList,
patch_index: 0,
sample_mask: u32::max_value(),
pass: None
}
}
}
impl Default for PipelineStatistics {
fn default() -> Self {
PipelineStatistics {
input_assembler_vertices: 0,
input_assembler_primitives: 0,
vertex_shader_invocations: 0,
pixel_shader_primitives: 0,
compute_shader_invocations: 0
}
}
}
impl<'stack, D> Default for TextureHeapInfo<'stack, D> where D: Device {
fn default() -> Self {
Self {
shader: None,
render_target: None,
depth_stencil: None
}
}
}
impl std::ops::Add for PipelineStatistics {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
input_assembler_vertices: self.input_assembler_vertices + other.input_assembler_vertices,
input_assembler_primitives: self.input_assembler_primitives + other.input_assembler_primitives,
vertex_shader_invocations: self.vertex_shader_invocations + other.vertex_shader_invocations,
pixel_shader_primitives: self.pixel_shader_primitives + other.pixel_shader_primitives,
compute_shader_invocations: self.compute_shader_invocations + other.compute_shader_invocations,
}
}
}
impl std::ops::AddAssign for PipelineStatistics {
fn add_assign(&mut self, other: Self) {
self.input_assembler_vertices += other.input_assembler_vertices;
self.input_assembler_primitives += other.input_assembler_primitives;
self.vertex_shader_invocations += other.vertex_shader_invocations;
self.pixel_shader_primitives += other.pixel_shader_primitives;
self.compute_shader_invocations += other.compute_shader_invocations;
}
}
impl std::fmt::Display for ResourceState {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}