d3d12: partially implement lut texture
This commit is contained in:
parent
2f82c5f430
commit
9a3ce029d7
|
@ -1,3 +1,16 @@
|
|||
use std::error::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 std::path::Path;
|
||||
use rustc_hash::FxHashMap;
|
||||
use windows::Win32::Graphics::Direct3D12::ID3D12Device;
|
||||
use crate::error;
|
||||
use crate::heap::{D3D12DescriptorHeap, LutTextureHeap};
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::LutTexture;
|
||||
use librashader_presets::{ShaderPreset, TextureConfig};
|
||||
use librashader_reflect::back::targets::HLSL;
|
||||
use librashader_reflect::front::GlslangCompilation;
|
||||
use librashader_reflect::reflect::presets::CompilePresetTarget;
|
||||
use crate::error;
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::LutTexture;
|
||||
use librashader_runtime::image::{Image, UVDirection};
|
||||
use rustc_hash::FxHashMap;
|
||||
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(crate) common: FilterCommon,
|
||||
|
@ -28,6 +37,8 @@ pub(crate) struct FilterCommon {
|
|||
// pub history_textures: Box<[Option<InputTexture>]>,
|
||||
// pub config: FilterMutable,
|
||||
// pub disable_mipmaps: bool,
|
||||
lut_heap: D3D12DescriptorHeap<LutTextureHeap>,
|
||||
luts: FxHashMap<usize, LutTexture>,
|
||||
}
|
||||
|
||||
impl FilterChainD3D12 {
|
||||
|
@ -44,9 +55,59 @@ impl FilterChainD3D12 {
|
|||
|
||||
fn load_luts(
|
||||
device: &ID3D12Device,
|
||||
heap: &mut D3D12DescriptorHeap<LutTextureHeap>,
|
||||
textures: &[TextureConfig],
|
||||
) -> 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`.
|
||||
|
@ -55,17 +116,23 @@ impl FilterChainD3D12 {
|
|||
preset: ShaderPreset,
|
||||
options: Option<&()>,
|
||||
) -> error::Result<FilterChainD3D12> {
|
||||
let (passes, semantics) = HLSL::compile_preset_passes::<
|
||||
GlslangCompilation,
|
||||
Box<dyn Error>,
|
||||
>(preset.shaders, &preset.textures)?;
|
||||
let (passes, semantics) = HLSL::compile_preset_passes::<GlslangCompilation, Box<dyn Error>>(
|
||||
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 {
|
||||
common: FilterCommon {
|
||||
d3d12: device.clone(),
|
||||
samplers,
|
||||
lut_heap,
|
||||
luts,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,28 @@
|
|||
use crate::error;
|
||||
use std::cell::RefCell;
|
||||
use std::marker::PhantomData;
|
||||
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 crate::error;
|
||||
use windows::Win32::Graphics::Direct3D12::{
|
||||
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]
|
||||
pub trait D3D12HeapType {
|
||||
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 {
|
||||
D3D12_DESCRIPTOR_HEAP_DESC {
|
||||
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> {
|
||||
cpu_handle: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||
gpu_handle: D3D12_GPU_DESCRIPTOR_HANDLE,
|
||||
gpu_handle: Option<D3D12_GPU_DESCRIPTOR_HANDLE>,
|
||||
heap: Arc<RefCell<D3D12DescriptorHeapInner>>,
|
||||
slot: usize,
|
||||
_pd: PhantomData<T>
|
||||
_pd: PhantomData<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 {
|
||||
&self.gpu_handle
|
||||
self.gpu_handle.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +78,7 @@ struct D3D12DescriptorHeapInner {
|
|||
heap: ID3D12DescriptorHeap,
|
||||
desc: D3D12_DESCRIPTOR_HEAP_DESC,
|
||||
cpu_start: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||
gpu_start: D3D12_GPU_DESCRIPTOR_HANDLE,
|
||||
gpu_start: Option<D3D12_GPU_DESCRIPTOR_HANDLE>,
|
||||
handle_size: usize,
|
||||
start: usize,
|
||||
// Bit flag representation of available handles in the heap.
|
||||
|
@ -65,30 +90,40 @@ struct D3D12DescriptorHeapInner {
|
|||
|
||||
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>> {
|
||||
let desc = T::get_desc(size);
|
||||
unsafe {
|
||||
D3D12DescriptorHeap::new_with_desc(device, desc)
|
||||
}
|
||||
unsafe { D3D12DescriptorHeap::new_with_desc(device, desc) }
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
let heap: ID3D12DescriptorHeap = device.CreateDescriptorHeap(&desc)?;
|
||||
let cpu_start = heap.GetCPUDescriptorHandleForHeapStart();
|
||||
let gpu_start = heap.GetGPUDescriptorHandleForHeapStart();
|
||||
Ok(D3D12DescriptorHeap(Arc::new(RefCell::new(D3D12DescriptorHeapInner {
|
||||
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()))
|
||||
|
||||
let gpu_start = if (desc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE).0 != 0 {
|
||||
Some(heap.GetGPUDescriptorHandleForHeapStart())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(D3D12DescriptorHeap(
|
||||
Arc::new(RefCell::new(D3D12DescriptorHeapInner {
|
||||
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);
|
||||
inner.start = i + 1;
|
||||
|
||||
let gpu_handle = D3D12_GPU_DESCRIPTOR_HANDLE {
|
||||
ptr: (handle.ptr as u64 - inner.cpu_start.ptr as u64 + inner.gpu_start.ptr),
|
||||
};
|
||||
let gpu_handle = inner
|
||||
.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 {
|
||||
cpu_handle: handle,
|
||||
slot: i,
|
||||
|
|
|
@ -32,8 +32,8 @@ use std::path::Path;
|
|||
|
||||
pub trait DXSample {
|
||||
fn new(filter: impl AsRef<Path>, command_line: &SampleCommandLine) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
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<()>
|
||||
where
|
||||
S: DXSample,
|
||||
where
|
||||
S: DXSample,
|
||||
{
|
||||
let instance = unsafe { GetModuleHandleA(None)? };
|
||||
|
||||
|
@ -214,7 +214,7 @@ fn get_hardware_adapter(factory: &IDXGIFactory4) -> Result<IDXGIAdapter1> {
|
|||
std::ptr::null_mut::<Option<ID3D12Device>>(),
|
||||
)
|
||||
}
|
||||
.is_ok()
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(adapter);
|
||||
}
|
||||
|
@ -223,18 +223,23 @@ fn get_hardware_adapter(factory: &IDXGIFactory4) -> Result<IDXGIAdapter1> {
|
|||
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 {
|
||||
let desc = CStr::from_ptr(pdescription.as_ptr().cast());
|
||||
eprintln!("[{severity:?}-{category:?}] {desc:?}")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub mod d3d12_hello_triangle {
|
||||
use std::path::Path;
|
||||
use crate::filter_chain::FilterChainD3D12;
|
||||
use super::*;
|
||||
use crate::filter_chain::FilterChainD3D12;
|
||||
use std::path::Path;
|
||||
|
||||
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> {
|
||||
let (dxgi_factory, device) = create_device(command_line)?;
|
||||
//
|
||||
// let queue = device.cast::<ID3D12InfoQueue1>()?;
|
||||
// unsafe {
|
||||
// queue.RegisterMessageCallback(Some(debug_log), D3D12_MESSAGE_CALLBACK_FLAG_NONE, std::ptr::null_mut(), &mut 0).expect("could not register message callback");
|
||||
// }
|
||||
let queue = device.cast::<ID3D12InfoQueue1>()?;
|
||||
unsafe {
|
||||
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();
|
||||
|
||||
Ok(Sample {
|
||||
|
@ -321,7 +333,7 @@ pub mod d3d12_hello_triangle {
|
|||
None,
|
||||
)?
|
||||
}
|
||||
.cast()?;
|
||||
.cast()?;
|
||||
|
||||
// This sample does not support fullscreen transitions
|
||||
unsafe {
|
||||
|
@ -496,11 +508,7 @@ pub mod d3d12_hello_triangle {
|
|||
// Record commands.
|
||||
unsafe {
|
||||
// TODO: workaround for https://github.com/microsoft/win32metadata/issues/1006
|
||||
command_list.ClearRenderTargetView(
|
||||
rtv_handle,
|
||||
&*[0.3, 0.4, 0.6, 1.0].as_ptr(),
|
||||
&[],
|
||||
);
|
||||
command_list.ClearRenderTargetView(rtv_handle, &*[0.3, 0.4, 0.6, 1.0].as_ptr(), &[]);
|
||||
command_list.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
command_list.IASetVertexBuffers(0, Some(&[resources.vbv]));
|
||||
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)> {
|
||||
// unsafe {
|
||||
// let mut debug: Option<ID3D12Debug> = None;
|
||||
// if let Some(debug) = D3D12GetDebugInterface(&mut debug).ok().and(debug) {
|
||||
// eprintln!("enabling debug");
|
||||
// debug.EnableDebugLayer();
|
||||
// }
|
||||
// }
|
||||
|
||||
unsafe {
|
||||
let mut debug: Option<ID3D12Debug> = None;
|
||||
if let Some(debug) = D3D12GetDebugInterface(&mut debug).ok().and(debug) {
|
||||
eprintln!("enabling debug");
|
||||
debug.EnableDebugLayer();
|
||||
}
|
||||
}
|
||||
|
||||
let dxgi_factory_flags = DXGI_CREATE_FACTORY_DEBUG;
|
||||
|
||||
|
@ -571,7 +578,7 @@ pub mod d3d12_hello_triangle {
|
|||
let signature = unsafe {
|
||||
D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &mut signature, None)
|
||||
}
|
||||
.map(|()| signature.unwrap())?;
|
||||
.map(|()| signature.unwrap())?;
|
||||
|
||||
unsafe {
|
||||
device.CreateRootSignature(
|
||||
|
@ -609,7 +616,7 @@ pub mod d3d12_hello_triangle {
|
|||
device: &ID3D12Device,
|
||||
root_signature: &ID3D12RootSignature,
|
||||
) -> 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 pixel_shader = compile_shader(SHADER, b"PSMain\0", b"ps_5_0\0")?;
|
||||
|
@ -791,8 +798,8 @@ pub mod d3d12_hello_triangle {
|
|||
.fence
|
||||
.SetEventOnCompletion(fence, resources.fence_event)
|
||||
}
|
||||
.ok()
|
||||
.unwrap();
|
||||
.ok()
|
||||
.unwrap();
|
||||
|
||||
unsafe { WaitForSingleObject(resources.fence_event, INFINITE) };
|
||||
}
|
||||
|
@ -801,7 +808,6 @@ pub mod d3d12_hello_triangle {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn main<S: DXSample>(sample: S) -> Result<()> {
|
||||
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::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 {
|
||||
samplers: FxHashMap<(WrapMode, FilterMode), D3D12DescriptorHeapSlot<SamplerHeap>>,
|
||||
heap: D3D12DescriptorHeap<SamplerHeap>
|
||||
samplers: FxHashMap<(WrapMode, FilterMode), D3D12DescriptorHeapSlot<SamplerPaletteHeap>>,
|
||||
heap: D3D12DescriptorHeap<SamplerPaletteHeap>,
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
pub fn new(device: &ID3D12Device) -> error::Result<SamplerSet> {
|
||||
|
||||
let mut samplers = FxHashMap::default();
|
||||
let wrap_modes = &[
|
||||
WrapMode::ClampToBorder,
|
||||
|
@ -23,7 +29,7 @@ impl SamplerSet {
|
|||
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 {
|
||||
unsafe {
|
||||
|
@ -58,7 +64,7 @@ impl SamplerSet {
|
|||
MinLOD: -D3D12_FLOAT32_MAX,
|
||||
MaxLOD: D3D12_FLOAT32_MAX,
|
||||
},
|
||||
*nearest.as_ref()
|
||||
*nearest.as_ref(),
|
||||
);
|
||||
|
||||
samplers.insert((*wrap_mode, FilterMode::Linear), linear);
|
||||
|
|
|
@ -1,20 +1,165 @@
|
|||
use windows::Win32::Graphics::Direct3D12::{D3D12_RESOURCE_DESC, ID3D12Device, ID3D12Resource};
|
||||
use librashader_common::{FilterMode, WrapMode};
|
||||
use crate::error;
|
||||
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 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 {
|
||||
handle: ID3D12Resource,
|
||||
|
||||
resource: ID3D12Resource,
|
||||
descriptor: D3D12DescriptorHeapSlot<LutTextureHeap>,
|
||||
size: Size<u32>,
|
||||
filter: FilterMode,
|
||||
wrap_mode: WrapMode,
|
||||
}
|
||||
|
||||
impl LutTexture {
|
||||
pub fn new(
|
||||
device: &ID3D12Device,
|
||||
heap: &mut D3D12DescriptorHeap<LutTextureHeap>,
|
||||
cmd: &ID3D12GraphicsCommandList,
|
||||
source: &Image,
|
||||
desc: D3D12_RESOURCE_DESC,
|
||||
filter: FilterMode,
|
||||
wrap_mode: WrapMode,
|
||||
) {
|
||||
mipmap: bool,
|
||||
) -> error::Result<LutTexture> {
|
||||
// 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