d3d12: load vertex buffers

This commit is contained in:
chyyran 2023-01-30 23:30:11 -05:00 committed by Ronny Chan
parent c2bef7f985
commit 22599285d3
6 changed files with 228 additions and 60 deletions

View file

@ -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<D3D12Buffer> {
unsafe {
let mut buffer: Option<ID3D12Resource> = 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<Range<usize>>) -> error::Result<D3D12BufferMapHandle> {
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,
}
}
}
}

View file

@ -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<usize, LutTexture>,
mipmap_gen: D3D12MipmapGen,
root_signature: D3D12RootSignature,
work_heap: D3D12DescriptorHeap<ResourceWorkHeap>,
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::<ResourceWorkHeap>::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(),
})
}

View file

@ -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<UniformBinding, MemberOffset>,
pub uniform_storage: UniformStorage,
pub(crate) push_cbuffer: Option<D3D12ConstantBuffer>,
pub(crate) ubo_cbuffer: Option<D3D12ConstantBuffer>,
}

View file

@ -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 {

View file

@ -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<DrawQuad> {
// 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::<D3D11Vertex>() 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<DrawQuad> {
let stride = std::mem::size_of::<D3D12Vertex>() 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] {
[