mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
Setup crate structure and wrap first interface
This commit is contained in:
parent
a0c95c9462
commit
4da4b1e908
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "d3d12-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["msiglreith <m.siglreith@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bitflags = "1"
|
||||||
|
winapi = { version = "0.3", features = ["d3d12","d3dcommon","d3dcompiler","dxgiformat","winerror"] }
|
98
src/com.rs
Normal file
98
src/com.rs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
use std::fmt;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::ptr;
|
||||||
|
use winapi::ctypes::c_void;
|
||||||
|
use winapi::um::unknwnbase::IUnknown;
|
||||||
|
use winapi::Interface;
|
||||||
|
use D3DResult;
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct WeakPtr<T>(*mut T);
|
||||||
|
|
||||||
|
impl<T> WeakPtr<T> {
|
||||||
|
pub fn null() -> Self {
|
||||||
|
WeakPtr(ptr::null_mut())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_null(&self) -> bool {
|
||||||
|
self.0.is_null()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_ptr(&self) -> *const T {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_mut_ptr(&self) -> *mut T {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn mut_void(&mut self) -> *mut *mut c_void {
|
||||||
|
&mut self.0 as *mut *mut _ as *mut *mut _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Interface> WeakPtr<T> {
|
||||||
|
pub unsafe fn as_unknown(&self) -> &IUnknown {
|
||||||
|
debug_assert!(!self.is_null());
|
||||||
|
&*(self.0 as *mut IUnknown)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cast creates a new WeakPtr requiring explicit destroy call.
|
||||||
|
pub unsafe fn cast<U>(&self) -> D3DResult<WeakPtr<U>>
|
||||||
|
where
|
||||||
|
U: Interface,
|
||||||
|
{
|
||||||
|
let mut obj = WeakPtr::<U>::null();
|
||||||
|
let hr = self
|
||||||
|
.as_unknown()
|
||||||
|
.QueryInterface(&U::uuidof(), obj.mut_void());
|
||||||
|
(obj, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroying one instance of the WeakPtr will invalidate all
|
||||||
|
// copies and clones.
|
||||||
|
pub unsafe fn destroy(&self) {
|
||||||
|
self.as_unknown().Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Clone for WeakPtr<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
WeakPtr(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Copy for WeakPtr<T> {}
|
||||||
|
|
||||||
|
impl<T> Deref for WeakPtr<T> {
|
||||||
|
type Target = T;
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
debug_assert!(!self.is_null());
|
||||||
|
unsafe { &*self.0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> fmt::Debug for WeakPtr<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "WeakPtr( ptr: {:?} )", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> PartialEq<*mut T> for WeakPtr<T> {
|
||||||
|
fn eq(&self, other: &*mut T) -> bool {
|
||||||
|
self.0 == *other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> PartialEq for WeakPtr<T> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.0 == other.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Hash for WeakPtr<T> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.0.hash(state);
|
||||||
|
}
|
||||||
|
}
|
14
src/command_allocator.rs
Normal file
14
src/command_allocator.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//! Command Allocator
|
||||||
|
|
||||||
|
use com::WeakPtr;
|
||||||
|
use winapi::um::d3d12;
|
||||||
|
|
||||||
|
pub type CommandAllocator = WeakPtr<d3d12::ID3D12CommandAllocator>;
|
||||||
|
|
||||||
|
impl CommandAllocator {
|
||||||
|
pub fn reset(&self) {
|
||||||
|
unsafe {
|
||||||
|
self.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
218
src/command_list.rs
Normal file
218
src/command_list.rs
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
//! Graphics command list
|
||||||
|
|
||||||
|
use com::WeakPtr;
|
||||||
|
use resource::DiscardRegion;
|
||||||
|
use std::mem;
|
||||||
|
use winapi::um::d3d12;
|
||||||
|
use {
|
||||||
|
CommandAllocator, CpuDescriptor, DescriptorHeap, Format, GpuAddress, GpuDescriptor, IndexCount,
|
||||||
|
InstanceCount, PipelineState, Rect, Resource, RootSignature, VertexCount, VertexOffset,
|
||||||
|
WorkGroupCount, HRESULT,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum CmdListType {
|
||||||
|
Direct = d3d12::D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||||
|
Bundle = d3d12::D3D12_COMMAND_LIST_TYPE_BUNDLE,
|
||||||
|
Compute = d3d12::D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
||||||
|
Copy = d3d12::D3D12_COMMAND_LIST_TYPE_COPY,
|
||||||
|
// VideoDecode = d3d12::D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
|
||||||
|
// VideoProcess = d3d12::D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct ClearFlags: u32 {
|
||||||
|
const DEPTH = d3d12::D3D12_CLEAR_FLAG_DEPTH;
|
||||||
|
const STENCIL = d3d12::D3D12_CLEAR_FLAG_STENCIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC);
|
||||||
|
|
||||||
|
impl IndirectArgument {
|
||||||
|
pub fn draw() -> Self {
|
||||||
|
IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC {
|
||||||
|
Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW,
|
||||||
|
..unsafe { mem::zeroed() }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_indexed() -> Self {
|
||||||
|
IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC {
|
||||||
|
Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED,
|
||||||
|
..unsafe { mem::zeroed() }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch() -> Self {
|
||||||
|
IndirectArgument(d3d12::D3D12_INDIRECT_ARGUMENT_DESC {
|
||||||
|
Type: d3d12::D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH,
|
||||||
|
..unsafe { mem::zeroed() }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: missing variants
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type CommandSignature = WeakPtr<d3d12::ID3D12CommandSignature>;
|
||||||
|
pub type GraphicsCommandList = WeakPtr<d3d12::ID3D12GraphicsCommandList>;
|
||||||
|
|
||||||
|
impl GraphicsCommandList {
|
||||||
|
pub fn close(&self) -> HRESULT {
|
||||||
|
unsafe { self.Close() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&self, allocator: CommandAllocator, initial_pso: PipelineState) -> HRESULT {
|
||||||
|
unsafe { self.Reset(allocator.as_mut_ptr(), initial_pso.as_mut_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn discard_resource(&self, resource: Resource, region: DiscardRegion) {
|
||||||
|
debug_assert!(region.subregions.start < region.subregions.end);
|
||||||
|
unsafe {
|
||||||
|
self.DiscardResource(
|
||||||
|
resource.as_mut_ptr(),
|
||||||
|
&d3d12::D3D12_DISCARD_REGION {
|
||||||
|
NumRects: region.rects.len() as _,
|
||||||
|
pRects: region.rects.as_ptr(),
|
||||||
|
FirstSubresource: region.subregions.start,
|
||||||
|
NumSubresources: region.subregions.end - region.subregions.start - 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_depth_stencil_view(
|
||||||
|
&self,
|
||||||
|
dsv: CpuDescriptor,
|
||||||
|
flags: ClearFlags,
|
||||||
|
depth: f32,
|
||||||
|
stencil: u8,
|
||||||
|
rects: &[Rect],
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
self.ClearDepthStencilView(
|
||||||
|
dsv,
|
||||||
|
flags.bits(),
|
||||||
|
depth,
|
||||||
|
stencil,
|
||||||
|
rects.len() as _,
|
||||||
|
rects.as_ptr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch(&self, count: WorkGroupCount) {
|
||||||
|
unsafe {
|
||||||
|
self.Dispatch(count[0], count[1], count[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(
|
||||||
|
&self,
|
||||||
|
num_vertices: VertexCount,
|
||||||
|
num_instances: InstanceCount,
|
||||||
|
start_vertex: VertexCount,
|
||||||
|
start_instance: InstanceCount,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
self.DrawInstanced(num_vertices, num_instances, start_vertex, start_instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_indexed(
|
||||||
|
&self,
|
||||||
|
num_indices: IndexCount,
|
||||||
|
num_instances: InstanceCount,
|
||||||
|
start_index: IndexCount,
|
||||||
|
base_vertex: VertexOffset,
|
||||||
|
start_instance: InstanceCount,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
self.DrawIndexedInstanced(
|
||||||
|
num_indices,
|
||||||
|
num_instances,
|
||||||
|
start_index,
|
||||||
|
base_vertex,
|
||||||
|
start_instance,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_index_buffer(&self, gpu_address: GpuAddress, size: u32, format: Format) {
|
||||||
|
let mut ibv = d3d12::D3D12_INDEX_BUFFER_VIEW {
|
||||||
|
BufferLocation: gpu_address,
|
||||||
|
SizeInBytes: size,
|
||||||
|
Format: format,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
self.IASetIndexBuffer(&mut ibv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_blend_factor(&self, factor: [f32; 4]) {
|
||||||
|
unsafe {
|
||||||
|
self.OMSetBlendFactor(&factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_stencil_reference(&self, reference: u32) {
|
||||||
|
unsafe {
|
||||||
|
self.OMSetStencilRef(reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_pipeline_state(&self, pso: PipelineState) {
|
||||||
|
unsafe {
|
||||||
|
self.SetPipelineState(pso.as_mut_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute_bundle(&self, bundle: GraphicsCommandList) {
|
||||||
|
unsafe {
|
||||||
|
self.ExecuteBundle(bundle.as_mut_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_descriptor_heaps(&self, heaps: &[DescriptorHeap]) {
|
||||||
|
unsafe {
|
||||||
|
self.SetDescriptorHeaps(
|
||||||
|
heaps.len() as _,
|
||||||
|
heaps.as_ptr() as *mut &DescriptorHeap as *mut _,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_compute_root_signature(&self, signature: RootSignature) {
|
||||||
|
unsafe {
|
||||||
|
self.SetComputeRootSignature(signature.as_mut_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_graphics_root_signature(&self, signature: RootSignature) {
|
||||||
|
unsafe {
|
||||||
|
self.SetGraphicsRootSignature(signature.as_mut_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_compute_root_descriptor_table(
|
||||||
|
&self,
|
||||||
|
root_index: u32,
|
||||||
|
base_descriptor: GpuDescriptor,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
self.SetComputeRootDescriptorTable(root_index, base_descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_graphics_root_descriptor_table(
|
||||||
|
&self,
|
||||||
|
root_index: u32,
|
||||||
|
base_descriptor: GpuDescriptor,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
self.SetGraphicsRootDescriptorTable(root_index, base_descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
207
src/descriptor.rs
Normal file
207
src/descriptor.rs
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
use com::WeakPtr;
|
||||||
|
use std::mem;
|
||||||
|
use std::ops::Range;
|
||||||
|
use winapi::um::d3d12;
|
||||||
|
use {Blob, D3DResult, Error, TextureAddressMode};
|
||||||
|
|
||||||
|
pub type CpuDescriptor = d3d12::D3D12_CPU_DESCRIPTOR_HANDLE;
|
||||||
|
pub type GpuDescriptor = d3d12::D3D12_GPU_DESCRIPTOR_HANDLE;
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum HeapType {
|
||||||
|
CbvSrvUav = d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||||
|
Sampler = d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||||
|
Rtv = d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
|
||||||
|
Dsv = d3d12::D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct HeapFlags: u32 {
|
||||||
|
const SHADER_VISIBLE = d3d12::D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DescriptorHeap = WeakPtr<d3d12::ID3D12DescriptorHeap>;
|
||||||
|
|
||||||
|
impl DescriptorHeap {
|
||||||
|
pub fn start_cpu_descriptor(&self) -> CpuDescriptor {
|
||||||
|
unsafe { self.GetCPUDescriptorHandleForHeapStart() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_gpu_descriptor(&self) -> GpuDescriptor {
|
||||||
|
unsafe { self.GetGPUDescriptorHandleForHeapStart() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum ShaderVisibility {
|
||||||
|
All = d3d12::D3D12_SHADER_VISIBILITY_ALL,
|
||||||
|
VS = d3d12::D3D12_SHADER_VISIBILITY_VERTEX,
|
||||||
|
HS = d3d12::D3D12_SHADER_VISIBILITY_HULL,
|
||||||
|
DS = d3d12::D3D12_SHADER_VISIBILITY_DOMAIN,
|
||||||
|
GS = d3d12::D3D12_SHADER_VISIBILITY_GEOMETRY,
|
||||||
|
PS = d3d12::D3D12_SHADER_VISIBILITY_PIXEL,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum DescriptorRangeType {
|
||||||
|
SRV = d3d12::D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
|
||||||
|
UAV = d3d12::D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
|
||||||
|
CBV = d3d12::D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
|
||||||
|
Sampler = d3d12::D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct DescriptorRange(d3d12::D3D12_DESCRIPTOR_RANGE);
|
||||||
|
impl DescriptorRange {
|
||||||
|
pub fn new(
|
||||||
|
ty: DescriptorRangeType,
|
||||||
|
count: u32,
|
||||||
|
base_register: u32,
|
||||||
|
register_space: u32,
|
||||||
|
offset: u32,
|
||||||
|
) -> Self {
|
||||||
|
DescriptorRange(d3d12::D3D12_DESCRIPTOR_RANGE {
|
||||||
|
RangeType: ty as _,
|
||||||
|
NumDescriptors: count,
|
||||||
|
BaseShaderRegister: base_register,
|
||||||
|
RegisterSpace: register_space,
|
||||||
|
OffsetInDescriptorsFromTableStart: offset,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct RootParameter(d3d12::D3D12_ROOT_PARAMETER);
|
||||||
|
impl RootParameter {
|
||||||
|
// TODO: DescriptorRange must outlive Self
|
||||||
|
pub fn descriptor_table(visibility: ShaderVisibility, ranges: &[DescriptorRange]) -> Self {
|
||||||
|
let mut param = d3d12::D3D12_ROOT_PARAMETER {
|
||||||
|
ParameterType: d3d12::D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||||
|
ShaderVisibility: visibility as _,
|
||||||
|
..unsafe { mem::zeroed() }
|
||||||
|
};
|
||||||
|
|
||||||
|
*unsafe { param.u.DescriptorTable_mut() } = d3d12::D3D12_ROOT_DESCRIPTOR_TABLE {
|
||||||
|
NumDescriptorRanges: ranges.len() as _,
|
||||||
|
pDescriptorRanges: ranges.as_ptr() as *const _,
|
||||||
|
};
|
||||||
|
|
||||||
|
RootParameter(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn constants(
|
||||||
|
visibility: ShaderVisibility,
|
||||||
|
register: u32,
|
||||||
|
register_space: u32,
|
||||||
|
num: u32,
|
||||||
|
) -> Self {
|
||||||
|
let mut param = d3d12::D3D12_ROOT_PARAMETER {
|
||||||
|
ParameterType: d3d12::D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
|
||||||
|
ShaderVisibility: visibility as _,
|
||||||
|
..unsafe { mem::zeroed() }
|
||||||
|
};
|
||||||
|
|
||||||
|
*unsafe { param.u.Constants_mut() } = d3d12::D3D12_ROOT_CONSTANTS {
|
||||||
|
ShaderRegister: register,
|
||||||
|
RegisterSpace: register_space,
|
||||||
|
Num32BitValues: num,
|
||||||
|
};
|
||||||
|
|
||||||
|
RootParameter(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum StaticBorderColor {
|
||||||
|
TransparentBlack = d3d12::D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK,
|
||||||
|
OpaqueBlack = d3d12::D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK,
|
||||||
|
OpaqueWhite = d3d12::D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct StaticSampler(d3d12::D3D12_STATIC_SAMPLER_DESC);
|
||||||
|
impl StaticSampler {
|
||||||
|
pub fn new(
|
||||||
|
visibility: ShaderVisibility,
|
||||||
|
register: u32,
|
||||||
|
register_space: u32,
|
||||||
|
|
||||||
|
filter: d3d12::D3D12_FILTER,
|
||||||
|
address_mode: TextureAddressMode,
|
||||||
|
mip_lod_bias: f32,
|
||||||
|
max_anisotropy: u32,
|
||||||
|
comparison_op: d3d12::D3D12_COMPARISON_FUNC,
|
||||||
|
border_color: StaticBorderColor,
|
||||||
|
lod: Range<f32>,
|
||||||
|
) -> Self {
|
||||||
|
StaticSampler(d3d12::D3D12_STATIC_SAMPLER_DESC {
|
||||||
|
Filter: filter,
|
||||||
|
AddressU: address_mode[0],
|
||||||
|
AddressV: address_mode[1],
|
||||||
|
AddressW: address_mode[2],
|
||||||
|
MipLODBias: mip_lod_bias,
|
||||||
|
MaxAnisotropy: max_anisotropy,
|
||||||
|
ComparisonFunc: comparison_op,
|
||||||
|
BorderColor: border_color as _,
|
||||||
|
MinLOD: lod.start,
|
||||||
|
MaxLOD: lod.end,
|
||||||
|
ShaderRegister: register,
|
||||||
|
RegisterSpace: register_space,
|
||||||
|
ShaderVisibility: visibility as _,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum RootSignatureVersion {
|
||||||
|
V1_0 = d3d12::D3D_ROOT_SIGNATURE_VERSION_1_0,
|
||||||
|
V1_1 = d3d12::D3D_ROOT_SIGNATURE_VERSION_1_1,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct RootSignatureFlags: u32 {
|
||||||
|
const ALLOW_IA_INPUT_LAYOUT = d3d12::D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||||
|
const DENY_VS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS;
|
||||||
|
const DENY_HS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS;
|
||||||
|
const DENY_DS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS;
|
||||||
|
const DENY_GS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
|
||||||
|
const DENY_PS_ROOT_ACCESS = d3d12::D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type RootSignature = WeakPtr<d3d12::ID3D12RootSignature>;
|
||||||
|
|
||||||
|
impl RootSignature {
|
||||||
|
pub fn serialize(
|
||||||
|
version: RootSignatureVersion,
|
||||||
|
parameters: &[RootParameter],
|
||||||
|
static_samplers: &[StaticSampler],
|
||||||
|
flags: RootSignatureFlags,
|
||||||
|
) -> D3DResult<(Blob, Error)> {
|
||||||
|
let mut blob = Blob::null();
|
||||||
|
let mut error = Error::null();
|
||||||
|
|
||||||
|
let desc = d3d12::D3D12_ROOT_SIGNATURE_DESC {
|
||||||
|
NumParameters: parameters.len() as _,
|
||||||
|
pParameters: parameters.as_ptr() as *const _,
|
||||||
|
NumStaticSamplers: static_samplers.len() as _,
|
||||||
|
pStaticSamplers: static_samplers.as_ptr() as _,
|
||||||
|
Flags: flags.bits(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let hr = unsafe {
|
||||||
|
d3d12::D3D12SerializeRootSignature(
|
||||||
|
&desc,
|
||||||
|
version as _,
|
||||||
|
blob.mut_void() as *mut *mut _,
|
||||||
|
error.mut_void() as *mut *mut _,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
((blob, error), hr)
|
||||||
|
}
|
||||||
|
}
|
268
src/device.rs
Normal file
268
src/device.rs
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
//! Device
|
||||||
|
|
||||||
|
use com::WeakPtr;
|
||||||
|
use command_list::{CmdListType, CommandSignature, IndirectArgument};
|
||||||
|
use descriptor::{CpuDescriptor, HeapFlags, HeapType};
|
||||||
|
use std::ops::Range;
|
||||||
|
use winapi::um::d3d12;
|
||||||
|
use winapi::Interface;
|
||||||
|
use {pso, query, queue};
|
||||||
|
use {
|
||||||
|
Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap, FeatureLevel,
|
||||||
|
GraphicsCommandList, NodeMask, PipelineState, QueryHeap, RootSignature, Shader,
|
||||||
|
TextureAddressMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub type Device = WeakPtr<d3d12::ID3D12Device>;
|
||||||
|
|
||||||
|
impl Device {
|
||||||
|
pub fn create<I: Interface>(
|
||||||
|
adapter: WeakPtr<I>,
|
||||||
|
feature_level: FeatureLevel,
|
||||||
|
) -> D3DResult<Self> {
|
||||||
|
let mut device = Device::null();
|
||||||
|
let hr = unsafe {
|
||||||
|
d3d12::D3D12CreateDevice(
|
||||||
|
adapter.as_unknown() as *const _ as *mut _,
|
||||||
|
feature_level as _,
|
||||||
|
&d3d12::ID3D12Device::uuidof(),
|
||||||
|
device.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(device, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_command_allocator(&self, list_type: CmdListType) -> D3DResult<CommandAllocator> {
|
||||||
|
let mut allocator = CommandAllocator::null();
|
||||||
|
let hr = unsafe {
|
||||||
|
self.CreateCommandAllocator(
|
||||||
|
list_type as _,
|
||||||
|
&d3d12::ID3D12CommandAllocator::uuidof(),
|
||||||
|
allocator.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(allocator, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_command_queue(
|
||||||
|
&self,
|
||||||
|
list_type: CmdListType,
|
||||||
|
priority: queue::Priority,
|
||||||
|
flags: queue::CommandQueueFlags,
|
||||||
|
node_mask: NodeMask,
|
||||||
|
) -> D3DResult<CommandQueue> {
|
||||||
|
let desc = d3d12::D3D12_COMMAND_QUEUE_DESC {
|
||||||
|
Type: list_type as _,
|
||||||
|
Priority: priority as _,
|
||||||
|
Flags: flags.bits(),
|
||||||
|
NodeMask: node_mask,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut queue = CommandQueue::null();
|
||||||
|
let hr = unsafe {
|
||||||
|
self.CreateCommandQueue(
|
||||||
|
&desc,
|
||||||
|
&d3d12::ID3D12CommandQueue::uuidof(),
|
||||||
|
queue.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(queue, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_descriptor_heap(
|
||||||
|
&self,
|
||||||
|
num_descriptors: u32,
|
||||||
|
heap_type: HeapType,
|
||||||
|
flags: HeapFlags,
|
||||||
|
node_mask: NodeMask,
|
||||||
|
) -> D3DResult<DescriptorHeap> {
|
||||||
|
let desc = d3d12::D3D12_DESCRIPTOR_HEAP_DESC {
|
||||||
|
Type: heap_type as _,
|
||||||
|
NumDescriptors: num_descriptors,
|
||||||
|
Flags: flags.bits(),
|
||||||
|
NodeMask: node_mask,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut heap = DescriptorHeap::null();
|
||||||
|
let hr = unsafe {
|
||||||
|
self.CreateDescriptorHeap(
|
||||||
|
&desc,
|
||||||
|
&d3d12::ID3D12DescriptorHeap::uuidof(),
|
||||||
|
heap.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(heap, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_descriptor_increment_size(&self, heap_type: HeapType) -> u32 {
|
||||||
|
unsafe { self.GetDescriptorHandleIncrementSize(heap_type as _) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_graphics_command_list(
|
||||||
|
&self,
|
||||||
|
list_type: CmdListType,
|
||||||
|
allocator: CommandAllocator,
|
||||||
|
initial: PipelineState,
|
||||||
|
node_mask: NodeMask,
|
||||||
|
) -> D3DResult<GraphicsCommandList> {
|
||||||
|
let mut command_list = GraphicsCommandList::null();
|
||||||
|
let hr = unsafe {
|
||||||
|
self.CreateCommandList(
|
||||||
|
node_mask,
|
||||||
|
list_type as _,
|
||||||
|
allocator.as_mut_ptr(),
|
||||||
|
initial.as_mut_ptr(),
|
||||||
|
&d3d12::ID3D12GraphicsCommandList::uuidof(),
|
||||||
|
command_list.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(command_list, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_query_heap(
|
||||||
|
&self,
|
||||||
|
heap_ty: query::HeapType,
|
||||||
|
count: u32,
|
||||||
|
node_mask: NodeMask,
|
||||||
|
) -> D3DResult<QueryHeap> {
|
||||||
|
let desc = d3d12::D3D12_QUERY_HEAP_DESC {
|
||||||
|
Type: heap_ty as _,
|
||||||
|
Count: count,
|
||||||
|
NodeMask: node_mask,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut query_heap = QueryHeap::null();
|
||||||
|
let hr = unsafe {
|
||||||
|
self.CreateQueryHeap(
|
||||||
|
&desc,
|
||||||
|
&d3d12::ID3D12QueryHeap::uuidof(),
|
||||||
|
query_heap.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(query_heap, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_graphics_pipeline_state(
|
||||||
|
&self,
|
||||||
|
_root_signature: RootSignature,
|
||||||
|
_vs: Shader,
|
||||||
|
_ps: Shader,
|
||||||
|
_gs: Shader,
|
||||||
|
_hs: Shader,
|
||||||
|
_ds: Shader,
|
||||||
|
_node_mask: NodeMask,
|
||||||
|
_cached_pso: CachedPSO,
|
||||||
|
_flags: pso::PipelineStateFlags,
|
||||||
|
) -> D3DResult<PipelineState> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_compute_pipeline_state(
|
||||||
|
&self,
|
||||||
|
root_signature: RootSignature,
|
||||||
|
cs: Shader,
|
||||||
|
node_mask: NodeMask,
|
||||||
|
cached_pso: CachedPSO,
|
||||||
|
flags: pso::PipelineStateFlags,
|
||||||
|
) -> D3DResult<PipelineState> {
|
||||||
|
let mut pipeline = PipelineState::null();
|
||||||
|
let desc = d3d12::D3D12_COMPUTE_PIPELINE_STATE_DESC {
|
||||||
|
pRootSignature: root_signature.as_mut_ptr(),
|
||||||
|
CS: *cs,
|
||||||
|
NodeMask: node_mask,
|
||||||
|
CachedPSO: *cached_pso,
|
||||||
|
Flags: flags.bits(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let hr = unsafe {
|
||||||
|
self.CreateComputePipelineState(
|
||||||
|
&desc,
|
||||||
|
&d3d12::ID3D12PipelineState::uuidof(),
|
||||||
|
pipeline.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(pipeline, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_sampler(
|
||||||
|
&self,
|
||||||
|
sampler: CpuDescriptor,
|
||||||
|
filter: d3d12::D3D12_FILTER,
|
||||||
|
address_mode: TextureAddressMode,
|
||||||
|
mip_lod_bias: f32,
|
||||||
|
max_anisotropy: u32,
|
||||||
|
comparison_op: d3d12::D3D12_COMPARISON_FUNC,
|
||||||
|
border_color: [f32; 4],
|
||||||
|
lod: Range<f32>,
|
||||||
|
) {
|
||||||
|
let desc = d3d12::D3D12_SAMPLER_DESC {
|
||||||
|
Filter: filter,
|
||||||
|
AddressU: address_mode[0],
|
||||||
|
AddressV: address_mode[1],
|
||||||
|
AddressW: address_mode[2],
|
||||||
|
MipLODBias: mip_lod_bias,
|
||||||
|
MaxAnisotropy: max_anisotropy,
|
||||||
|
ComparisonFunc: comparison_op,
|
||||||
|
BorderColor: border_color,
|
||||||
|
MinLOD: lod.start,
|
||||||
|
MaxLOD: lod.end,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.CreateSampler(&desc, sampler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_root_signature(
|
||||||
|
&self,
|
||||||
|
blob: Blob,
|
||||||
|
node_mask: NodeMask,
|
||||||
|
) -> D3DResult<RootSignature> {
|
||||||
|
let mut signature = RootSignature::null();
|
||||||
|
let hr = unsafe {
|
||||||
|
self.CreateRootSignature(
|
||||||
|
node_mask,
|
||||||
|
blob.GetBufferPointer(),
|
||||||
|
blob.GetBufferSize(),
|
||||||
|
&d3d12::ID3D12RootSignature::uuidof(),
|
||||||
|
signature.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(signature, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_command_signature(
|
||||||
|
&self,
|
||||||
|
root_signature: RootSignature,
|
||||||
|
arguments: &[IndirectArgument],
|
||||||
|
stride: u32,
|
||||||
|
node_mask: NodeMask,
|
||||||
|
) -> D3DResult<CommandSignature> {
|
||||||
|
let mut signature = CommandSignature::null();
|
||||||
|
let desc = d3d12::D3D12_COMMAND_SIGNATURE_DESC {
|
||||||
|
ByteStride: stride,
|
||||||
|
NumArgumentDescs: arguments.len() as _,
|
||||||
|
pArgumentDescs: arguments.as_ptr() as *const _,
|
||||||
|
NodeMask: node_mask,
|
||||||
|
};
|
||||||
|
|
||||||
|
let hr = unsafe {
|
||||||
|
self.CreateCommandSignature(
|
||||||
|
&desc,
|
||||||
|
root_signature.as_mut_ptr(),
|
||||||
|
&d3d12::ID3D12RootSignature::uuidof(),
|
||||||
|
signature.mut_void(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(signature, hr)
|
||||||
|
}
|
||||||
|
}
|
74
src/lib.rs
Normal file
74
src/lib.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
extern crate winapi;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate bitflags;
|
||||||
|
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use winapi::shared::dxgiformat;
|
||||||
|
use winapi::um::{d3d12, d3dcommon};
|
||||||
|
|
||||||
|
mod com;
|
||||||
|
pub mod command_allocator;
|
||||||
|
pub mod command_list;
|
||||||
|
pub mod descriptor;
|
||||||
|
pub mod device;
|
||||||
|
pub mod pso;
|
||||||
|
pub mod query;
|
||||||
|
pub mod queue;
|
||||||
|
pub mod resource;
|
||||||
|
pub mod sync;
|
||||||
|
|
||||||
|
pub use self::com::WeakPtr;
|
||||||
|
pub use self::command_allocator::CommandAllocator;
|
||||||
|
pub use self::command_list::{CommandSignature, GraphicsCommandList};
|
||||||
|
pub use self::descriptor::{CpuDescriptor, DescriptorHeap, GpuDescriptor, RootSignature};
|
||||||
|
pub use self::device::Device;
|
||||||
|
pub use self::pso::{CachedPSO, PipelineState, Shader};
|
||||||
|
pub use self::query::QueryHeap;
|
||||||
|
pub use self::queue::CommandQueue;
|
||||||
|
pub use self::resource::{Heap, Resource};
|
||||||
|
pub use self::sync::Fence;
|
||||||
|
|
||||||
|
pub use winapi::shared::winerror::HRESULT;
|
||||||
|
|
||||||
|
pub type D3DResult<T> = (T, HRESULT);
|
||||||
|
pub type GpuAddress = d3d12::D3D12_GPU_VIRTUAL_ADDRESS;
|
||||||
|
pub type Format = dxgiformat::DXGI_FORMAT;
|
||||||
|
pub type Rect = d3d12::D3D12_RECT;
|
||||||
|
pub type NodeMask = u32;
|
||||||
|
|
||||||
|
/// Draw vertex count.
|
||||||
|
pub type VertexCount = u32;
|
||||||
|
/// Draw vertex base offset.
|
||||||
|
pub type VertexOffset = i32;
|
||||||
|
/// Draw number of indices.
|
||||||
|
pub type IndexCount = u32;
|
||||||
|
/// Draw number of instances.
|
||||||
|
pub type InstanceCount = u32;
|
||||||
|
/// Number of work groups.
|
||||||
|
pub type WorkGroupCount = [u32; 3];
|
||||||
|
|
||||||
|
pub type TextureAddressMode = [d3d12::D3D12_TEXTURE_ADDRESS_MODE; 3];
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum FeatureLevel {
|
||||||
|
L9_1 = d3dcommon::D3D_FEATURE_LEVEL_9_1,
|
||||||
|
L9_2 = d3dcommon::D3D_FEATURE_LEVEL_9_2,
|
||||||
|
L9_3 = d3dcommon::D3D_FEATURE_LEVEL_9_3,
|
||||||
|
L10_0 = d3dcommon::D3D_FEATURE_LEVEL_10_0,
|
||||||
|
L10_1 = d3dcommon::D3D_FEATURE_LEVEL_10_1,
|
||||||
|
L11_0 = d3dcommon::D3D_FEATURE_LEVEL_11_0,
|
||||||
|
L11_1 = d3dcommon::D3D_FEATURE_LEVEL_11_1,
|
||||||
|
L12_0 = d3dcommon::D3D_FEATURE_LEVEL_12_0,
|
||||||
|
L12_1 = d3dcommon::D3D_FEATURE_LEVEL_12_1,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Blob = self::com::WeakPtr<d3dcommon::ID3DBlob>;
|
||||||
|
|
||||||
|
pub type Error = self::com::WeakPtr<d3dcommon::ID3DBlob>;
|
||||||
|
impl Error {
|
||||||
|
pub unsafe fn as_c_str(&self) -> &CStr {
|
||||||
|
debug_assert!(!self.is_null());
|
||||||
|
let data = self.GetBufferPointer();
|
||||||
|
CStr::from_ptr(data as *const _ as *const _)
|
||||||
|
}
|
||||||
|
}
|
164
src/pso.rs
Normal file
164
src/pso.rs
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
//! Pipeline state
|
||||||
|
|
||||||
|
use com::WeakPtr;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::{ffi, ptr};
|
||||||
|
use winapi::um::{d3d12, d3dcompiler};
|
||||||
|
use {Blob, D3DResult, Error};
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct PipelineStateFlags: u32 {
|
||||||
|
const TOOL_DEBUG = d3d12::D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct ShaderCompileFlags: u32 {
|
||||||
|
const DEBUG = d3dcompiler::D3DCOMPILE_DEBUG;
|
||||||
|
const SKIP_VALIDATION = d3dcompiler::D3DCOMPILE_SKIP_VALIDATION;
|
||||||
|
const SKIP_OPTIMIZATION = d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||||
|
const PACK_MATRIX_ROW_MAJOR = d3dcompiler::D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
|
||||||
|
const PACK_MATRIX_COLUMN_MAJOR = d3dcompiler::D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
|
||||||
|
const PARTIAL_PRECISION = d3dcompiler::D3DCOMPILE_PARTIAL_PRECISION;
|
||||||
|
// TODO: add missing flags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Shader(d3d12::D3D12_SHADER_BYTECODE);
|
||||||
|
impl Shader {
|
||||||
|
pub fn null() -> Self {
|
||||||
|
Shader(d3d12::D3D12_SHADER_BYTECODE {
|
||||||
|
BytecodeLength: 0,
|
||||||
|
pShaderBytecode: ptr::null(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// `blob` may not be null.
|
||||||
|
pub fn from_blob(blob: Blob) -> Self {
|
||||||
|
Shader(d3d12::D3D12_SHADER_BYTECODE {
|
||||||
|
BytecodeLength: unsafe { blob.GetBufferSize() },
|
||||||
|
pShaderBytecode: unsafe { blob.GetBufferPointer() },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile a shader from raw HLSL.
|
||||||
|
///
|
||||||
|
/// * `target`: example format: `ps_5_1`.
|
||||||
|
pub fn compile(
|
||||||
|
code: &[u8],
|
||||||
|
target: &ffi::CStr,
|
||||||
|
entry: &ffi::CStr,
|
||||||
|
flags: ShaderCompileFlags,
|
||||||
|
) -> D3DResult<(Blob, Error)> {
|
||||||
|
let mut shader = Blob::null();
|
||||||
|
let mut error = Error::null();
|
||||||
|
|
||||||
|
let hr = unsafe {
|
||||||
|
d3dcompiler::D3DCompile(
|
||||||
|
code.as_ptr() as *const _,
|
||||||
|
code.len(),
|
||||||
|
ptr::null(), // defines
|
||||||
|
ptr::null(), // include
|
||||||
|
ptr::null_mut(),
|
||||||
|
entry.as_ptr() as *const _,
|
||||||
|
target.as_ptr() as *const _,
|
||||||
|
flags.bits(),
|
||||||
|
0,
|
||||||
|
shader.mut_void() as *mut *mut _,
|
||||||
|
error.mut_void() as *mut *mut _,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
((shader, error), hr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Shader {
|
||||||
|
type Target = d3d12::D3D12_SHADER_BYTECODE;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<Blob>> for Shader {
|
||||||
|
fn from(blob: Option<Blob>) -> Self {
|
||||||
|
match blob {
|
||||||
|
Some(b) => Shader::from_blob(b),
|
||||||
|
None => Shader::null(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE);
|
||||||
|
impl CachedPSO {
|
||||||
|
pub fn null() -> Self {
|
||||||
|
CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE {
|
||||||
|
CachedBlobSizeInBytes: 0,
|
||||||
|
pCachedBlob: ptr::null(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// `blob` may not be null.
|
||||||
|
pub fn from_blob(blob: Blob) -> Self {
|
||||||
|
CachedPSO(d3d12::D3D12_CACHED_PIPELINE_STATE {
|
||||||
|
CachedBlobSizeInBytes: unsafe { blob.GetBufferSize() },
|
||||||
|
pCachedBlob: unsafe { blob.GetBufferPointer() },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for CachedPSO {
|
||||||
|
type Target = d3d12::D3D12_CACHED_PIPELINE_STATE;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type PipelineState = WeakPtr<d3d12::ID3D12PipelineState>;
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum Subobject {
|
||||||
|
RootSignature = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE,
|
||||||
|
VS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS,
|
||||||
|
PS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS,
|
||||||
|
DS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS,
|
||||||
|
HS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS,
|
||||||
|
GS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS,
|
||||||
|
CS = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS,
|
||||||
|
StreamOutput = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT,
|
||||||
|
Blend = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND,
|
||||||
|
SampleMask = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK,
|
||||||
|
Rasterizer = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER,
|
||||||
|
DepthStencil = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL,
|
||||||
|
InputLayout = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT,
|
||||||
|
IBStripCut = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE,
|
||||||
|
PrimitiveTopology = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY,
|
||||||
|
RTFormats = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS,
|
||||||
|
DSFormat = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT,
|
||||||
|
SampleDesc = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC,
|
||||||
|
NodeMask = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK,
|
||||||
|
CachedPSO = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO,
|
||||||
|
Flags = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS,
|
||||||
|
DepthStencil1 = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1,
|
||||||
|
// ViewInstancing = d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subobject of a pipeline stream description
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PipelineStateSubobject<T> {
|
||||||
|
subobject_align: [usize; 0], // Subobjects must have the same alignment as pointers.
|
||||||
|
subobject_type: d3d12::D3D12_PIPELINE_STATE_SUBOBJECT_TYPE,
|
||||||
|
subobject: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> PipelineStateSubobject<T> {
|
||||||
|
pub fn new(subobject_type: Subobject, subobject: T) -> Self {
|
||||||
|
PipelineStateSubobject {
|
||||||
|
subobject_align: [],
|
||||||
|
subobject_type: subobject_type as _,
|
||||||
|
subobject,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
src/query.rs
Normal file
15
src/query.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use com::WeakPtr;
|
||||||
|
use winapi::um::d3d12;
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum HeapType {
|
||||||
|
Occlusion = d3d12::D3D12_QUERY_HEAP_TYPE_OCCLUSION,
|
||||||
|
Timestamp = d3d12::D3D12_QUERY_HEAP_TYPE_TIMESTAMP,
|
||||||
|
PipelineStatistics = d3d12::D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS,
|
||||||
|
SOStatistics = d3d12::D3D12_QUERY_HEAP_TYPE_SO_STATISTICS,
|
||||||
|
// VideoDecodeStatistcs = d3d12::D3D12_QUERY_HEAP_TYPE_VIDEO_DECODE_STATISTICS,
|
||||||
|
// CopyQueueTimestamp = d3d12::D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type QueryHeap = WeakPtr<d3d12::ID3D12QueryHeap>;
|
25
src/queue.rs
Normal file
25
src/queue.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use com::WeakPtr;
|
||||||
|
use sync::Fence;
|
||||||
|
use winapi::um::d3d12;
|
||||||
|
use HRESULT;
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum Priority {
|
||||||
|
Normal = d3d12::D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
|
||||||
|
High = d3d12::D3D12_COMMAND_QUEUE_PRIORITY_HIGH,
|
||||||
|
GlobalRealtime = d3d12::D3D12_COMMAND_QUEUE_PRIORITY_GLOBAL_REALTIME,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct CommandQueueFlags: u32 {
|
||||||
|
const DISABLE_GPU_TIMEOUT = d3d12::D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type CommandQueue = WeakPtr<d3d12::ID3D12CommandQueue>;
|
||||||
|
|
||||||
|
impl CommandQueue {
|
||||||
|
pub fn signal(&self, fence: Fence, value: u64) -> HRESULT {
|
||||||
|
unsafe { self.Signal(fence.as_mut_ptr(), value) }
|
||||||
|
}
|
||||||
|
}
|
57
src/resource.rs
Normal file
57
src/resource.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//! GPU Resource
|
||||||
|
|
||||||
|
use com::WeakPtr;
|
||||||
|
use std::ops::Range;
|
||||||
|
use std::ptr;
|
||||||
|
use winapi::um::d3d12;
|
||||||
|
use {D3DResult, Rect};
|
||||||
|
|
||||||
|
pub type Subresource = u32;
|
||||||
|
|
||||||
|
pub struct DiscardRegion<'a> {
|
||||||
|
pub rects: &'a [Rect],
|
||||||
|
pub subregions: Range<Subresource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Heap = WeakPtr<d3d12::ID3D12Heap>;
|
||||||
|
|
||||||
|
pub type Resource = WeakPtr<d3d12::ID3D12Resource>;
|
||||||
|
|
||||||
|
impl Resource {
|
||||||
|
///
|
||||||
|
pub fn map(
|
||||||
|
&self,
|
||||||
|
subresource: Subresource,
|
||||||
|
read_range: Option<Range<usize>>,
|
||||||
|
) -> D3DResult<*mut ()> {
|
||||||
|
let mut ptr = ptr::null_mut();
|
||||||
|
let read_range = read_range.map(|r| d3d12::D3D12_RANGE {
|
||||||
|
Begin: r.start,
|
||||||
|
End: r.end,
|
||||||
|
});
|
||||||
|
let read = match read_range {
|
||||||
|
Some(ref r) => r as *const _,
|
||||||
|
None => ptr::null(),
|
||||||
|
};
|
||||||
|
let hr = unsafe { self.Map(subresource, read, &mut ptr) };
|
||||||
|
|
||||||
|
(ptr as _, hr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unmap(&self, subresource: Subresource, write_range: Option<Range<usize>>) {
|
||||||
|
let write_range = write_range.map(|r| d3d12::D3D12_RANGE {
|
||||||
|
Begin: r.start,
|
||||||
|
End: r.end,
|
||||||
|
});
|
||||||
|
let write = match write_range {
|
||||||
|
Some(ref r) => r as *const _,
|
||||||
|
None => ptr::null(),
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe { self.Unmap(subresource, write) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gpu_virtual_address(&self) -> u64 {
|
||||||
|
unsafe { self.GetGPUVirtualAddress() }
|
||||||
|
}
|
||||||
|
}
|
21
src/sync.rs
Normal file
21
src/sync.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use com::WeakPtr;
|
||||||
|
use winapi::um::d3d12;
|
||||||
|
use winapi::um::winnt;
|
||||||
|
use HRESULT;
|
||||||
|
|
||||||
|
pub type Event = winnt::HANDLE;
|
||||||
|
pub type Fence = WeakPtr<d3d12::ID3D12Fence>;
|
||||||
|
|
||||||
|
impl Fence {
|
||||||
|
pub fn set_event_on_completion(&self, event: Event, value: u64) -> HRESULT {
|
||||||
|
unsafe { self.SetEventOnCompletion(value, event) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> u64 {
|
||||||
|
unsafe { self.GetCompletedValue() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn signal(&self, value: u64) -> HRESULT {
|
||||||
|
unsafe { self.Signal(value) }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user