d3d12: render to intermediate buffers
This commit is contained in:
parent
cbe087fa6c
commit
c29cc51ed5
|
@ -1,5 +1,5 @@
|
|||
use std::collections::VecDeque;
|
||||
use crate::{error};
|
||||
use crate::{error, util};
|
||||
use crate::heap::{D3D12DescriptorHeap, CpuStagingHeap, ResourceWorkHeap, SamplerWorkHeap, RenderTargetHeap};
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::luts::LutTexture;
|
||||
|
@ -14,7 +14,7 @@ use std::path::Path;
|
|||
use windows::core::Interface;
|
||||
use windows::w;
|
||||
use windows::Win32::Foundation::CloseHandle;
|
||||
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};
|
||||
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, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET};
|
||||
use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleObject};
|
||||
use windows::Win32::System::WindowsProgramming::INFINITE;
|
||||
use librashader_common::{ImageFormat, Size, Viewport};
|
||||
|
@ -22,6 +22,7 @@ use librashader_reflect::back::{CompileReflectShader, CompileShader};
|
|||
use librashader_reflect::reflect::ReflectShader;
|
||||
use librashader_reflect::reflect::semantics::{MAX_BINDINGS_COUNT, ShaderSemantics, TextureSemantics, UniformBinding};
|
||||
use librashader_runtime::binding::TextureInput;
|
||||
use librashader_runtime::quad::{IDENTITY_MVP, QuadType};
|
||||
use librashader_runtime::uniforms::UniformStorage;
|
||||
use crate::buffer::{D3D12Buffer, D3D12ConstantBuffer};
|
||||
use crate::filter_pass::FilterPass;
|
||||
|
@ -29,6 +30,7 @@ use crate::framebuffer::OwnedImage;
|
|||
use crate::graphics_pipeline::{D3D12GraphicsPipeline, D3D12RootSignature};
|
||||
use crate::mipmap::D3D12MipmapGen;
|
||||
use crate::quad_render::DrawQuad;
|
||||
use crate::render_target::RenderTarget;
|
||||
use crate::texture::{InputTexture, OutputTexture};
|
||||
|
||||
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
|
||||
|
@ -443,7 +445,8 @@ impl FilterChainD3D12 {
|
|||
/// Process a frame with the input image.
|
||||
pub fn frame(
|
||||
&mut self,
|
||||
input: InputTexture,
|
||||
cmd: &ID3D12GraphicsCommandList,
|
||||
mut input: InputTexture,
|
||||
viewport: &Viewport<OutputTexture>,
|
||||
frame_count: usize,
|
||||
options: Option<&()>,
|
||||
|
@ -482,8 +485,8 @@ impl FilterChainD3D12 {
|
|||
}
|
||||
|
||||
|
||||
let original = &input;
|
||||
let mut source = &input;
|
||||
let original = input;
|
||||
let mut source = unsafe { original.cloned() };
|
||||
|
||||
|
||||
// rescale render buffers to ensure all bindings are valid.
|
||||
|
@ -512,8 +515,78 @@ impl FilterChainD3D12 {
|
|||
)?;
|
||||
|
||||
source_size = next_size;
|
||||
|
||||
// refresh inputs
|
||||
self.common.feedback_textures[index] = Some(
|
||||
self.feedback_framebuffers[index]
|
||||
.create_shader_resource_view(&mut self.staging_heap, pass.config.filter, pass.config.wrap_mode)?,
|
||||
);
|
||||
self.common.output_textures[index] = Some(
|
||||
self.output_framebuffers[index]
|
||||
.create_shader_resource_view(&mut self.staging_heap, pass.config.filter, pass.config.wrap_mode)?,
|
||||
);
|
||||
}
|
||||
|
||||
let passes_len = passes.len();
|
||||
let (pass, last) = passes.split_at_mut(passes_len - 1);
|
||||
|
||||
let mut residuals = Vec::new();
|
||||
|
||||
unsafe {
|
||||
let heaps = [self.texture_heap.clone(), self.sampler_heap.clone()];
|
||||
cmd.SetDescriptorHeaps(&heaps);
|
||||
cmd.SetGraphicsRootSignature(&self.common.root_signature.handle);
|
||||
}
|
||||
for (index, pass) in pass.iter_mut().enumerate() {
|
||||
|
||||
source.filter = pass.config.filter;
|
||||
source.wrap_mode = pass.config.wrap_mode;
|
||||
let target = &self.output_framebuffers[index];
|
||||
util::d3d12_resource_transition(&cmd,
|
||||
&target.handle,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
let size = target.size;
|
||||
let view = target.create_render_target_view(&mut self.rtv_heap)?;
|
||||
|
||||
let out = RenderTarget {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
mvp:IDENTITY_MVP,
|
||||
output: OutputTexture { descriptor: view.descriptor, size },
|
||||
};
|
||||
|
||||
pass.draw(
|
||||
cmd,
|
||||
index,
|
||||
&self.common,
|
||||
if pass.config.frame_count_mod > 0 {
|
||||
frame_count % pass.config.frame_count_mod as usize
|
||||
} else {
|
||||
frame_count
|
||||
} as u32,
|
||||
1,
|
||||
viewport,
|
||||
&original,
|
||||
&source,
|
||||
&out,
|
||||
QuadType::Offscreen
|
||||
)?;
|
||||
|
||||
util::d3d12_resource_transition(&cmd,
|
||||
&target.handle,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
// let target_handle = target.create_shader_resource_view(
|
||||
// &mut self.staging_heap,
|
||||
// pass.config.filter,
|
||||
// pass.config.wrap_mode,
|
||||
// )?;
|
||||
residuals.push(out.output.descriptor);
|
||||
source = self.common.output_textures[index].as_ref().unwrap().cloned()
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ impl FilterPass {
|
|||
viewport: &Viewport<OutputTexture>,
|
||||
original: &InputTexture,
|
||||
source: &InputTexture,
|
||||
output: RenderTarget,
|
||||
output: &RenderTarget,
|
||||
vbo_type: QuadType,
|
||||
) -> error::Result<()> {
|
||||
|
||||
|
@ -188,7 +188,7 @@ impl FilterPass {
|
|||
|
||||
unsafe {
|
||||
cmd.SetGraphicsRootDescriptorTable(0, *self.texture_heap[0].as_ref());
|
||||
cmd.SetGraphicsRootDescriptorTable(0, *self.sampler_heap[0].as_ref());
|
||||
cmd.SetGraphicsRootDescriptorTable(1, *self.sampler_heap[0].as_ref());
|
||||
}
|
||||
|
||||
// todo: check for non-renderpass.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use windows::Win32::Graphics::Direct3D12::{D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES, D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RENDER_TARGET_VIEW_DESC, D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RTV_DIMENSION_TEXTURE2D, D3D12_SHADER_RESOURCE_VIEW_DESC, D3D12_SHADER_RESOURCE_VIEW_DESC_0, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_RTV, D3D12_TEX2D_SRV, ID3D12Device, ID3D12Resource};
|
||||
use windows::Win32::Graphics::Direct3D12::{D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES, D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RENDER_TARGET_VIEW_DESC, D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RTV_DIMENSION_TEXTURE2D, D3D12_SHADER_RESOURCE_VIEW_DESC, D3D12_SHADER_RESOURCE_VIEW_DESC_0, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_RTV, D3D12_TEX2D_SRV, ID3D12Device, ID3D12Resource};
|
||||
use windows::Win32::Graphics::Dxgi::Common::{DXGI_SAMPLE_DESC};
|
||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||
use librashader_presets::Scale2D;
|
||||
|
@ -11,7 +11,7 @@ use crate::util::d3d12_get_closest_format;
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct OwnedImage {
|
||||
handle: ID3D12Resource,
|
||||
pub(crate)handle: ID3D12Resource,
|
||||
pub(crate) size: Size<u32>,
|
||||
format: ImageFormat,
|
||||
device: ID3D12Device,
|
||||
|
@ -41,7 +41,7 @@ impl OwnedImage {
|
|||
Quality: 0,
|
||||
},
|
||||
Layout: Default::default(),
|
||||
Flags: Default::default(),
|
||||
Flags: D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
|
||||
};
|
||||
|
||||
let mut format_support = D3D12_FEATURE_DATA_FORMAT_SUPPORT {
|
||||
|
|
|
@ -79,7 +79,7 @@ const D3D12_SLANG_ROOT_SIGNATURE: &D3D12_ROOT_SIGNATURE_DESC = &D3D12_ROOT_SIGNA
|
|||
};
|
||||
|
||||
pub struct D3D12RootSignature {
|
||||
signature: ID3D12RootSignature
|
||||
pub(crate) handle: ID3D12RootSignature
|
||||
}
|
||||
|
||||
impl D3D12RootSignature {
|
||||
|
@ -107,7 +107,7 @@ impl D3D12RootSignature {
|
|||
};
|
||||
|
||||
Ok(D3D12RootSignature {
|
||||
signature,
|
||||
handle: signature,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ impl D3D12GraphicsPipeline {
|
|||
|
||||
let pipeline_state: ID3D12PipelineState = unsafe {
|
||||
let pipeline_desc = D3D12_GRAPHICS_PIPELINE_STATE_DESC {
|
||||
pRootSignature: windows::core::ManuallyDrop::new(&root_signature.signature),
|
||||
pRootSignature: windows::core::ManuallyDrop::new(&root_signature.handle),
|
||||
VS: D3D12_SHADER_BYTECODE {
|
||||
pShaderBytecode: vertex_dxbc.GetBufferPointer(),
|
||||
BytecodeLength: vertex_dxbc.GetBufferSize(),
|
||||
|
|
|
@ -241,6 +241,7 @@ pub mod d3d12_hello_triangle {
|
|||
use crate::filter_chain::FilterChainD3D12;
|
||||
use std::path::Path;
|
||||
use librashader_common::{FilterMode, Size, Viewport, WrapMode};
|
||||
use crate::heap::{CpuStagingHeap, D3D12DescriptorHeap};
|
||||
use crate::texture::{InputTexture, OutputTexture};
|
||||
|
||||
const FRAME_COUNT: u32 = 2;
|
||||
|
@ -276,6 +277,7 @@ pub mod d3d12_hello_triangle {
|
|||
fence: ID3D12Fence,
|
||||
fence_value: u64,
|
||||
fence_event: HANDLE,
|
||||
frambuffer_heap: D3D12DescriptorHeap<CpuStagingHeap>
|
||||
}
|
||||
|
||||
impl DXSample for Sample {
|
||||
|
@ -468,6 +470,7 @@ pub mod d3d12_hello_triangle {
|
|||
fence,
|
||||
fence_value,
|
||||
fence_event,
|
||||
frambuffer_heap: D3D12DescriptorHeap::new(&self.device, 1024).unwrap(),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
@ -483,7 +486,24 @@ pub mod d3d12_hello_triangle {
|
|||
|
||||
fn render(&mut self) {
|
||||
if let Some(resources) = &mut self.resources {
|
||||
populate_command_list(resources, &mut self.filter, self.framecount).unwrap();
|
||||
let srv = resources.frambuffer_heap.alloc_slot()
|
||||
.unwrap();
|
||||
|
||||
unsafe {
|
||||
self.device.CreateShaderResourceView(&resources.framebuffer, Some(&D3D12_SHADER_RESOURCE_VIEW_DESC {
|
||||
Format: DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
ViewDimension: D3D12_SRV_DIMENSION_TEXTURE2D,
|
||||
Shader4ComponentMapping: D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
||||
Anonymous: D3D12_SHADER_RESOURCE_VIEW_DESC_0 {
|
||||
Texture2D: D3D12_TEX2D_SRV {
|
||||
MipLevels: u32::MAX,
|
||||
..Default::default()
|
||||
}
|
||||
},
|
||||
}), *srv.as_ref())
|
||||
}
|
||||
|
||||
populate_command_list(resources, &mut self.filter, self.framecount, *srv.as_ref()).unwrap();
|
||||
|
||||
// Execute the command list.
|
||||
let command_list = ID3D12CommandList::from(&resources.command_list);
|
||||
|
@ -498,7 +518,10 @@ pub mod d3d12_hello_triangle {
|
|||
}
|
||||
}
|
||||
|
||||
fn populate_command_list(resources: &Resources, filter: &mut FilterChainD3D12, frame_count: usize) -> Result<()> {
|
||||
fn populate_command_list(resources: &mut Resources, filter: &mut FilterChainD3D12,
|
||||
frame_count: usize,
|
||||
framebuffer: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||
) -> Result<()> {
|
||||
// Command list allocators can only be reset when the associated
|
||||
// command lists have finished execution on the GPU; apps should use
|
||||
// fences to determine GPU execution progress.
|
||||
|
@ -568,9 +591,9 @@ pub mod d3d12_hello_triangle {
|
|||
)]);
|
||||
|
||||
filter.frame(
|
||||
InputTexture::new_from_raw(D3D12_CPU_DESCRIPTOR_HANDLE {
|
||||
ptr: 0
|
||||
}, Size::new(resources.viewport.Width as u32, resources.viewport.Height as u32),
|
||||
command_list,
|
||||
InputTexture::new_from_raw(framebuffer,
|
||||
Size::new(resources.viewport.Width as u32, resources.viewport.Height as u32),
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
WrapMode::ClampToEdge,
|
||||
FilterMode::Linear,
|
||||
|
|
|
@ -100,6 +100,13 @@ impl InputTexture {
|
|||
}
|
||||
}
|
||||
|
||||
// parent descriptor has to stay alive.
|
||||
pub fn cloned(&self) -> InputTexture {
|
||||
unsafe {
|
||||
Self::new_from_raw(*self.descriptor.as_ref(),
|
||||
self.size, self.format, self.wrap_mode, self.filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<InputTexture> for InputTexture {
|
||||
|
|
Loading…
Reference in a new issue