d3d12: load vertex buffers
This commit is contained in:
parent
c2bef7f985
commit
22599285d3
117
librashader-runtime-d3d12/src/buffer.rs
Normal file
117
librashader-runtime-d3d12/src/buffer.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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(),
|
||||
})
|
||||
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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] {
|
||||
[
|
||||
|
|
Loading…
Reference in a new issue