mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 00:03:29 +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