d3d12: render to intermediate buffers
This commit is contained in:
parent
cbe087fa6c
commit
c29cc51ed5
|
@ -1,5 +1,5 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use crate::{error};
|
use crate::{error, util};
|
||||||
use crate::heap::{D3D12DescriptorHeap, CpuStagingHeap, ResourceWorkHeap, SamplerWorkHeap, RenderTargetHeap};
|
use crate::heap::{D3D12DescriptorHeap, CpuStagingHeap, ResourceWorkHeap, SamplerWorkHeap, RenderTargetHeap};
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::luts::LutTexture;
|
use crate::luts::LutTexture;
|
||||||
|
@ -14,7 +14,7 @@ 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::{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::Threading::{CreateEventA, ResetEvent, WaitForSingleObject};
|
||||||
use windows::Win32::System::WindowsProgramming::INFINITE;
|
use windows::Win32::System::WindowsProgramming::INFINITE;
|
||||||
use librashader_common::{ImageFormat, Size, Viewport};
|
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::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::binding::TextureInput;
|
||||||
|
use librashader_runtime::quad::{IDENTITY_MVP, QuadType};
|
||||||
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;
|
||||||
|
@ -29,6 +30,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::render_target::RenderTarget;
|
||||||
use crate::texture::{InputTexture, OutputTexture};
|
use crate::texture::{InputTexture, OutputTexture};
|
||||||
|
|
||||||
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
|
type ShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
|
||||||
|
@ -443,7 +445,8 @@ impl FilterChainD3D12 {
|
||||||
/// Process a frame with the input image.
|
/// Process a frame with the input image.
|
||||||
pub fn frame(
|
pub fn frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: InputTexture,
|
cmd: &ID3D12GraphicsCommandList,
|
||||||
|
mut input: InputTexture,
|
||||||
viewport: &Viewport<OutputTexture>,
|
viewport: &Viewport<OutputTexture>,
|
||||||
frame_count: usize,
|
frame_count: usize,
|
||||||
options: Option<&()>,
|
options: Option<&()>,
|
||||||
|
@ -482,8 +485,8 @@ impl FilterChainD3D12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let original = &input;
|
let original = input;
|
||||||
let mut source = &input;
|
let mut source = unsafe { original.cloned() };
|
||||||
|
|
||||||
|
|
||||||
// rescale render buffers to ensure all bindings are valid.
|
// rescale render buffers to ensure all bindings are valid.
|
||||||
|
@ -512,8 +515,78 @@ impl FilterChainD3D12 {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
source_size = next_size;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ impl FilterPass {
|
||||||
viewport: &Viewport<OutputTexture>,
|
viewport: &Viewport<OutputTexture>,
|
||||||
original: &InputTexture,
|
original: &InputTexture,
|
||||||
source: &InputTexture,
|
source: &InputTexture,
|
||||||
output: RenderTarget,
|
output: &RenderTarget,
|
||||||
vbo_type: QuadType,
|
vbo_type: QuadType,
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ impl FilterPass {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
cmd.SetGraphicsRootDescriptorTable(0, *self.texture_heap[0].as_ref());
|
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.
|
// 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 windows::Win32::Graphics::Dxgi::Common::{DXGI_SAMPLE_DESC};
|
||||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||||
use librashader_presets::Scale2D;
|
use librashader_presets::Scale2D;
|
||||||
|
@ -11,7 +11,7 @@ use crate::util::d3d12_get_closest_format;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct OwnedImage {
|
pub(crate) struct OwnedImage {
|
||||||
handle: ID3D12Resource,
|
pub(crate)handle: ID3D12Resource,
|
||||||
pub(crate) size: Size<u32>,
|
pub(crate) size: Size<u32>,
|
||||||
format: ImageFormat,
|
format: ImageFormat,
|
||||||
device: ID3D12Device,
|
device: ID3D12Device,
|
||||||
|
@ -41,7 +41,7 @@ impl OwnedImage {
|
||||||
Quality: 0,
|
Quality: 0,
|
||||||
},
|
},
|
||||||
Layout: Default::default(),
|
Layout: Default::default(),
|
||||||
Flags: Default::default(),
|
Flags: D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut format_support = D3D12_FEATURE_DATA_FORMAT_SUPPORT {
|
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 {
|
pub struct D3D12RootSignature {
|
||||||
signature: ID3D12RootSignature
|
pub(crate) handle: ID3D12RootSignature
|
||||||
}
|
}
|
||||||
|
|
||||||
impl D3D12RootSignature {
|
impl D3D12RootSignature {
|
||||||
|
@ -107,7 +107,7 @@ impl D3D12RootSignature {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(D3D12RootSignature {
|
Ok(D3D12RootSignature {
|
||||||
signature,
|
handle: signature,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ impl D3D12GraphicsPipeline {
|
||||||
|
|
||||||
let pipeline_state: ID3D12PipelineState = unsafe {
|
let pipeline_state: ID3D12PipelineState = unsafe {
|
||||||
let pipeline_desc = D3D12_GRAPHICS_PIPELINE_STATE_DESC {
|
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 {
|
VS: D3D12_SHADER_BYTECODE {
|
||||||
pShaderBytecode: vertex_dxbc.GetBufferPointer(),
|
pShaderBytecode: vertex_dxbc.GetBufferPointer(),
|
||||||
BytecodeLength: vertex_dxbc.GetBufferSize(),
|
BytecodeLength: vertex_dxbc.GetBufferSize(),
|
||||||
|
|
|
@ -241,6 +241,7 @@ pub mod d3d12_hello_triangle {
|
||||||
use crate::filter_chain::FilterChainD3D12;
|
use crate::filter_chain::FilterChainD3D12;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use librashader_common::{FilterMode, Size, Viewport, WrapMode};
|
use librashader_common::{FilterMode, Size, Viewport, WrapMode};
|
||||||
|
use crate::heap::{CpuStagingHeap, D3D12DescriptorHeap};
|
||||||
use crate::texture::{InputTexture, OutputTexture};
|
use crate::texture::{InputTexture, OutputTexture};
|
||||||
|
|
||||||
const FRAME_COUNT: u32 = 2;
|
const FRAME_COUNT: u32 = 2;
|
||||||
|
@ -276,6 +277,7 @@ pub mod d3d12_hello_triangle {
|
||||||
fence: ID3D12Fence,
|
fence: ID3D12Fence,
|
||||||
fence_value: u64,
|
fence_value: u64,
|
||||||
fence_event: HANDLE,
|
fence_event: HANDLE,
|
||||||
|
frambuffer_heap: D3D12DescriptorHeap<CpuStagingHeap>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DXSample for Sample {
|
impl DXSample for Sample {
|
||||||
|
@ -468,6 +470,7 @@ pub mod d3d12_hello_triangle {
|
||||||
fence,
|
fence,
|
||||||
fence_value,
|
fence_value,
|
||||||
fence_event,
|
fence_event,
|
||||||
|
frambuffer_heap: D3D12DescriptorHeap::new(&self.device, 1024).unwrap(),
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -483,7 +486,24 @@ pub mod d3d12_hello_triangle {
|
||||||
|
|
||||||
fn render(&mut self) {
|
fn render(&mut self) {
|
||||||
if let Some(resources) = &mut self.resources {
|
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.
|
// Execute the command list.
|
||||||
let command_list = ID3D12CommandList::from(&resources.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 list allocators can only be reset when the associated
|
||||||
// command lists have finished execution on the GPU; apps should use
|
// command lists have finished execution on the GPU; apps should use
|
||||||
// fences to determine GPU execution progress.
|
// fences to determine GPU execution progress.
|
||||||
|
@ -568,9 +591,9 @@ pub mod d3d12_hello_triangle {
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
filter.frame(
|
filter.frame(
|
||||||
InputTexture::new_from_raw(D3D12_CPU_DESCRIPTOR_HANDLE {
|
command_list,
|
||||||
ptr: 0
|
InputTexture::new_from_raw(framebuffer,
|
||||||
}, Size::new(resources.viewport.Width as u32, resources.viewport.Height as u32),
|
Size::new(resources.viewport.Width as u32, resources.viewport.Height as u32),
|
||||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
WrapMode::ClampToEdge,
|
WrapMode::ClampToEdge,
|
||||||
FilterMode::Linear,
|
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 {
|
impl AsRef<InputTexture> for InputTexture {
|
||||||
|
|
Loading…
Reference in a new issue