d3d12: partially implement lut texture
This commit is contained in:
parent
2f82c5f430
commit
9a3ce029d7
|
@ -1,3 +1,16 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||||
|
|
||||||
|
// todo: make this return error
|
||||||
|
macro_rules! assume_d3d12_init {
|
||||||
|
($value:ident, $call:literal) => {
|
||||||
|
let $value = $value.expect($call);
|
||||||
|
};
|
||||||
|
(mut $value:ident, $call:literal) => {
|
||||||
|
let mut $value = $value.expect($call);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro for unwrapping result of a D3D function.
|
||||||
|
pub(crate) use assume_d3d12_init;
|
||||||
|
|
|
@ -1,14 +1,23 @@
|
||||||
use std::error::Error;
|
use crate::error;
|
||||||
use std::path::Path;
|
use crate::heap::{D3D12DescriptorHeap, LutTextureHeap};
|
||||||
use rustc_hash::FxHashMap;
|
use crate::samplers::SamplerSet;
|
||||||
use windows::Win32::Graphics::Direct3D12::ID3D12Device;
|
use crate::texture::LutTexture;
|
||||||
use librashader_presets::{ShaderPreset, TextureConfig};
|
use librashader_presets::{ShaderPreset, TextureConfig};
|
||||||
use librashader_reflect::back::targets::HLSL;
|
use librashader_reflect::back::targets::HLSL;
|
||||||
use librashader_reflect::front::GlslangCompilation;
|
use librashader_reflect::front::GlslangCompilation;
|
||||||
use librashader_reflect::reflect::presets::CompilePresetTarget;
|
use librashader_reflect::reflect::presets::CompilePresetTarget;
|
||||||
use crate::error;
|
use librashader_runtime::image::{Image, UVDirection};
|
||||||
use crate::samplers::SamplerSet;
|
use rustc_hash::FxHashMap;
|
||||||
use crate::texture::LutTexture;
|
use std::error::Error;
|
||||||
|
use std::path::Path;
|
||||||
|
use windows::core::Interface;
|
||||||
|
use windows::Win32::Graphics::Direct3D12::{
|
||||||
|
ID3D12CommandAllocator, ID3D12CommandList, ID3D12CommandQueue, ID3D12Device, ID3D12Fence,
|
||||||
|
ID3D12GraphicsCommandList, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC,
|
||||||
|
D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE,
|
||||||
|
};
|
||||||
|
use windows::Win32::System::Threading::{CreateEventA, WaitForSingleObject};
|
||||||
|
use windows::Win32::System::WindowsProgramming::INFINITE;
|
||||||
|
|
||||||
pub struct FilterChainD3D12 {
|
pub struct FilterChainD3D12 {
|
||||||
pub(crate) common: FilterCommon,
|
pub(crate) common: FilterCommon,
|
||||||
|
@ -28,6 +37,8 @@ pub(crate) struct FilterCommon {
|
||||||
// pub history_textures: Box<[Option<InputTexture>]>,
|
// pub history_textures: Box<[Option<InputTexture>]>,
|
||||||
// pub config: FilterMutable,
|
// pub config: FilterMutable,
|
||||||
// pub disable_mipmaps: bool,
|
// pub disable_mipmaps: bool,
|
||||||
|
lut_heap: D3D12DescriptorHeap<LutTextureHeap>,
|
||||||
|
luts: FxHashMap<usize, LutTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilterChainD3D12 {
|
impl FilterChainD3D12 {
|
||||||
|
@ -44,9 +55,59 @@ impl FilterChainD3D12 {
|
||||||
|
|
||||||
fn load_luts(
|
fn load_luts(
|
||||||
device: &ID3D12Device,
|
device: &ID3D12Device,
|
||||||
|
heap: &mut D3D12DescriptorHeap<LutTextureHeap>,
|
||||||
textures: &[TextureConfig],
|
textures: &[TextureConfig],
|
||||||
) -> error::Result<FxHashMap<usize, LutTexture>> {
|
) -> error::Result<FxHashMap<usize, LutTexture>> {
|
||||||
todo!()
|
unsafe {
|
||||||
|
// 1 time queue infrastructure for lut uploads
|
||||||
|
let command_pool: ID3D12CommandAllocator =
|
||||||
|
device.CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT)?;
|
||||||
|
let cmd: ID3D12GraphicsCommandList =
|
||||||
|
device.CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, &command_pool, None)?;
|
||||||
|
let queue: ID3D12CommandQueue =
|
||||||
|
device.CreateCommandQueue(&D3D12_COMMAND_QUEUE_DESC {
|
||||||
|
Type: D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||||
|
Priority: 0,
|
||||||
|
Flags: D3D12_COMMAND_QUEUE_FLAG_NONE,
|
||||||
|
NodeMask: 0,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let fence_event = unsafe { CreateEventA(None, false, false, None)? };
|
||||||
|
let fence: ID3D12Fence = device.CreateFence(0, D3D12_FENCE_FLAG_NONE)?;
|
||||||
|
|
||||||
|
let mut luts = FxHashMap::default();
|
||||||
|
|
||||||
|
for (index, texture) in textures.iter().enumerate() {
|
||||||
|
let image = Image::load(&texture.path, UVDirection::TopLeft)?;
|
||||||
|
|
||||||
|
let texture = LutTexture::new(
|
||||||
|
device,
|
||||||
|
heap,
|
||||||
|
&cmd,
|
||||||
|
&image,
|
||||||
|
texture.filter_mode,
|
||||||
|
texture.wrap_mode,
|
||||||
|
// todo: mipmaps
|
||||||
|
false,
|
||||||
|
)?;
|
||||||
|
luts.insert(index, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Close()?;
|
||||||
|
|
||||||
|
queue.ExecuteCommandLists(&[cmd.cast()?]);
|
||||||
|
queue.Signal(&fence, 1)?;
|
||||||
|
|
||||||
|
// Wait until the previous frame is finished.
|
||||||
|
if unsafe { fence.GetCompletedValue() } < 1 {
|
||||||
|
unsafe { fence.SetEventOnCompletion(1, fence_event) }
|
||||||
|
.ok()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
unsafe { WaitForSingleObject(fence_event, INFINITE) };
|
||||||
|
}
|
||||||
|
Ok(luts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load a filter chain from a pre-parsed `ShaderPreset`.
|
/// Load a filter chain from a pre-parsed `ShaderPreset`.
|
||||||
|
@ -55,17 +116,23 @@ impl FilterChainD3D12 {
|
||||||
preset: ShaderPreset,
|
preset: ShaderPreset,
|
||||||
options: Option<&()>,
|
options: Option<&()>,
|
||||||
) -> error::Result<FilterChainD3D12> {
|
) -> error::Result<FilterChainD3D12> {
|
||||||
let (passes, semantics) = HLSL::compile_preset_passes::<
|
let (passes, semantics) = HLSL::compile_preset_passes::<GlslangCompilation, Box<dyn Error>>(
|
||||||
GlslangCompilation,
|
preset.shaders,
|
||||||
Box<dyn Error>,
|
&preset.textures,
|
||||||
>(preset.shaders, &preset.textures)?;
|
)?;
|
||||||
|
|
||||||
|
let samplers = SamplerSet::new(device)?;
|
||||||
|
let mut lut_heap = D3D12DescriptorHeap::new(device, preset.textures.len())?;
|
||||||
|
|
||||||
|
let luts = FilterChainD3D12::load_luts(device, &mut lut_heap, &preset.textures)?;
|
||||||
|
|
||||||
let samplers = SamplerSet::new(&device)?;
|
|
||||||
Ok(FilterChainD3D12 {
|
Ok(FilterChainD3D12 {
|
||||||
common: FilterCommon {
|
common: FilterCommon {
|
||||||
d3d12: device.clone(),
|
d3d12: device.clone(),
|
||||||
samplers,
|
samplers,
|
||||||
|
lut_heap,
|
||||||
|
luts,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
|
use crate::error;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use windows::Win32::Graphics::Direct3D12::{D3D12_CPU_DESCRIPTOR_HANDLE, D3D12_DESCRIPTOR_HEAP_DESC, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_GPU_DESCRIPTOR_HANDLE, ID3D12DescriptorHeap, ID3D12Device};
|
use windows::Win32::Graphics::Direct3D12::{
|
||||||
use crate::error;
|
ID3D12DescriptorHeap, ID3D12Device, D3D12_CPU_DESCRIPTOR_HANDLE, D3D12_DESCRIPTOR_HEAP_DESC,
|
||||||
|
D3D12_DESCRIPTOR_HEAP_FLAG_NONE, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
|
||||||
|
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||||
|
D3D12_GPU_DESCRIPTOR_HANDLE,
|
||||||
|
};
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
pub trait D3D12HeapType {
|
pub trait D3D12HeapType {
|
||||||
fn get_desc(size: usize) -> D3D12_DESCRIPTOR_HEAP_DESC;
|
fn get_desc(size: usize) -> D3D12_DESCRIPTOR_HEAP_DESC;
|
||||||
}
|
}
|
||||||
pub struct SamplerHeap;
|
|
||||||
|
|
||||||
impl const D3D12HeapType for SamplerHeap
|
pub trait D3D12ShaderVisibleHeapType: D3D12HeapType {}
|
||||||
{
|
|
||||||
|
pub struct SamplerPaletteHeap;
|
||||||
|
pub struct LutTextureHeap;
|
||||||
|
|
||||||
|
impl D3D12ShaderVisibleHeapType for SamplerPaletteHeap {}
|
||||||
|
|
||||||
|
impl const D3D12HeapType for SamplerPaletteHeap {
|
||||||
|
// sampler palettes just get set directly
|
||||||
fn get_desc(size: usize) -> D3D12_DESCRIPTOR_HEAP_DESC {
|
fn get_desc(size: usize) -> D3D12_DESCRIPTOR_HEAP_DESC {
|
||||||
D3D12_DESCRIPTOR_HEAP_DESC {
|
D3D12_DESCRIPTOR_HEAP_DESC {
|
||||||
Type: D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
Type: D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
||||||
|
@ -22,12 +33,24 @@ impl const D3D12HeapType for SamplerHeap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl const D3D12HeapType for LutTextureHeap {
|
||||||
|
// Lut texture heaps are CPU only and get bound to the descriptor heap of the shader.
|
||||||
|
fn get_desc(size: usize) -> D3D12_DESCRIPTOR_HEAP_DESC {
|
||||||
|
D3D12_DESCRIPTOR_HEAP_DESC {
|
||||||
|
Type: D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
||||||
|
NumDescriptors: size as u32,
|
||||||
|
Flags: D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
|
||||||
|
NodeMask: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct D3D12DescriptorHeapSlot<T> {
|
pub struct D3D12DescriptorHeapSlot<T> {
|
||||||
cpu_handle: D3D12_CPU_DESCRIPTOR_HANDLE,
|
cpu_handle: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||||
gpu_handle: D3D12_GPU_DESCRIPTOR_HANDLE,
|
gpu_handle: Option<D3D12_GPU_DESCRIPTOR_HANDLE>,
|
||||||
heap: Arc<RefCell<D3D12DescriptorHeapInner>>,
|
heap: Arc<RefCell<D3D12DescriptorHeapInner>>,
|
||||||
slot: usize,
|
slot: usize,
|
||||||
_pd: PhantomData<T>
|
_pd: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> D3D12DescriptorHeapSlot<T> {
|
impl<T> D3D12DescriptorHeapSlot<T> {
|
||||||
|
@ -43,9 +66,11 @@ impl<T> AsRef<D3D12_CPU_DESCRIPTOR_HANDLE> for D3D12DescriptorHeapSlot<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> AsRef<D3D12_GPU_DESCRIPTOR_HANDLE> for D3D12DescriptorHeapSlot<T> {
|
impl<T: D3D12ShaderVisibleHeapType> AsRef<D3D12_GPU_DESCRIPTOR_HANDLE>
|
||||||
|
for D3D12DescriptorHeapSlot<T>
|
||||||
|
{
|
||||||
fn as_ref(&self) -> &D3D12_GPU_DESCRIPTOR_HANDLE {
|
fn as_ref(&self) -> &D3D12_GPU_DESCRIPTOR_HANDLE {
|
||||||
&self.gpu_handle
|
self.gpu_handle.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +78,7 @@ struct D3D12DescriptorHeapInner {
|
||||||
heap: ID3D12DescriptorHeap,
|
heap: ID3D12DescriptorHeap,
|
||||||
desc: D3D12_DESCRIPTOR_HEAP_DESC,
|
desc: D3D12_DESCRIPTOR_HEAP_DESC,
|
||||||
cpu_start: D3D12_CPU_DESCRIPTOR_HANDLE,
|
cpu_start: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||||
gpu_start: D3D12_GPU_DESCRIPTOR_HANDLE,
|
gpu_start: Option<D3D12_GPU_DESCRIPTOR_HANDLE>,
|
||||||
handle_size: usize,
|
handle_size: usize,
|
||||||
start: usize,
|
start: usize,
|
||||||
// Bit flag representation of available handles in the heap.
|
// Bit flag representation of available handles in the heap.
|
||||||
|
@ -65,30 +90,40 @@ struct D3D12DescriptorHeapInner {
|
||||||
|
|
||||||
pub struct D3D12DescriptorHeap<T>(Arc<RefCell<D3D12DescriptorHeapInner>>, PhantomData<T>);
|
pub struct D3D12DescriptorHeap<T>(Arc<RefCell<D3D12DescriptorHeapInner>>, PhantomData<T>);
|
||||||
|
|
||||||
impl<T:D3D12HeapType> D3D12DescriptorHeap<T> {
|
impl<T: D3D12HeapType> D3D12DescriptorHeap<T> {
|
||||||
pub fn new(device: &ID3D12Device, size: usize) -> error::Result<D3D12DescriptorHeap<T>> {
|
pub fn new(device: &ID3D12Device, size: usize) -> error::Result<D3D12DescriptorHeap<T>> {
|
||||||
let desc = T::get_desc(size);
|
let desc = T::get_desc(size);
|
||||||
unsafe {
|
unsafe { D3D12DescriptorHeap::new_with_desc(device, desc) }
|
||||||
D3D12DescriptorHeap::new_with_desc(device, desc)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> D3D12DescriptorHeap<T> {
|
impl<T> D3D12DescriptorHeap<T> {
|
||||||
pub unsafe fn new_with_desc(device: &ID3D12Device, desc: D3D12_DESCRIPTOR_HEAP_DESC) -> error::Result<D3D12DescriptorHeap<T>> {
|
pub unsafe fn new_with_desc(
|
||||||
|
device: &ID3D12Device,
|
||||||
|
desc: D3D12_DESCRIPTOR_HEAP_DESC,
|
||||||
|
) -> error::Result<D3D12DescriptorHeap<T>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let heap: ID3D12DescriptorHeap = device.CreateDescriptorHeap(&desc)?;
|
let heap: ID3D12DescriptorHeap = device.CreateDescriptorHeap(&desc)?;
|
||||||
let cpu_start = heap.GetCPUDescriptorHandleForHeapStart();
|
let cpu_start = heap.GetCPUDescriptorHandleForHeapStart();
|
||||||
let gpu_start = heap.GetGPUDescriptorHandleForHeapStart();
|
|
||||||
Ok(D3D12DescriptorHeap(Arc::new(RefCell::new(D3D12DescriptorHeapInner {
|
let gpu_start = if (desc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE).0 != 0 {
|
||||||
heap,
|
Some(heap.GetGPUDescriptorHandleForHeapStart())
|
||||||
desc,
|
} else {
|
||||||
cpu_start,
|
None
|
||||||
gpu_start,
|
};
|
||||||
handle_size: device.GetDescriptorHandleIncrementSize(desc.Type) as usize,
|
|
||||||
start: 0,
|
Ok(D3D12DescriptorHeap(
|
||||||
map: vec![false; desc.NumDescriptors as usize].into_boxed_slice(),
|
Arc::new(RefCell::new(D3D12DescriptorHeapInner {
|
||||||
})), PhantomData::default()))
|
heap,
|
||||||
|
desc,
|
||||||
|
cpu_start,
|
||||||
|
gpu_start,
|
||||||
|
handle_size: device.GetDescriptorHandleIncrementSize(desc.Type) as usize,
|
||||||
|
start: 0,
|
||||||
|
map: vec![false; desc.NumDescriptors as usize].into_boxed_slice(),
|
||||||
|
})),
|
||||||
|
PhantomData::default(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,9 +137,12 @@ impl<T> D3D12DescriptorHeap<T> {
|
||||||
handle.ptr = inner.cpu_start.ptr + (i * inner.handle_size);
|
handle.ptr = inner.cpu_start.ptr + (i * inner.handle_size);
|
||||||
inner.start = i + 1;
|
inner.start = i + 1;
|
||||||
|
|
||||||
let gpu_handle = D3D12_GPU_DESCRIPTOR_HANDLE {
|
let gpu_handle = inner
|
||||||
ptr: (handle.ptr as u64 - inner.cpu_start.ptr as u64 + inner.gpu_start.ptr),
|
.gpu_start
|
||||||
};
|
.map(|gpu_start| D3D12_GPU_DESCRIPTOR_HANDLE {
|
||||||
|
ptr: (handle.ptr as u64 - inner.cpu_start.ptr as u64 + gpu_start.ptr),
|
||||||
|
});
|
||||||
|
|
||||||
return Ok(D3D12DescriptorHeapSlot {
|
return Ok(D3D12DescriptorHeapSlot {
|
||||||
cpu_handle: handle,
|
cpu_handle: handle,
|
||||||
slot: i,
|
slot: i,
|
||||||
|
|
|
@ -32,8 +32,8 @@ use std::path::Path;
|
||||||
|
|
||||||
pub trait DXSample {
|
pub trait DXSample {
|
||||||
fn new(filter: impl AsRef<Path>, command_line: &SampleCommandLine) -> Result<Self>
|
fn new(filter: impl AsRef<Path>, command_line: &SampleCommandLine) -> Result<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
fn bind_to_window(&mut self, hwnd: &HWND) -> Result<()>;
|
fn bind_to_window(&mut self, hwnd: &HWND) -> Result<()>;
|
||||||
|
|
||||||
|
@ -69,8 +69,8 @@ fn build_command_line() -> SampleCommandLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_sample<S>(mut sample: S) -> Result<()>
|
fn run_sample<S>(mut sample: S) -> Result<()>
|
||||||
where
|
where
|
||||||
S: DXSample,
|
S: DXSample,
|
||||||
{
|
{
|
||||||
let instance = unsafe { GetModuleHandleA(None)? };
|
let instance = unsafe { GetModuleHandleA(None)? };
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ fn get_hardware_adapter(factory: &IDXGIFactory4) -> Result<IDXGIAdapter1> {
|
||||||
std::ptr::null_mut::<Option<ID3D12Device>>(),
|
std::ptr::null_mut::<Option<ID3D12Device>>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
return Ok(adapter);
|
return Ok(adapter);
|
||||||
}
|
}
|
||||||
|
@ -223,18 +223,23 @@ fn get_hardware_adapter(factory: &IDXGIFactory4) -> Result<IDXGIAdapter1> {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "system" fn debug_log(category: D3D12_MESSAGE_CATEGORY, severity: D3D12_MESSAGE_SEVERITY, id: D3D12_MESSAGE_ID, pdescription: ::windows::core::PCSTR, pcontext: *mut ::core::ffi::c_void) {
|
unsafe extern "system" fn debug_log(
|
||||||
|
category: D3D12_MESSAGE_CATEGORY,
|
||||||
|
severity: D3D12_MESSAGE_SEVERITY,
|
||||||
|
id: D3D12_MESSAGE_ID,
|
||||||
|
pdescription: ::windows::core::PCSTR,
|
||||||
|
pcontext: *mut ::core::ffi::c_void,
|
||||||
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let desc = CStr::from_ptr(pdescription.as_ptr().cast());
|
let desc = CStr::from_ptr(pdescription.as_ptr().cast());
|
||||||
eprintln!("[{severity:?}-{category:?}] {desc:?}")
|
eprintln!("[{severity:?}-{category:?}] {desc:?}")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod d3d12_hello_triangle {
|
pub mod d3d12_hello_triangle {
|
||||||
use std::path::Path;
|
|
||||||
use crate::filter_chain::FilterChainD3D12;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::filter_chain::FilterChainD3D12;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
const FRAME_COUNT: u32 = 2;
|
const FRAME_COUNT: u32 = 2;
|
||||||
|
|
||||||
|
@ -274,10 +279,17 @@ pub mod d3d12_hello_triangle {
|
||||||
fn new(filter: impl AsRef<Path>, command_line: &SampleCommandLine) -> Result<Self> {
|
fn new(filter: impl AsRef<Path>, command_line: &SampleCommandLine) -> Result<Self> {
|
||||||
let (dxgi_factory, device) = create_device(command_line)?;
|
let (dxgi_factory, device) = create_device(command_line)?;
|
||||||
//
|
//
|
||||||
// let queue = device.cast::<ID3D12InfoQueue1>()?;
|
let queue = device.cast::<ID3D12InfoQueue1>()?;
|
||||||
// unsafe {
|
unsafe {
|
||||||
// queue.RegisterMessageCallback(Some(debug_log), D3D12_MESSAGE_CALLBACK_FLAG_NONE, std::ptr::null_mut(), &mut 0).expect("could not register message callback");
|
queue
|
||||||
// }
|
.RegisterMessageCallback(
|
||||||
|
Some(debug_log),
|
||||||
|
D3D12_MESSAGE_CALLBACK_FLAG_NONE,
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
&mut 0,
|
||||||
|
)
|
||||||
|
.expect("could not register message callback");
|
||||||
|
}
|
||||||
let filter = FilterChainD3D12::load_from_path(&device, filter, None).unwrap();
|
let filter = FilterChainD3D12::load_from_path(&device, filter, None).unwrap();
|
||||||
|
|
||||||
Ok(Sample {
|
Ok(Sample {
|
||||||
|
@ -321,7 +333,7 @@ pub mod d3d12_hello_triangle {
|
||||||
None,
|
None,
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
.cast()?;
|
.cast()?;
|
||||||
|
|
||||||
// This sample does not support fullscreen transitions
|
// This sample does not support fullscreen transitions
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -496,11 +508,7 @@ pub mod d3d12_hello_triangle {
|
||||||
// Record commands.
|
// Record commands.
|
||||||
unsafe {
|
unsafe {
|
||||||
// TODO: workaround for https://github.com/microsoft/win32metadata/issues/1006
|
// TODO: workaround for https://github.com/microsoft/win32metadata/issues/1006
|
||||||
command_list.ClearRenderTargetView(
|
command_list.ClearRenderTargetView(rtv_handle, &*[0.3, 0.4, 0.6, 1.0].as_ptr(), &[]);
|
||||||
rtv_handle,
|
|
||||||
&*[0.3, 0.4, 0.6, 1.0].as_ptr(),
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
command_list.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
command_list.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
command_list.IASetVertexBuffers(0, Some(&[resources.vbv]));
|
command_list.IASetVertexBuffers(0, Some(&[resources.vbv]));
|
||||||
command_list.DrawInstanced(3, 1, 0, 0);
|
command_list.DrawInstanced(3, 1, 0, 0);
|
||||||
|
@ -536,14 +544,13 @@ pub mod d3d12_hello_triangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_device(command_line: &SampleCommandLine) -> Result<(IDXGIFactory4, ID3D12Device)> {
|
fn create_device(command_line: &SampleCommandLine) -> Result<(IDXGIFactory4, ID3D12Device)> {
|
||||||
// unsafe {
|
unsafe {
|
||||||
// let mut debug: Option<ID3D12Debug> = None;
|
let mut debug: Option<ID3D12Debug> = None;
|
||||||
// if let Some(debug) = D3D12GetDebugInterface(&mut debug).ok().and(debug) {
|
if let Some(debug) = D3D12GetDebugInterface(&mut debug).ok().and(debug) {
|
||||||
// eprintln!("enabling debug");
|
eprintln!("enabling debug");
|
||||||
// debug.EnableDebugLayer();
|
debug.EnableDebugLayer();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
|
||||||
let dxgi_factory_flags = DXGI_CREATE_FACTORY_DEBUG;
|
let dxgi_factory_flags = DXGI_CREATE_FACTORY_DEBUG;
|
||||||
|
|
||||||
|
@ -571,7 +578,7 @@ pub mod d3d12_hello_triangle {
|
||||||
let signature = unsafe {
|
let signature = unsafe {
|
||||||
D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &mut signature, None)
|
D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &mut signature, None)
|
||||||
}
|
}
|
||||||
.map(|()| signature.unwrap())?;
|
.map(|()| signature.unwrap())?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
device.CreateRootSignature(
|
device.CreateRootSignature(
|
||||||
|
@ -609,7 +616,7 @@ pub mod d3d12_hello_triangle {
|
||||||
device: &ID3D12Device,
|
device: &ID3D12Device,
|
||||||
root_signature: &ID3D12RootSignature,
|
root_signature: &ID3D12RootSignature,
|
||||||
) -> Result<ID3D12PipelineState> {
|
) -> Result<ID3D12PipelineState> {
|
||||||
let compile_flags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
let compile_flags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||||
|
|
||||||
let vertex_shader = compile_shader(SHADER, b"VSMain\0", b"vs_5_0\0")?;
|
let vertex_shader = compile_shader(SHADER, b"VSMain\0", b"vs_5_0\0")?;
|
||||||
let pixel_shader = compile_shader(SHADER, b"PSMain\0", b"ps_5_0\0")?;
|
let pixel_shader = compile_shader(SHADER, b"PSMain\0", b"ps_5_0\0")?;
|
||||||
|
@ -791,8 +798,8 @@ pub mod d3d12_hello_triangle {
|
||||||
.fence
|
.fence
|
||||||
.SetEventOnCompletion(fence, resources.fence_event)
|
.SetEventOnCompletion(fence, resources.fence_event)
|
||||||
}
|
}
|
||||||
.ok()
|
.ok()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
unsafe { WaitForSingleObject(resources.fence_event, INFINITE) };
|
unsafe { WaitForSingleObject(resources.fence_event, INFINITE) };
|
||||||
}
|
}
|
||||||
|
@ -801,7 +808,6 @@ pub mod d3d12_hello_triangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn main<S: DXSample>(sample: S) -> Result<()> {
|
pub fn main<S: DXSample>(sample: S) -> Result<()> {
|
||||||
run_sample(sample)?;
|
run_sample(sample)?;
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use windows::Win32::Graphics::Direct3D12::{D3D12_COMPARISON_FUNC_NEVER, D3D12_FLOAT32_MAX, D3D12_SAMPLER_DESC, D3D12_TEXTURE_ADDRESS_MODE, ID3D12Device};
|
|
||||||
use librashader_common::{FilterMode, WrapMode};
|
|
||||||
use crate::heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot, SamplerHeap};
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
|
use crate::heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot, SamplerPaletteHeap};
|
||||||
|
use librashader_common::{FilterMode, WrapMode};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
use windows::Win32::Graphics::Direct3D12::{
|
||||||
|
ID3D12Device, D3D12_COMPARISON_FUNC_NEVER, D3D12_FLOAT32_MAX, D3D12_SAMPLER_DESC,
|
||||||
|
D3D12_TEXTURE_ADDRESS_MODE,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct SamplerSet {
|
pub struct SamplerSet {
|
||||||
samplers: FxHashMap<(WrapMode, FilterMode), D3D12DescriptorHeapSlot<SamplerHeap>>,
|
samplers: FxHashMap<(WrapMode, FilterMode), D3D12DescriptorHeapSlot<SamplerPaletteHeap>>,
|
||||||
heap: D3D12DescriptorHeap<SamplerHeap>
|
heap: D3D12DescriptorHeap<SamplerPaletteHeap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SamplerSet {
|
impl SamplerSet {
|
||||||
pub fn get(&self, wrap: WrapMode, filter: FilterMode) -> &D3D12DescriptorHeapSlot<SamplerHeap> {
|
pub fn get(
|
||||||
|
&self,
|
||||||
|
wrap: WrapMode,
|
||||||
|
filter: FilterMode,
|
||||||
|
) -> &D3D12DescriptorHeapSlot<SamplerPaletteHeap> {
|
||||||
self.samplers.get(&(wrap, filter)).unwrap()
|
self.samplers.get(&(wrap, filter)).unwrap()
|
||||||
}
|
}
|
||||||
pub fn new(device: &ID3D12Device) -> error::Result<SamplerSet> {
|
pub fn new(device: &ID3D12Device) -> error::Result<SamplerSet> {
|
||||||
|
|
||||||
let mut samplers = FxHashMap::default();
|
let mut samplers = FxHashMap::default();
|
||||||
let wrap_modes = &[
|
let wrap_modes = &[
|
||||||
WrapMode::ClampToBorder,
|
WrapMode::ClampToBorder,
|
||||||
|
@ -23,7 +29,7 @@ impl SamplerSet {
|
||||||
WrapMode::MirroredRepeat,
|
WrapMode::MirroredRepeat,
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut heap = D3D12DescriptorHeap::new(&device, (2 * wrap_modes.len()))?;
|
let mut heap = D3D12DescriptorHeap::new(&device, 2 * wrap_modes.len())?;
|
||||||
|
|
||||||
for wrap_mode in wrap_modes {
|
for wrap_mode in wrap_modes {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -58,7 +64,7 @@ impl SamplerSet {
|
||||||
MinLOD: -D3D12_FLOAT32_MAX,
|
MinLOD: -D3D12_FLOAT32_MAX,
|
||||||
MaxLOD: D3D12_FLOAT32_MAX,
|
MaxLOD: D3D12_FLOAT32_MAX,
|
||||||
},
|
},
|
||||||
*nearest.as_ref()
|
*nearest.as_ref(),
|
||||||
);
|
);
|
||||||
|
|
||||||
samplers.insert((*wrap_mode, FilterMode::Linear), linear);
|
samplers.insert((*wrap_mode, FilterMode::Linear), linear);
|
||||||
|
|
|
@ -1,20 +1,165 @@
|
||||||
use windows::Win32::Graphics::Direct3D12::{D3D12_RESOURCE_DESC, ID3D12Device, ID3D12Resource};
|
use crate::error;
|
||||||
use librashader_common::{FilterMode, WrapMode};
|
use crate::error::assume_d3d12_init;
|
||||||
|
use crate::heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot, LutTextureHeap};
|
||||||
|
use crate::util::d3d12_get_closest_format;
|
||||||
|
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||||
use librashader_runtime::image::Image;
|
use librashader_runtime::image::Image;
|
||||||
|
use windows::Win32::Graphics::Direct3D12::{ID3D12CommandList, ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES, D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_UPLOAD, D3D12_MEMORY_POOL_UNKNOWN, D3D12_PLACED_SUBRESOURCE_FOOTPRINT, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_SHADER_RESOURCE_VIEW_DESC, D3D12_SHADER_RESOURCE_VIEW_DESC_0, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_SRV, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, D3D12_RANGE};
|
||||||
|
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
|
||||||
|
|
||||||
pub struct LutTexture {
|
pub struct LutTexture {
|
||||||
handle: ID3D12Resource,
|
resource: ID3D12Resource,
|
||||||
|
descriptor: D3D12DescriptorHeapSlot<LutTextureHeap>,
|
||||||
|
size: Size<u32>,
|
||||||
|
filter: FilterMode,
|
||||||
|
wrap_mode: WrapMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LutTexture {
|
impl LutTexture {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &ID3D12Device,
|
device: &ID3D12Device,
|
||||||
|
heap: &mut D3D12DescriptorHeap<LutTextureHeap>,
|
||||||
|
cmd: &ID3D12GraphicsCommandList,
|
||||||
source: &Image,
|
source: &Image,
|
||||||
desc: D3D12_RESOURCE_DESC,
|
|
||||||
filter: FilterMode,
|
filter: FilterMode,
|
||||||
wrap_mode: WrapMode,
|
wrap_mode: WrapMode,
|
||||||
) {
|
mipmap: bool,
|
||||||
|
) -> error::Result<LutTexture> {
|
||||||
// todo: d3d12:800
|
// todo: d3d12:800
|
||||||
|
let mut desc = D3D12_RESOURCE_DESC {
|
||||||
|
Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||||
|
Alignment: 0,
|
||||||
|
Width: source.size.width as u64,
|
||||||
|
Height: source.size.height,
|
||||||
|
DepthOrArraySize: 1,
|
||||||
|
MipLevels: 1, // todo: mipmaps
|
||||||
|
// MipLevels: if mipmap { u16::MAX } else { 1 },
|
||||||
|
Format: ImageFormat::R8G8B8A8Unorm.into(),
|
||||||
|
SampleDesc: DXGI_SAMPLE_DESC {
|
||||||
|
Count: 1,
|
||||||
|
Quality: 0,
|
||||||
|
},
|
||||||
|
Layout: Default::default(),
|
||||||
|
Flags: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let format_support = D3D12_FEATURE_DATA_FORMAT_SUPPORT {
|
||||||
|
Format: desc.Format,
|
||||||
|
Support1: D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
desc.Format = d3d12_get_closest_format(device, desc.Format, format_support);
|
||||||
|
let descriptor = heap.alloc_slot()?;
|
||||||
|
|
||||||
|
// create handles on GPU
|
||||||
|
let mut resource: Option<ID3D12Resource> = None;
|
||||||
|
unsafe {
|
||||||
|
device.CreateCommittedResource(
|
||||||
|
&D3D12_HEAP_PROPERTIES {
|
||||||
|
Type: D3D12_HEAP_TYPE_DEFAULT,
|
||||||
|
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
|
||||||
|
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
|
||||||
|
CreationNodeMask: 1,
|
||||||
|
VisibleNodeMask: 1,
|
||||||
|
},
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&desc,
|
||||||
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
|
None,
|
||||||
|
&mut resource,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
assume_d3d12_init!(resource, "CreateCommittedResource");
|
||||||
|
unsafe {
|
||||||
|
let srv_desc = D3D12_SHADER_RESOURCE_VIEW_DESC {
|
||||||
|
Format: desc.Format,
|
||||||
|
ViewDimension: D3D12_SRV_DIMENSION_TEXTURE2D,
|
||||||
|
Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
||||||
|
Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
|
||||||
|
Texture2D: D3D12_TEX2D_SRV {
|
||||||
|
MipLevels: desc.MipLevels as u32,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
device.CreateShaderResourceView(&resource, Some(&srv_desc), *descriptor.as_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buffer_desc = D3D12_RESOURCE_DESC {
|
||||||
|
Dimension: D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut layout = D3D12_PLACED_SUBRESOURCE_FOOTPRINT::default();
|
||||||
|
let mut numrows = 0;
|
||||||
|
let mut rowsize = 0;
|
||||||
|
let mut total = 0;
|
||||||
|
// texture upload
|
||||||
|
unsafe {
|
||||||
|
device.GetCopyableFootprints(
|
||||||
|
&desc,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
Some(&mut layout),
|
||||||
|
Some(&mut numrows),
|
||||||
|
Some(&mut rowsize),
|
||||||
|
Some(&mut total),
|
||||||
|
);
|
||||||
|
|
||||||
|
buffer_desc.Width = total;
|
||||||
|
buffer_desc.Height = 1;
|
||||||
|
buffer_desc.DepthOrArraySize = 1;
|
||||||
|
buffer_desc.MipLevels = 1;
|
||||||
|
buffer_desc.SampleDesc.Count = 1;
|
||||||
|
buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||||
|
}
|
||||||
|
let mut upload: Option<ID3D12Resource> = None;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device.CreateCommittedResource(
|
||||||
|
&D3D12_HEAP_PROPERTIES {
|
||||||
|
Type: D3D12_HEAP_TYPE_UPLOAD,
|
||||||
|
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
|
||||||
|
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
|
||||||
|
CreationNodeMask: 1,
|
||||||
|
VisibleNodeMask: 1,
|
||||||
|
},
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&buffer_desc,
|
||||||
|
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||||
|
None,
|
||||||
|
&mut upload,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
assume_d3d12_init!(upload, "CreateCommittedResource");
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut range = D3D12_RANGE {
|
||||||
|
Begin: 0,
|
||||||
|
End: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buf = std::ptr::null_mut();
|
||||||
|
|
||||||
|
upload.Map(0, Some(&range), Some(&mut buf))?;
|
||||||
|
|
||||||
|
upload.Unmap(0, None);
|
||||||
|
|
||||||
|
}
|
||||||
|
// todo: upload image data to textur
|
||||||
|
|
||||||
|
Ok(LutTexture {
|
||||||
|
resource,
|
||||||
|
descriptor,
|
||||||
|
size: source.size,
|
||||||
|
filter,
|
||||||
|
wrap_mode,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// todo https://github.com/microsoft/DirectX-Graphics-Samples/blob/master/Libraries/D3D12RaytracingFallback/Include/d3dx12.h#L1893
|
142
librashader-runtime-d3d12/src/util.rs
Normal file
142
librashader-runtime-d3d12/src/util.rs
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
use crate::error;
|
||||||
|
use windows::core::PCSTR;
|
||||||
|
use windows::Win32::Graphics::Direct3D::Fxc::{
|
||||||
|
D3DCompile, D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION,
|
||||||
|
};
|
||||||
|
use windows::Win32::Graphics::Direct3D::ID3DBlob;
|
||||||
|
use windows::Win32::Graphics::Direct3D12::{
|
||||||
|
ID3D12Device, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FEATURE_FORMAT_SUPPORT,
|
||||||
|
};
|
||||||
|
use windows::Win32::Graphics::Dxgi::Common::*;
|
||||||
|
|
||||||
|
/// wtf retroarch?
|
||||||
|
const DXGI_FORMAT_EX_A4R4G4B4_UNORM: DXGI_FORMAT = DXGI_FORMAT(1000);
|
||||||
|
|
||||||
|
const fn d3d12_format_fallback_list(format: DXGI_FORMAT) -> Option<&'static [DXGI_FORMAT]> {
|
||||||
|
match format {
|
||||||
|
DXGI_FORMAT_R32G32B32A32_FLOAT => Some(&[
|
||||||
|
DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||||
|
DXGI_FORMAT_R32G32B32_FLOAT,
|
||||||
|
DXGI_FORMAT_R11G11B10_FLOAT,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_R16G16B16A16_FLOAT => Some(&[
|
||||||
|
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||||
|
DXGI_FORMAT_R32G32B32_FLOAT,
|
||||||
|
DXGI_FORMAT_R11G11B10_FLOAT,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM => Some(&[
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB => Some(&[
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM => Some(&[
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM => Some(&[
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_B5G6R5_UNORM => Some(&[
|
||||||
|
DXGI_FORMAT_B5G6R5_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_EX_A4R4G4B4_UNORM | DXGI_FORMAT_B4G4R4A4_UNORM => Some(&[
|
||||||
|
DXGI_FORMAT_B4G4R4A4_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_A8_UNORM => Some(&[
|
||||||
|
DXGI_FORMAT_A8_UNORM,
|
||||||
|
DXGI_FORMAT_R8_UNORM,
|
||||||
|
DXGI_FORMAT_R8G8_UNORM,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
DXGI_FORMAT_R8_UNORM => Some(&[
|
||||||
|
DXGI_FORMAT_R8_UNORM,
|
||||||
|
DXGI_FORMAT_A8_UNORM,
|
||||||
|
DXGI_FORMAT_R8G8_UNORM,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
DXGI_FORMAT_UNKNOWN,
|
||||||
|
]),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn d3d12_get_closest_format(
|
||||||
|
device: &ID3D12Device,
|
||||||
|
format: DXGI_FORMAT,
|
||||||
|
format_support: D3D12_FEATURE_DATA_FORMAT_SUPPORT,
|
||||||
|
) -> DXGI_FORMAT {
|
||||||
|
let default_list = [format, DXGI_FORMAT_UNKNOWN];
|
||||||
|
let format_support_list = d3d12_format_fallback_list(format).unwrap_or(&default_list);
|
||||||
|
|
||||||
|
for supported in format_support_list {
|
||||||
|
unsafe {
|
||||||
|
let mut support = D3D12_FEATURE_DATA_FORMAT_SUPPORT {
|
||||||
|
Format: format,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
if device
|
||||||
|
.CheckFeatureSupport(
|
||||||
|
D3D12_FEATURE_FORMAT_SUPPORT,
|
||||||
|
&mut support as *mut _ as *mut _,
|
||||||
|
std::mem::size_of::<D3D12_FEATURE_DATA_FORMAT_SUPPORT>() as u32,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
&& (support.Support1 & format_support.Support1) == format_support.Support1
|
||||||
|
&& (support.Support2 & format_support.Support2) == format_support.Support2
|
||||||
|
{
|
||||||
|
return *supported;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DXGI_FORMAT_UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn d3d_compile_shader(source: &[u8], entry: &[u8], version: &[u8]) -> error::Result<ID3DBlob> {
|
||||||
|
unsafe {
|
||||||
|
let mut blob = None;
|
||||||
|
D3DCompile(
|
||||||
|
source.as_ptr().cast(),
|
||||||
|
source.len(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
PCSTR(entry.as_ptr()),
|
||||||
|
PCSTR(version.as_ptr()),
|
||||||
|
if cfg!(feature = "debug-shader") {
|
||||||
|
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
&mut blob,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(blob.unwrap())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue