From 22599285d3805542534344a0c08110b4d2ececc1 Mon Sep 17 00:00:00 2001 From: chyyran Date: Mon, 30 Jan 2023 23:30:11 -0500 Subject: [PATCH] d3d12: load vertex buffers --- librashader-runtime-d3d12/src/buffer.rs | 117 ++++++++++++++++++ librashader-runtime-d3d12/src/filter_chain.rs | 60 ++++++++- librashader-runtime-d3d12/src/filter_pass.rs | 14 ++- librashader-runtime-d3d12/src/lib.rs | 3 +- .../src/{texture.rs => luts.rs} | 0 librashader-runtime-d3d12/src/quad_render.rs | 94 ++++++-------- 6 files changed, 228 insertions(+), 60 deletions(-) create mode 100644 librashader-runtime-d3d12/src/buffer.rs rename librashader-runtime-d3d12/src/{texture.rs => luts.rs} (100%) diff --git a/librashader-runtime-d3d12/src/buffer.rs b/librashader-runtime-d3d12/src/buffer.rs new file mode 100644 index 0000000..a6c5a54 --- /dev/null +++ b/librashader-runtime-d3d12/src/buffer.rs @@ -0,0 +1,117 @@ +use std::ops::Range; +use windows::Win32::Graphics::Direct3D12::{D3D12_CONSTANT_BUFFER_VIEW_DESC, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES, D3D12_HEAP_TYPE_UPLOAD, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RANGE, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION, D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, ID3D12Device, ID3D12Resource}; +use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC; +use crate::error; +use crate::error::assume_d3d12_init; + +pub struct D3D12ConstantBuffer { + buffer: D3D12Buffer, + desc: D3D12_CONSTANT_BUFFER_VIEW_DESC, +} + +pub struct D3D12Buffer { + handle: ID3D12Resource, + size: usize +} + +pub struct D3D12BufferMapHandle<'a> { + pub slice: &'a mut [u8], + pub handle: &'a ID3D12Resource, +} + +impl<'a> Drop for D3D12BufferMapHandle<'a> { + fn drop(&mut self) { + unsafe { + self.handle.Unmap(0, None) + } + } +} + +impl D3D12Buffer { + pub fn new(device: &ID3D12Device, size: usize) -> error::Result { + unsafe { + let mut buffer: Option = None; + device.CreateCommittedResource( + &D3D12_HEAP_PROPERTIES { + Type: D3D12_HEAP_TYPE_UPLOAD, + CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN, + MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN, + ..Default::default() + }, + D3D12_HEAP_FLAG_NONE, + &D3D12_RESOURCE_DESC { + Dimension: D3D12_RESOURCE_DIMENSION_BUFFER, + Width: size as u64, + Height: 1, + DepthOrArraySize: 1, + MipLevels: 1, + Layout: D3D12_TEXTURE_LAYOUT_ROW_MAJOR, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0 + }, + ..Default::default() + }, + D3D12_RESOURCE_STATE_GENERIC_READ, + None, + &mut buffer + )?; + + assume_d3d12_init!(buffer, "CreateCommittedResource"); + + Ok(D3D12Buffer { + handle: buffer, + size + }) + } + } + + pub fn gpu_address(&self) -> u64 { + unsafe { + self.handle.GetGPUVirtualAddress() + } + } + + pub fn into_raw(self) -> ID3D12Resource { + self.handle + } + + pub fn map(&mut self, range: Option>) -> error::Result { + let (range, size) = range.map(|range| { + (D3D12_RANGE { + Begin: range.start, + End: range.end + }, range.end - range.start) + }).unwrap_or((D3D12_RANGE { + Begin: 0, + End: 0 + }, self.size)); + + unsafe { + let mut ptr = std::ptr::null_mut(); + self.handle.Map(0, Some(&range), Some(&mut ptr))?; + let slice = std::slice::from_raw_parts_mut(ptr.cast(), size); + Ok(D3D12BufferMapHandle { + handle: &self.handle, + slice, + }) + } + } +} + + +impl D3D12ConstantBuffer { + pub fn new(buffer: D3D12Buffer) -> D3D12ConstantBuffer { + unsafe { + let desc = D3D12_CONSTANT_BUFFER_VIEW_DESC { + BufferLocation: buffer.handle.GetGPUVirtualAddress(), + SizeInBytes: buffer.size as u32, + }; + + D3D12ConstantBuffer { + buffer, + desc, + } + } + } +} \ No newline at end of file diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index 5f7ccca..5d23508 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use crate::{error, util}; use crate::heap::{D3D12DescriptorHeap, LutTextureHeap, ResourceWorkHeap}; use crate::samplers::SamplerSet; -use crate::texture::LutTexture; +use crate::luts::LutTexture; use librashader_presets::{ShaderPreset, TextureConfig}; use librashader_reflect::back::targets::HLSL; use librashader_reflect::front::GlslangCompilation; @@ -24,7 +24,9 @@ use windows::Win32::System::WindowsProgramming::INFINITE; use librashader_common::ImageFormat; use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::reflect::ReflectShader; -use librashader_reflect::reflect::semantics::ShaderSemantics; +use librashader_reflect::reflect::semantics::{MAX_BINDINGS_COUNT, ShaderSemantics, UniformBinding}; +use librashader_runtime::uniforms::UniformStorage; +use crate::buffer::{D3D12Buffer, D3D12ConstantBuffer}; use crate::filter_pass::FilterPass; use crate::graphics_pipeline::{D3D12GraphicsPipeline, D3D12RootSignature}; use crate::mipmap::D3D12MipmapGen; @@ -55,6 +57,8 @@ pub(crate) struct FilterCommon { luts: FxHashMap, mipmap_gen: D3D12MipmapGen, root_signature: D3D12RootSignature, + work_heap: D3D12DescriptorHeap, + draw_quad: DrawQuad, } impl FilterChainD3D12 { @@ -84,6 +88,7 @@ impl FilterChainD3D12 { let samplers = SamplerSet::new(device)?; let mipmap_gen = D3D12MipmapGen::new(device).unwrap(); + let draw_quad = DrawQuad::new(device)?; let mut lut_heap = D3D12DescriptorHeap::new(device, preset.textures.len())?; let luts = FilterChainD3D12::load_luts(device, &mut lut_heap, &preset.textures, &mipmap_gen).unwrap(); @@ -91,6 +96,9 @@ impl FilterChainD3D12 { let filters = FilterChainD3D12::init_passes(device, &root_signature, passes, &semantics)?; + let work_heap = + D3D12DescriptorHeap::::new(device, (MAX_BINDINGS_COUNT as usize) * 64 + 2048)?; + Ok(FilterChainD3D12 { common: FilterCommon { d3d12: device.clone(), @@ -99,6 +107,8 @@ impl FilterChainD3D12 { luts, mipmap_gen, root_signature, + work_heap, + draw_quad, }, filters }) @@ -216,8 +226,54 @@ impl FilterChainD3D12 { }.into() )?; + let uniform_storage = UniformStorage::new( + reflection + .ubo + .as_ref() + .map(|ubo| ubo.size as usize) + .unwrap_or(0), + reflection + .push_constant + .as_ref() + .map(|push| push.size as usize) + .unwrap_or(0), + ); + + let ubo_cbuffer = if let Some(ubo) = &reflection.ubo && ubo.size != 0 { + let buffer = D3D12ConstantBuffer::new(D3D12Buffer::new(device, ubo.size as usize)?); + Some(buffer) + } else { + None + }; + + let push_cbuffer = if let Some(push) = &reflection.push_constant && push.size != 0 { + let buffer = D3D12ConstantBuffer::new(D3D12Buffer::new(device, push.size as usize)?); + Some(buffer) + } else { + None + }; + + let mut uniform_bindings = FxHashMap::default(); + for param in reflection.meta.parameter_meta.values() { + uniform_bindings.insert(UniformBinding::Parameter(param.id.clone()), param.offset); + } + + for (semantics, param) in &reflection.meta.unique_meta { + uniform_bindings.insert(UniformBinding::SemanticVariable(*semantics), param.offset); + } + + for (semantics, param) in &reflection.meta.texture_size_meta { + uniform_bindings.insert(UniformBinding::TextureSize(*semantics), param.offset); + } + filters.push(FilterPass { + reflection, + uniform_bindings, + uniform_storage, + push_cbuffer, + ubo_cbuffer, pipeline: graphics_pipeline, + config: config.clone(), }) } diff --git a/librashader-runtime-d3d12/src/filter_pass.rs b/librashader-runtime-d3d12/src/filter_pass.rs index 9bb2108..14a5a07 100644 --- a/librashader-runtime-d3d12/src/filter_pass.rs +++ b/librashader-runtime-d3d12/src/filter_pass.rs @@ -1,5 +1,17 @@ +use rustc_hash::FxHashMap; +use librashader_presets::ShaderPassConfig; +use librashader_reflect::reflect::semantics::{MemberOffset, UniformBinding}; +use librashader_reflect::reflect::ShaderReflection; +use librashader_runtime::uniforms::UniformStorage; +use crate::buffer::D3D12ConstantBuffer; use crate::graphics_pipeline::D3D12GraphicsPipeline; pub(crate) struct FilterPass { - pub(crate) pipeline: D3D12GraphicsPipeline + pub(crate) pipeline: D3D12GraphicsPipeline, + pub(crate) reflection: ShaderReflection, + pub(crate) config: ShaderPassConfig, + pub(crate) uniform_bindings: FxHashMap, + pub uniform_storage: UniformStorage, + pub(crate) push_cbuffer: Option, + pub(crate) ubo_cbuffer: Option, } \ No newline at end of file diff --git a/librashader-runtime-d3d12/src/lib.rs b/librashader-runtime-d3d12/src/lib.rs index af26003..bfee59f 100644 --- a/librashader-runtime-d3d12/src/lib.rs +++ b/librashader-runtime-d3d12/src/lib.rs @@ -6,12 +6,13 @@ mod filter_chain; mod heap; mod hello_triangle; mod samplers; -mod texture; +mod luts; mod util; mod mipmap; mod filter_pass; mod quad_render; mod graphics_pipeline; +mod buffer; #[cfg(test)] mod tests { diff --git a/librashader-runtime-d3d12/src/texture.rs b/librashader-runtime-d3d12/src/luts.rs similarity index 100% rename from librashader-runtime-d3d12/src/texture.rs rename to librashader-runtime-d3d12/src/luts.rs diff --git a/librashader-runtime-d3d12/src/quad_render.rs b/librashader-runtime-d3d12/src/quad_render.rs index 715fc46..970b5ee 100644 --- a/librashader-runtime-d3d12/src/quad_render.rs +++ b/librashader-runtime-d3d12/src/quad_render.rs @@ -1,17 +1,14 @@ use crate::error; -use bytemuck::offset_of; +use bytemuck::{offset_of, Pod, Zeroable}; use windows::core::PCSTR; -use windows::Win32::Graphics::Direct3D::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; -use windows::Win32::Graphics::Direct3D11::{ - ID3D11Buffer, ID3D11Device, ID3D11DeviceContext, D3D11_BIND_VERTEX_BUFFER, D3D11_BUFFER_DESC, - D3D11_INPUT_ELEMENT_DESC, D3D11_INPUT_PER_VERTEX_DATA, D3D11_SUBRESOURCE_DATA, - D3D11_USAGE_IMMUTABLE, -}; -use windows::Win32::Graphics::Direct3D12::{D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, D3D12_INPUT_ELEMENT_DESC}; +use windows::w; +use windows::Win32::Graphics::Direct3D::{D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP}; +use windows::Win32::Graphics::Direct3D12::{D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, D3D12_INPUT_ELEMENT_DESC, D3D12_VERTEX_BUFFER_VIEW, ID3D12CommandList, ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource}; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R32G32_FLOAT; +use crate::buffer::{D3D12Buffer, D3D12ConstantBuffer}; #[repr(C)] -#[derive(Debug, Copy, Clone, Default)] +#[derive(Debug, Copy, Clone, Default, Zeroable, Pod)] struct D3D12Vertex { position: [f32; 2], texcoord: [f32; 2], @@ -44,56 +41,41 @@ static QUAD_VBO_DATA: &[D3D12Vertex; 4] = &[ ]; pub(crate) struct DrawQuad { - buffer: ID3D11Buffer, - context: ID3D11DeviceContext, - offset: u32, - stride: u32, + buffer: ID3D12Resource, + view: D3D12_VERTEX_BUFFER_VIEW, } impl DrawQuad { - // pub fn new(device: &ID3D11Device, context: &ID3D11DeviceContext) -> error::Result { - // unsafe { - // let mut buffer = None; - // device.CreateBuffer( - // &D3D11_BUFFER_DESC { - // ByteWidth: std::mem::size_of::<[D3D11Vertex; 4]>() as u32, - // Usage: D3D11_USAGE_IMMUTABLE, - // BindFlags: D3D11_BIND_VERTEX_BUFFER, - // CPUAccessFlags: Default::default(), - // MiscFlags: Default::default(), - // StructureByteStride: 0, - // }, - // Some(&D3D11_SUBRESOURCE_DATA { - // pSysMem: QUAD_VBO_DATA.as_ptr().cast(), - // SysMemPitch: 0, - // SysMemSlicePitch: 0, - // }), - // Some(&mut buffer), - // )?; - // assume_d3d11_init!(buffer, "CreateBuffer"); - // - // Ok(DrawQuad { - // buffer, - // context: context.clone(), - // offset: 0, - // stride: std::mem::size_of::() as u32, - // }) - // } - // } - // - // pub fn bind_vertices(&self) { - // unsafe { - // self.context - // .IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - // self.context.IASetVertexBuffers( - // 0, - // 1, - // Some(&Some(self.buffer.clone())), - // Some(&self.stride), - // Some(&self.offset), - // ); - // } - // } + pub fn new(device: &ID3D12Device) + -> error::Result { + let stride = std::mem::size_of::() as u32; + let size = std::mem::size_of::<[D3D12Vertex;4]>() as u32; + let mut buffer = D3D12Buffer::new(device, size as usize)?; + buffer.map(None)? + .slice.copy_from_slice(bytemuck::cast_slice(QUAD_VBO_DATA)); + + let view = D3D12_VERTEX_BUFFER_VIEW { + BufferLocation: buffer.gpu_address(), + SizeInBytes: size, + StrideInBytes: stride, + }; + + let buffer = buffer.into_raw(); + unsafe { + buffer.SetName(w!("drawquad"))?; + } + Ok(DrawQuad { + buffer, + view + }) + } + + pub fn bind_vertices(&self, cmd: &ID3D12GraphicsCommandList) { + unsafe { + cmd.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + cmd.IASetVertexBuffers(0, Some(&[self.view])); + } + } pub fn get_spirv_cross_vbo_desc() -> [D3D12_INPUT_ELEMENT_DESC; 2] { [