d3d12: filter chain pass

This commit is contained in:
chyyran 2023-02-01 00:16:06 -05:00 committed by Ronny Chan
parent e1154ac52a
commit 03b4a7574e
10 changed files with 280 additions and 48 deletions

View file

@ -5,8 +5,8 @@ use crate::error;
use crate::error::assume_d3d12_init; use crate::error::assume_d3d12_init;
pub struct D3D12ConstantBuffer { pub struct D3D12ConstantBuffer {
buffer: D3D12Buffer, pub buffer: D3D12Buffer,
desc: D3D12_CONSTANT_BUFFER_VIEW_DESC, pub desc: D3D12_CONSTANT_BUFFER_VIEW_DESC,
} }
pub struct D3D12Buffer { pub struct D3D12Buffer {

View file

@ -1,6 +1,6 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::{error}; use crate::{error};
use crate::heap::{D3D12DescriptorHeap, CpuStagingHeap, ResourceWorkHeap, SamplerWorkHeap}; use crate::heap::{D3D12DescriptorHeap, CpuStagingHeap, ResourceWorkHeap, SamplerWorkHeap, RenderTargetHeap};
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::luts::LutTexture; use crate::luts::LutTexture;
use librashader_presets::{ShaderPreset, TextureConfig}; use librashader_presets::{ShaderPreset, TextureConfig};
@ -14,17 +14,14 @@ use std::path::Path;
use windows::core::Interface; use windows::core::Interface;
use windows::w; use windows::w;
use windows::Win32::Foundation::CloseHandle; use windows::Win32::Foundation::CloseHandle;
use windows::Win32::Graphics::Direct3D12::{ use windows::Win32::Graphics::Direct3D12::{ID3D12CommandAllocator, ID3D12CommandQueue, ID3D12Device, ID3D12Fence, ID3D12GraphicsCommandList, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC, D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE, ID3D12DescriptorHeap};
ID3D12CommandAllocator, 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, ResetEvent, WaitForSingleObject}; use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleObject};
use windows::Win32::System::WindowsProgramming::INFINITE; use windows::Win32::System::WindowsProgramming::INFINITE;
use librashader_common::{ImageFormat, Size}; use librashader_common::{ImageFormat, Size, Viewport};
use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::back::{CompileReflectShader, CompileShader};
use librashader_reflect::reflect::ReflectShader; use librashader_reflect::reflect::ReflectShader;
use librashader_reflect::reflect::semantics::{MAX_BINDINGS_COUNT, ShaderSemantics, TextureSemantics, UniformBinding}; use librashader_reflect::reflect::semantics::{MAX_BINDINGS_COUNT, ShaderSemantics, TextureSemantics, UniformBinding};
use librashader_runtime::binding::TextureInput;
use librashader_runtime::uniforms::UniformStorage; use librashader_runtime::uniforms::UniformStorage;
use crate::buffer::{D3D12Buffer, D3D12ConstantBuffer}; use crate::buffer::{D3D12Buffer, D3D12ConstantBuffer};
use crate::filter_pass::FilterPass; use crate::filter_pass::FilterPass;
@ -32,7 +29,7 @@ use crate::framebuffer::OwnedImage;
use crate::graphics_pipeline::{D3D12GraphicsPipeline, D3D12RootSignature}; use crate::graphics_pipeline::{D3D12GraphicsPipeline, D3D12RootSignature};
use crate::mipmap::D3D12MipmapGen; use crate::mipmap::D3D12MipmapGen;
use crate::quad_render::DrawQuad; use crate::quad_render::DrawQuad;
use crate::texture::InputTexture; use crate::texture::{InputTexture, OutputTexture};
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>; type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
@ -48,6 +45,10 @@ pub struct FilterChainD3D12 {
pub(crate) feedback_framebuffers: Box<[OwnedImage]>, pub(crate) feedback_framebuffers: Box<[OwnedImage]>,
pub(crate) history_framebuffers: VecDeque<OwnedImage>, pub(crate) history_framebuffers: VecDeque<OwnedImage>,
staging_heap: D3D12DescriptorHeap<CpuStagingHeap>, staging_heap: D3D12DescriptorHeap<CpuStagingHeap>,
rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>,
pub texture_heap: ID3D12DescriptorHeap,
pub sampler_heap: ID3D12DescriptorHeap,
} }
pub(crate) struct FilterCommon { pub(crate) struct FilterCommon {
@ -97,6 +98,10 @@ impl FilterChainD3D12 {
D3D12DescriptorHeap::new(device, D3D12DescriptorHeap::new(device,
(MAX_BINDINGS_COUNT as usize) * (MAX_BINDINGS_COUNT as usize) *
shader_count + 2048 + lut_count)?; shader_count + 2048 + lut_count)?;
let mut rtv_heap =
D3D12DescriptorHeap::new(device,
(MAX_BINDINGS_COUNT as usize) *
shader_count + 2048 + lut_count)?;
@ -104,7 +109,8 @@ impl FilterChainD3D12 {
let root_signature = D3D12RootSignature::new(device)?; let root_signature = D3D12RootSignature::new(device)?;
let filters = FilterChainD3D12::init_passes(device, &root_signature, passes, &semantics)?; let (texture_heap, sampler_heap, filters)
= FilterChainD3D12::init_passes(device, &root_signature, passes, &semantics)?;
@ -172,10 +178,13 @@ impl FilterChainD3D12 {
history_textures, history_textures,
}, },
staging_heap, staging_heap,
rtv_heap,
passes: filters, passes: filters,
output_framebuffers: output_framebuffers.into_boxed_slice(), output_framebuffers: output_framebuffers.into_boxed_slice(),
feedback_framebuffers: feedback_framebuffers.into_boxed_slice(), feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
history_framebuffers, history_framebuffers,
texture_heap,
sampler_heap
}) })
} }
@ -329,7 +338,7 @@ impl FilterChainD3D12 {
root_signature: &D3D12RootSignature, root_signature: &D3D12RootSignature,
passes: Vec<ShaderPassMeta>, passes: Vec<ShaderPassMeta>,
semantics: &ShaderSemantics,) semantics: &ShaderSemantics,)
-> error::Result<Vec<FilterPass>> { -> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>)> {
let mut filters = Vec::new(); let mut filters = Vec::new();
let shader_count = passes.len(); let shader_count = passes.len();
@ -337,8 +346,8 @@ impl FilterChainD3D12 {
D3D12DescriptorHeap::<ResourceWorkHeap>::new(device, D3D12DescriptorHeap::<ResourceWorkHeap>::new(device,
(MAX_BINDINGS_COUNT as usize) * (MAX_BINDINGS_COUNT as usize) *
shader_count)?; shader_count)?;
let work_heaps = unsafe { let (work_heaps, texture_heap_handle) = unsafe {
work_heap.suballocate(shader_count) work_heap.suballocate(MAX_BINDINGS_COUNT as usize)
}; };
@ -346,12 +355,12 @@ impl FilterChainD3D12 {
D3D12DescriptorHeap::new(device, D3D12DescriptorHeap::new(device,
(MAX_BINDINGS_COUNT as usize) * shader_count)?; (MAX_BINDINGS_COUNT as usize) * shader_count)?;
let sampler_work_heaps = unsafe { let (sampler_work_heaps, sampler_heap_handle) = unsafe {
sampler_work_heap.suballocate(shader_count) sampler_work_heap.suballocate(MAX_BINDINGS_COUNT as usize)
}; };
for (index, (((config, source, mut reflect), for (index, (((config, source, mut reflect),
texture_heap), sampler_heap)) mut texture_heap), mut sampler_heap))
in passes.into_iter() in passes.into_iter()
.zip(work_heaps) .zip(work_heaps)
.zip(sampler_work_heaps) .zip(sampler_work_heaps)
@ -411,6 +420,8 @@ impl FilterChainD3D12 {
uniform_bindings.insert(UniformBinding::TextureSize(*semantics), param.offset); uniform_bindings.insert(UniformBinding::TextureSize(*semantics), param.offset);
} }
let texture_heap = texture_heap.alloc_range()?;
let sampler_heap = sampler_heap.alloc_range()?;
filters.push(FilterPass { filters.push(FilterPass {
reflection, reflection,
uniform_bindings, uniform_bindings,
@ -426,7 +437,84 @@ impl FilterChainD3D12 {
} }
Ok(filters) Ok((texture_heap_handle, sampler_heap_handle, filters))
}
/// Process a frame with the input image.
pub fn frame(
&mut self,
input: InputTexture,
viewport: &Viewport<OutputTexture>,
frame_count: usize,
options: Option<&()>,
) -> error::Result<()>
{
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
let passes = &mut self.passes[0..max];
if passes.is_empty() {
return Ok(());
}
let filter = passes[0].config.filter;
let wrap_mode = passes[0].config.wrap_mode;
for ((texture, fbo), pass) in self
.common
.feedback_textures
.iter_mut()
.zip(self.feedback_framebuffers.iter())
.zip(passes.iter())
{
*texture = Some(fbo.create_shader_resource_view(&mut self.staging_heap,
pass.config.filter,
pass.config.wrap_mode)?);
}
for (texture, fbo) in self
.common
.history_textures
.iter_mut()
.zip(self.history_framebuffers.iter())
{
*texture = Some(fbo.create_shader_resource_view(&mut self.staging_heap,
filter,
wrap_mode)?);
}
let original = &input;
let mut source = &input;
// rescale render buffers to ensure all bindings are valid.
let mut source_size = source.size();
let mut iterator = passes.iter_mut().enumerate().peekable();
while let Some((index, pass)) = iterator.next() {
let should_mipmap = iterator
.peek()
.map(|(_, p)| p.config.mipmap_input)
.unwrap_or(false);
// let next_size = self.output_framebuffers[index].scale(
// pass.config.scaling.clone(),
// pass.get_format(),
// &viewport.output.size,
// &source_size,
// should_mipmap,
// )?;
//
// self.feedback_framebuffers[index].scale(
// pass.config.scaling.clone(),
// pass.get_format(),
// &viewport.output.size,
// &source_size,
// should_mipmap,
// )?;
// source_size = next_size;
}
Ok(())
} }
} }

View file

@ -1,19 +1,24 @@
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use windows::core::Interface;
use windows::Win32::Foundation::RECT;
use windows::Win32::Graphics::Direct3D11::ID3D11Device; use windows::Win32::Graphics::Direct3D11::ID3D11Device;
use windows::Win32::Graphics::Direct3D12::ID3D12Device; use windows::Win32::Graphics::Direct3D12::{D3D12_RENDER_PASS_BEGINNING_ACCESS, D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD, D3D12_RENDER_PASS_ENDING_ACCESS, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE, D3D12_RENDER_PASS_FLAG_NONE, D3D12_RENDER_PASS_RENDER_TARGET_DESC, D3D12_VIEWPORT, ID3D12CommandList, ID3D12Device, ID3D12GraphicsCommandList, ID3D12GraphicsCommandList4};
use librashader_common::{ImageFormat, Size}; use librashader_common::{ImageFormat, Size, Viewport};
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, UniformBinding}; use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, UniformBinding};
use librashader_reflect::reflect::ShaderReflection; use librashader_reflect::reflect::ShaderReflection;
use librashader_runtime::binding::{BindSemantics, TextureInput}; use librashader_runtime::binding::{BindSemantics, TextureInput};
use librashader_runtime::uniforms::UniformStorage; use librashader_runtime::quad::QuadType;
use librashader_runtime::uniforms::{UniformStorage, UniformStorageAccess};
use crate::buffer::D3D12ConstantBuffer; use crate::buffer::D3D12ConstantBuffer;
use crate::{error, util};
use crate::filter_chain::FilterCommon; use crate::filter_chain::FilterCommon;
use crate::graphics_pipeline::D3D12GraphicsPipeline; use crate::graphics_pipeline::D3D12GraphicsPipeline;
use crate::heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot, ResourceWorkHeap, SamplerWorkHeap}; use crate::heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot, ResourceWorkHeap, SamplerWorkHeap};
use crate::render_target::RenderTarget;
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::texture::InputTexture; use crate::texture::{InputTexture, OutputTexture};
pub(crate) struct FilterPass { pub(crate) struct FilterPass {
pub(crate) pipeline: D3D12GraphicsPipeline, pub(crate) pipeline: D3D12GraphicsPipeline,
@ -23,8 +28,8 @@ pub(crate) struct FilterPass {
pub uniform_storage: UniformStorage, pub uniform_storage: UniformStorage,
pub(crate) push_cbuffer: Option<D3D12ConstantBuffer>, pub(crate) push_cbuffer: Option<D3D12ConstantBuffer>,
pub(crate) ubo_cbuffer: Option<D3D12ConstantBuffer>, pub(crate) ubo_cbuffer: Option<D3D12ConstantBuffer>,
pub(crate) texture_heap: D3D12DescriptorHeap<ResourceWorkHeap>, pub(crate) texture_heap: [D3D12DescriptorHeapSlot<ResourceWorkHeap>; 16],
pub(crate) sampler_heap: D3D12DescriptorHeap<SamplerWorkHeap>, pub(crate) sampler_heap: [D3D12DescriptorHeapSlot<SamplerWorkHeap>; 16],
pub source: ShaderSource, pub source: ShaderSource,
} }
@ -34,7 +39,7 @@ impl TextureInput for InputTexture {
self.size self.size
} }
} }
//
impl BindSemantics for FilterPass { impl BindSemantics for FilterPass {
type InputTexture = InputTexture; type InputTexture = InputTexture;
type SamplerSet = SamplerSet; type SamplerSet = SamplerSet;
@ -87,18 +92,15 @@ impl FilterPass {
frame_direction: i32, frame_direction: i32,
fb_size: Size<u32>, fb_size: Size<u32>,
viewport_size: Size<u32>, viewport_size: Size<u32>,
mut descriptors: (
&'a mut [D3D12DescriptorHeapSlot<ResourceWorkHeap>; 16],
&'a mut [D3D12DescriptorHeapSlot<SamplerWorkHeap>; 16],
),
original: &InputTexture, original: &InputTexture,
source: &InputTexture, source: &InputTexture,
) { ) {
Self::bind_semantics( Self::bind_semantics(
&(), &(),
&parent.samplers, &parent.samplers,
&mut self.uniform_storage, &mut self.uniform_storage,
&mut descriptors, &mut (&mut self.texture_heap, &mut self.sampler_heap),
mvp, mvp,
frame_count, frame_count,
frame_direction, frame_direction,
@ -118,4 +120,121 @@ impl FilterPass {
&parent.config.parameters, &parent.config.parameters,
); );
} }
/// preconditions
/// rootsig is bound
/// descriptor heaps are bound
/// input must be ready to read from
/// output must be ready to write to
pub(crate) fn draw(
&mut self,
cmd: &ID3D12GraphicsCommandList,
pass_index: usize,
parent: &FilterCommon,
frame_count: u32,
frame_direction: i32,
viewport: &Viewport<OutputTexture>,
original: &InputTexture,
source: &InputTexture,
output: RenderTarget,
vbo_type: QuadType,
) -> error::Result<()> {
parent.draw_quad.bind_vertices(cmd, vbo_type);
unsafe {
cmd.SetPipelineState(&self.pipeline.handle);
}
self.build_semantics(
pass_index,
parent,
output.mvp,
frame_count,
frame_direction,
output.output.size,
viewport.output.size,
original,
source,
);
// todo: write directly to persistently bound cbuffer.
if let Some(ubo) = &self.reflection.ubo
&& let Some(cbuffer) = &mut self.ubo_cbuffer
&& ubo.size != 0
{
{
let guard = cbuffer.buffer.map(None)?;
guard.slice.copy_from_slice(self.uniform_storage.ubo_slice());
}
unsafe {
cmd.SetGraphicsRootConstantBufferView(2, cbuffer.desc.BufferLocation)
}
}
if let Some(push) = &self.reflection.push_constant
&& let Some(cbuffer) = &mut self.push_cbuffer
&& push.size != 0
{
{
let guard = cbuffer.buffer.map(None)?;
guard.slice.copy_from_slice(self.uniform_storage.push_slice());
}
unsafe {
cmd.SetGraphicsRootConstantBufferView(3, cbuffer.desc.BufferLocation)
}
}
unsafe {
cmd.SetGraphicsRootDescriptorTable(0, *self.texture_heap[0].as_ref());
cmd.SetGraphicsRootDescriptorTable(0, *self.sampler_heap[0].as_ref());
}
// todo: check for non-renderpass.
let cmd = cmd.cast::<ID3D12GraphicsCommandList4>()?;
unsafe {
let pass = [D3D12_RENDER_PASS_RENDER_TARGET_DESC {
cpuDescriptor: *output.output.descriptor.as_ref(),
BeginningAccess: D3D12_RENDER_PASS_BEGINNING_ACCESS {
Type: D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD,
..Default::default()
},
EndingAccess: D3D12_RENDER_PASS_ENDING_ACCESS {
Type: D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE,
Anonymous: Default::default(),
},
}];
cmd.BeginRenderPass(Some(&pass), None, D3D12_RENDER_PASS_FLAG_NONE)
}
unsafe {
cmd.RSSetViewports(&[D3D12_VIEWPORT {
TopLeftX: output.x,
TopLeftY: output.y,
Width: output.output.size.width as f32,
Height: output.output.size.height as f32,
MinDepth: 0.0,
MaxDepth: 1.0,
}]);
cmd.RSSetScissorRects(&[RECT {
left: 0,
top: 0,
right: output.output.size.width as i32,
bottom: output.output.size.height as i32,
}]);
// todo put this in drawquad
cmd.DrawInstanced(4, 1, 0, 0)
}
unsafe {
cmd.EndRenderPass()
}
Ok(())
}
} }

View file

@ -4,8 +4,8 @@ use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_runtime::scaling::MipmapSize; use librashader_runtime::scaling::MipmapSize;
use crate::error; use crate::error;
use crate::error::assume_d3d12_init; use crate::error::assume_d3d12_init;
use crate::heap::{CpuStagingHeap, D3D12DescriptorHeap}; use crate::heap::{CpuStagingHeap, D3D12DescriptorHeap, RenderTargetHeap};
use crate::texture::InputTexture; use crate::texture::{InputTexture, OutputTexture};
use crate::util::d3d12_get_closest_format; use crate::util::d3d12_get_closest_format;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -113,8 +113,8 @@ impl OwnedImage {
Ok(InputTexture::new(descriptor, self.size, self.format, wrap_mode, filter)) Ok(InputTexture::new(descriptor, self.size, self.format, wrap_mode, filter))
} }
pub(crate) fn create_render_target_view(&self, heap: &mut D3D12DescriptorHeap<CpuStagingHeap>, pub(crate) fn create_render_target_view(&self, heap: &mut D3D12DescriptorHeap<RenderTargetHeap>
filter: FilterMode, wrap_mode: WrapMode) -> error::Result<InputTexture> { ) -> error::Result<OutputTexture> {
let descriptor = heap.alloc_slot()?; let descriptor = heap.alloc_slot()?;
@ -133,6 +133,6 @@ impl OwnedImage {
self.device.CreateRenderTargetView(&self.handle, Some(&rtv_desc), *descriptor.as_ref()); self.device.CreateRenderTargetView(&self.handle, Some(&rtv_desc), *descriptor.as_ref());
} }
Ok(InputTexture::new(descriptor, self.size, self.format, wrap_mode, filter)) Ok(OutputTexture::new(descriptor, self.size))
} }
} }

View file

@ -8,7 +8,7 @@ use crate::{error, util};
use crate::quad_render::DrawQuad; use crate::quad_render::DrawQuad;
pub struct D3D12GraphicsPipeline { pub struct D3D12GraphicsPipeline {
pipeline_state: ID3D12PipelineState, pub(crate) handle: ID3D12PipelineState,
} }
const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[ const D3D12_SLANG_ROOT_PARAMETERS: &[D3D12_ROOT_PARAMETER; 4] = &[
@ -198,7 +198,7 @@ impl D3D12GraphicsPipeline {
}; };
Ok(D3D12GraphicsPipeline { Ok(D3D12GraphicsPipeline {
pipeline_state, handle: pipeline_state,
}) })
} }
} }

View file

@ -3,7 +3,7 @@ use std::cell::RefCell;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::Deref; use std::ops::Deref;
use std::sync::Arc; use std::sync::Arc;
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, D3D12_DESCRIPTOR_HEAP_TYPE}; 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, D3D12_DESCRIPTOR_HEAP_TYPE, D3D12_DESCRIPTOR_HEAP_TYPE_RTV};
#[const_trait] #[const_trait]
pub trait D3D12HeapType { pub trait D3D12HeapType {
@ -17,6 +17,9 @@ pub struct SamplerPaletteHeap;
#[derive(Clone)] #[derive(Clone)]
pub struct CpuStagingHeap; pub struct CpuStagingHeap;
#[derive(Clone)]
pub struct RenderTargetHeap;
#[derive(Clone)] #[derive(Clone)]
pub struct ResourceWorkHeap; pub struct ResourceWorkHeap;
@ -47,6 +50,18 @@ impl const D3D12HeapType for CpuStagingHeap {
} }
} }
impl const D3D12HeapType for RenderTargetHeap {
// 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_RTV,
NumDescriptors: size as u32,
Flags: D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
NodeMask: 0,
}
}
}
impl D3D12ShaderVisibleHeapType for ResourceWorkHeap {} impl D3D12ShaderVisibleHeapType for ResourceWorkHeap {}
impl const D3D12HeapType for ResourceWorkHeap { impl const D3D12HeapType for ResourceWorkHeap {
// Lut texture heaps are CPU only and get bound to the descriptor heap of the shader. // Lut texture heaps are CPU only and get bound to the descriptor heap of the shader.
@ -73,7 +88,6 @@ impl const D3D12HeapType for SamplerWorkHeap {
} }
} }
#[derive(Clone)]
pub struct D3D12DescriptorHeapSlot<T> { pub struct D3D12DescriptorHeapSlot<T> {
cpu_handle: D3D12_CPU_DESCRIPTOR_HANDLE, cpu_handle: D3D12_CPU_DESCRIPTOR_HANDLE,
gpu_handle: Option<D3D12_GPU_DESCRIPTOR_HANDLE>, gpu_handle: Option<D3D12_GPU_DESCRIPTOR_HANDLE>,
@ -191,7 +205,7 @@ impl<T> D3D12DescriptorHeap<T> {
/// descriptors allocated for it. /// descriptors allocated for it.
/// ///
/// size must also divide equally into the size of the heap. /// size must also divide equally into the size of the heap.
pub unsafe fn suballocate(self, size: usize) -> Vec<D3D12DescriptorHeap<T>> { pub unsafe fn suballocate(self, size: usize) -> (Vec<D3D12DescriptorHeap<T>>, ID3D12DescriptorHeap) {
// has to be called right after creation. // has to be called right after creation.
assert_eq!(Arc::strong_count(&self.0), 1, assert_eq!(Arc::strong_count(&self.0), 1,
"D3D12DescriptorHeap::suballocate can only be callled immediately after creation."); "D3D12DescriptorHeap::suballocate can only be callled immediately after creation.");
@ -237,11 +251,11 @@ impl<T> D3D12DescriptorHeap<T> {
start += size; start += size;
} }
heaps.into_iter() (heaps.into_iter()
.map(|inner| D3D12DescriptorHeap( .map(|inner| D3D12DescriptorHeap(
Arc::new(RefCell::new(inner)), Arc::new(RefCell::new(inner)),
PhantomData::default())) PhantomData::default()))
.collect() .collect(), inner.heap)
} }
pub fn alloc_slot(&mut self) -> error::Result<D3D12DescriptorHeapSlot<T>> { pub fn alloc_slot(&mut self) -> error::Result<D3D12DescriptorHeapSlot<T>> {

View file

@ -15,6 +15,7 @@ mod graphics_pipeline;
mod buffer; mod buffer;
mod framebuffer; mod framebuffer;
mod texture; mod texture;
mod render_target;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -5,6 +5,7 @@ use windows::w;
use windows::Win32::Graphics::Direct3D::{D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP}; use windows::Win32::Graphics::Direct3D::{D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP};
use windows::Win32::Graphics::Direct3D12::{D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, D3D12_INPUT_ELEMENT_DESC, D3D12_VERTEX_BUFFER_VIEW, ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource}; use windows::Win32::Graphics::Direct3D12::{D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, D3D12_INPUT_ELEMENT_DESC, D3D12_VERTEX_BUFFER_VIEW, ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource};
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R32G32_FLOAT; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R32G32_FLOAT;
use librashader_runtime::quad::QuadType;
use crate::buffer::{D3D12Buffer}; use crate::buffer::{D3D12Buffer};
#[repr(C)] #[repr(C)]
@ -70,7 +71,7 @@ impl DrawQuad {
}) })
} }
pub fn bind_vertices(&self, cmd: &ID3D12GraphicsCommandList) { pub fn bind_vertices(&self, cmd: &ID3D12GraphicsCommandList, _vbo_type: QuadType) {
unsafe { unsafe {
cmd.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); cmd.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
cmd.IASetVertexBuffers(0, Some(&[self.view])); cmd.IASetVertexBuffers(0, Some(&[self.view]));

View file

@ -0,0 +1,9 @@
use crate::texture::OutputTexture;
pub(crate) struct RenderTarget<'a> {
pub x: f32,
pub y: f32,
pub mvp: &'a [f32; 16],
pub output: OutputTexture,
}

View file

@ -1,6 +1,6 @@
use windows::Win32::Graphics::Direct3D12::{D3D12_CPU_DESCRIPTOR_HANDLE}; use windows::Win32::Graphics::Direct3D12::{D3D12_CPU_DESCRIPTOR_HANDLE};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use crate::heap::{CpuStagingHeap, D3D12DescriptorHeapSlot}; use crate::heap::{CpuStagingHeap, D3D12DescriptorHeapSlot, RenderTargetHeap};
pub(crate) enum InputDescriptor { pub(crate) enum InputDescriptor {
Owned(D3D12DescriptorHeapSlot<CpuStagingHeap>), Owned(D3D12DescriptorHeapSlot<CpuStagingHeap>),
@ -8,7 +8,7 @@ pub(crate) enum InputDescriptor {
} }
pub(crate) enum OutputDescriptor { pub(crate) enum OutputDescriptor {
Owned(D3D12DescriptorHeapSlot<CpuStagingHeap>), Owned(D3D12DescriptorHeapSlot<RenderTargetHeap>),
Raw(D3D12_CPU_DESCRIPTOR_HANDLE) Raw(D3D12_CPU_DESCRIPTOR_HANDLE)
} }
@ -31,12 +31,12 @@ impl AsRef<D3D12_CPU_DESCRIPTOR_HANDLE> for OutputDescriptor {
} }
pub struct OutputTexture { pub struct OutputTexture {
descriptor: OutputDescriptor, pub(crate) descriptor: OutputDescriptor,
size: Size<u32>, pub(crate) size: Size<u32>,
} }
impl OutputTexture { impl OutputTexture {
pub fn new(handle: D3D12DescriptorHeapSlot<CpuStagingHeap>, pub fn new(handle: D3D12DescriptorHeapSlot<RenderTargetHeap>,
size: Size<u32>, size: Size<u32>,
) -> OutputTexture { ) -> OutputTexture {
let descriptor = OutputDescriptor::Owned(handle); let descriptor = OutputDescriptor::Owned(handle);