rt: abstract reusable bindingmeta ops

This commit is contained in:
chyyran 2023-02-05 16:17:14 -05:00
parent 4e9cc26093
commit 7d8c137083
5 changed files with 254 additions and 333 deletions

View file

@ -5,7 +5,9 @@ use librashader_presets::{ShaderPreset, TextureConfig};
use librashader_reflect::back::targets::HLSL; use librashader_reflect::back::targets::HLSL;
use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::back::{CompileReflectShader, CompileShader};
use librashader_reflect::front::GlslangCompilation; use librashader_reflect::front::GlslangCompilation;
use librashader_reflect::reflect::semantics::{ShaderSemantics, TextureSemantics, UniformBinding}; use librashader_reflect::reflect::semantics::{
BindingMeta, ShaderSemantics, TextureSemantics, UniformBinding,
};
use librashader_reflect::reflect::ReflectShader; use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::image::{Image, UVDirection}; use librashader_runtime::image::{Image, UVDirection};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -23,7 +25,8 @@ use crate::samplers::SamplerSet;
use crate::util::d3d11_compile_bound_shader; use crate::util::d3d11_compile_bound_shader;
use crate::{error, util, D3D11OutputView}; use crate::{error, util, D3D11OutputView};
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_runtime::binding::TextureInput; use librashader_runtime::binding::{BindingUtil, TextureInput};
use librashader_runtime::quad::{QuadType, IDENTITY_MVP};
use librashader_runtime::uniforms::UniformStorage; use librashader_runtime::uniforms::UniformStorage;
use windows::Win32::Graphics::Direct3D11::{ use windows::Win32::Graphics::Direct3D11::{
ID3D11Buffer, ID3D11Device, ID3D11DeviceContext, D3D11_BIND_CONSTANT_BUFFER, D3D11_BUFFER_DESC, ID3D11Buffer, ID3D11Device, ID3D11DeviceContext, D3D11_BIND_CONSTANT_BUFFER, D3D11_BUFFER_DESC,
@ -31,7 +34,6 @@ use windows::Win32::Graphics::Direct3D11::{
D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC,
}; };
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM;
use librashader_runtime::quad::{IDENTITY_MVP, QuadType};
pub struct FilterMutable { pub struct FilterMutable {
pub(crate) passes_enabled: usize, pub(crate) passes_enabled: usize,
@ -284,18 +286,7 @@ impl FilterChainD3D11 {
.unwrap_or(0), .unwrap_or(0),
); );
let mut uniform_bindings = FxHashMap::default(); let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
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 { filters.push(FilterPass {
reflection, reflection,
@ -319,28 +310,8 @@ impl FilterChainD3D11 {
context: &ID3D11DeviceContext, context: &ID3D11DeviceContext,
filters: &Vec<FilterPass>, filters: &Vec<FilterPass>,
) -> error::Result<(VecDeque<OwnedFramebuffer>, Box<[Option<InputTexture>]>)> { ) -> error::Result<(VecDeque<OwnedFramebuffer>, Box<[Option<InputTexture>]>)> {
let mut required_images = 0; let mut required_images =
BindingMeta::calculate_required_history(filters.iter().map(|f| &f.reflection.meta));
for pass in filters {
// If a shader uses history size, but not history, we still need to keep the texture.
let texture_count = pass
.reflection
.meta
.texture_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
let texture_size_count = pass
.reflection
.meta
.texture_size_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
required_images = std::cmp::max(required_images, texture_count);
required_images = std::cmp::max(required_images, texture_size_count);
}
// not using frame history; // not using frame history;
if required_images <= 1 { if required_images <= 1 {
@ -522,7 +493,7 @@ impl FilterChainD3D11 {
&original, &original,
&source, &source,
RenderTarget::new(target.as_output_framebuffer()?, Some(IDENTITY_MVP)), RenderTarget::new(target.as_output_framebuffer()?, Some(IDENTITY_MVP)),
QuadType::Offscreen QuadType::Offscreen,
)?; )?;
source = InputTexture { source = InputTexture {
@ -554,7 +525,7 @@ impl FilterChainD3D11 {
&original, &original,
&source, &source,
viewport.into(), viewport.into(),
QuadType::Final QuadType::Final,
)?; )?;
} }

View file

@ -1,39 +1,51 @@
use std::collections::VecDeque;
use crate::{error, graphics_pipeline, util};
use crate::descriptor_heap::{D3D12DescriptorHeap, CpuStagingHeap, ResourceWorkHeap, SamplerWorkHeap, RenderTargetHeap};
use crate::samplers::SamplerSet;
use crate::luts::LutTexture;
use librashader_presets::{ShaderPreset, TextureConfig};
use librashader_reflect::back::targets::{DXIL, HLSL};
use librashader_reflect::front::GlslangCompilation;
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_runtime::image::{Image, UVDirection};
use rustc_hash::FxHashMap;
use std::error::Error;
use std::path::Path;
use spirv_cross::hlsl::ShaderModel;
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, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET};
use windows::Win32::Graphics::Direct3D::Dxc::{CLSID_DxcCompiler, CLSID_DxcLibrary, CLSID_DxcValidator, DxcCreateInstance, IDxcCompiler, IDxcLibrary, IDxcUtils, IDxcValidator};
use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleObject};
use windows::Win32::System::WindowsProgramming::INFINITE;
use librashader_common::{ImageFormat, Size, Viewport};
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::{DEFAULT_MVP, IDENTITY_MVP, QuadType};
use librashader_runtime::uniforms::UniformStorage;
use crate::buffer::{D3D12Buffer, D3D12ConstantBuffer}; use crate::buffer::{D3D12Buffer, D3D12ConstantBuffer};
use crate::descriptor_heap::{
CpuStagingHeap, D3D12DescriptorHeap, RenderTargetHeap, ResourceWorkHeap, SamplerWorkHeap,
};
use crate::filter_pass::FilterPass; use crate::filter_pass::FilterPass;
use crate::framebuffer::OwnedImage; use crate::framebuffer::OwnedImage;
use crate::graphics_pipeline::{D3D12GraphicsPipeline, D3D12RootSignature}; use crate::graphics_pipeline::{D3D12GraphicsPipeline, D3D12RootSignature};
use crate::luts::LutTexture;
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::render_target::RenderTarget;
use crate::samplers::SamplerSet;
use crate::texture::{InputTexture, OutputDescriptor, OutputTexture}; use crate::texture::{InputTexture, OutputDescriptor, OutputTexture};
use crate::{error, graphics_pipeline, util};
use librashader_common::{ImageFormat, Size, Viewport};
use librashader_presets::{ShaderPreset, TextureConfig};
use librashader_reflect::back::targets::{DXIL, HLSL};
use librashader_reflect::back::{CompileReflectShader, CompileShader};
use librashader_reflect::front::GlslangCompilation;
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_reflect::reflect::semantics::{
BindingMeta, ShaderSemantics, TextureSemantics, UniformBinding, MAX_BINDINGS_COUNT,
};
use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::binding::{BindingUtil, TextureInput};
use librashader_runtime::image::{Image, UVDirection};
use librashader_runtime::quad::{QuadType, DEFAULT_MVP, IDENTITY_MVP};
use librashader_runtime::uniforms::UniformStorage;
use rustc_hash::FxHashMap;
use spirv_cross::hlsl::ShaderModel;
use std::collections::VecDeque;
use std::error::Error;
use std::path::Path;
use windows::core::Interface;
use windows::w;
use windows::Win32::Foundation::CloseHandle;
use windows::Win32::Graphics::Direct3D::Dxc::{
CLSID_DxcCompiler, CLSID_DxcLibrary, CLSID_DxcValidator, DxcCreateInstance, IDxcCompiler,
IDxcLibrary, IDxcUtils, IDxcValidator,
};
use windows::Win32::Graphics::Direct3D12::{
ID3D12CommandAllocator, ID3D12CommandQueue, ID3D12DescriptorHeap, ID3D12Device, ID3D12Fence,
ID3D12GraphicsCommandList, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC,
D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE,
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;
type DxilShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation>>; type DxilShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation>>;
type HlslShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>; type HlslShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
@ -55,7 +67,7 @@ pub struct FilterChainD3D12 {
texture_heap: ID3D12DescriptorHeap, texture_heap: ID3D12DescriptorHeap,
sampler_heap: ID3D12DescriptorHeap, sampler_heap: ID3D12DescriptorHeap,
residuals: Vec<OutputDescriptor> residuals: Vec<OutputDescriptor>,
} }
pub(crate) struct FilterCommon { pub(crate) struct FilterCommon {
@ -95,50 +107,46 @@ impl FilterChainD3D12 {
let shader_copy = preset.shaders.clone(); let shader_copy = preset.shaders.clone();
let (passes, semantics) = DXIL::compile_preset_passes::<GlslangCompilation, Box<dyn Error>>( let (passes, semantics) =
preset.shaders, DXIL::compile_preset_passes::<GlslangCompilation, Box<dyn Error>>(
&preset.textures, preset.shaders,
).unwrap(); &preset.textures,
)
.unwrap();
let (hlsl_passes, _) = HLSL::compile_preset_passes::<GlslangCompilation, Box<dyn Error>>( let (hlsl_passes, _) = HLSL::compile_preset_passes::<GlslangCompilation, Box<dyn Error>>(
shader_copy, shader_copy,
&preset.textures, &preset.textures,
).unwrap(); )
.unwrap();
let samplers = SamplerSet::new(device)?; let samplers = SamplerSet::new(device)?;
let mipmap_gen = D3D12MipmapGen::new(device).unwrap(); let mipmap_gen = D3D12MipmapGen::new(device).unwrap();
let draw_quad = DrawQuad::new(device)?; let draw_quad = DrawQuad::new(device)?;
let mut staging_heap = let mut staging_heap = D3D12DescriptorHeap::new(
D3D12DescriptorHeap::new(device, 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 = let mut rtv_heap = D3D12DescriptorHeap::new(
D3D12DescriptorHeap::new(device, device,
(MAX_BINDINGS_COUNT as usize) * (MAX_BINDINGS_COUNT as usize) * shader_count + 2048 + lut_count,
shader_count + 2048 + lut_count)?; )?;
let luts =
FilterChainD3D12::load_luts(device, &mut staging_heap, &preset.textures, &mipmap_gen)
let luts = FilterChainD3D12::load_luts(device, &mut staging_heap, &preset.textures, &mipmap_gen).unwrap(); .unwrap();
let root_signature = D3D12RootSignature::new(device)?; let root_signature = D3D12RootSignature::new(device)?;
let (texture_heap, sampler_heap, filters) let (texture_heap, sampler_heap, filters) =
= FilterChainD3D12::init_passes(device, &root_signature, passes, hlsl_passes, &semantics).unwrap(); FilterChainD3D12::init_passes(device, &root_signature, passes, hlsl_passes, &semantics)
.unwrap();
// initialize output framebuffers // initialize output framebuffers
let mut output_framebuffers = Vec::new(); let mut output_framebuffers = Vec::new();
output_framebuffers.resize_with(filters.len(), || { output_framebuffers.resize_with(filters.len(), || {
OwnedImage::new( OwnedImage::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false)
device,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm,
false,
)
}); });
// resolve all results // resolve all results
@ -154,12 +162,7 @@ impl FilterChainD3D12 {
// // initialize feedback framebuffers // // initialize feedback framebuffers
let mut feedback_framebuffers = Vec::new(); let mut feedback_framebuffers = Vec::new();
feedback_framebuffers.resize_with(filters.len(), || { feedback_framebuffers.resize_with(filters.len(), || {
OwnedImage::new( OwnedImage::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false)
device,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm,
false,
)
}); });
// resolve all results // resolve all results
@ -200,7 +203,7 @@ impl FilterChainD3D12 {
history_framebuffers, history_framebuffers,
texture_heap, texture_heap,
sampler_heap, sampler_heap,
residuals: Vec::new() residuals: Vec::new(),
}) })
} }
@ -208,28 +211,8 @@ impl FilterChainD3D12 {
device: &ID3D12Device, device: &ID3D12Device,
filters: &Vec<FilterPass>, filters: &Vec<FilterPass>,
) -> error::Result<(VecDeque<OwnedImage>, Box<[Option<InputTexture>]>)> { ) -> error::Result<(VecDeque<OwnedImage>, Box<[Option<InputTexture>]>)> {
let mut required_images = 0; let mut required_images =
BindingMeta::calculate_required_history(filters.iter().map(|f| &f.reflection.meta));
for pass in filters {
// If a shader uses history size, but not history, we still need to keep the texture.
let texture_count = pass
.reflection
.meta
.texture_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
let texture_size_count = pass
.reflection
.meta
.texture_size_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
required_images = std::cmp::max(required_images, texture_count);
required_images = std::cmp::max(required_images, texture_size_count);
}
// not using frame history; // not using frame history;
if required_images <= 1 { if required_images <= 1 {
@ -242,12 +225,7 @@ impl FilterChainD3D12 {
// eprintln!("[history] using frame history with {required_images} images"); // eprintln!("[history] using frame history with {required_images} images");
let mut framebuffers = VecDeque::with_capacity(required_images); let mut framebuffers = VecDeque::with_capacity(required_images);
framebuffers.resize_with(required_images, || { framebuffers.resize_with(required_images, || {
OwnedImage::new( OwnedImage::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false)
device,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm,
false,
)
}); });
let framebuffers = framebuffers let framebuffers = framebuffers
@ -260,14 +238,14 @@ impl FilterChainD3D12 {
Ok((framebuffers, history_textures.into_boxed_slice())) Ok((framebuffers, history_textures.into_boxed_slice()))
} }
fn load_luts( fn load_luts(
device: &ID3D12Device, device: &ID3D12Device,
heap: &mut D3D12DescriptorHeap<CpuStagingHeap>, heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
textures: &[TextureConfig], textures: &[TextureConfig],
mipmap_gen: &D3D12MipmapGen mipmap_gen: &D3D12MipmapGen,
) -> error::Result<FxHashMap<usize, LutTexture>> { ) -> error::Result<FxHashMap<usize, LutTexture>> {
let mut work_heap: D3D12DescriptorHeap<ResourceWorkHeap> = D3D12DescriptorHeap::new(device, u16::MAX as usize)?; let mut work_heap: D3D12DescriptorHeap<ResourceWorkHeap> =
D3D12DescriptorHeap::new(device, u16::MAX as usize)?;
unsafe { unsafe {
// 1 time queue infrastructure for lut uploads // 1 time queue infrastructure for lut uploads
let command_pool: ID3D12CommandAllocator = let command_pool: ID3D12CommandAllocator =
@ -290,7 +268,6 @@ impl FilterChainD3D12 {
let mut luts = FxHashMap::default(); let mut luts = FxHashMap::default();
for (index, texture) in textures.iter().enumerate() { for (index, texture) in textures.iter().enumerate() {
let image = Image::load(&texture.path, UVDirection::TopLeft)?; let image = Image::load(&texture.path, UVDirection::TopLeft)?;
@ -324,8 +301,7 @@ impl FilterChainD3D12 {
cmd.Reset(&command_pool, None).unwrap(); cmd.Reset(&command_pool, None).unwrap();
let residuals = mipmap_gen let residuals = mipmap_gen.mipmapping_context(&cmd, &mut work_heap, |context| {
.mipmapping_context(&cmd, &mut work_heap, |context| {
for lut in luts.values() { for lut in luts.values() {
lut.generate_mipmaps(context).unwrap() lut.generate_mipmaps(context).unwrap()
} }
@ -350,54 +326,48 @@ impl FilterChainD3D12 {
} }
} }
fn init_passes(device: &ID3D12Device, fn init_passes(
root_signature: &D3D12RootSignature, device: &ID3D12Device,
passes: Vec<DxilShaderPassMeta>, root_signature: &D3D12RootSignature,
hlsl_passes: Vec<HlslShaderPassMeta>, passes: Vec<DxilShaderPassMeta>,
semantics: &ShaderSemantics,) hlsl_passes: Vec<HlslShaderPassMeta>,
-> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>)> { semantics: &ShaderSemantics,
let validator: IDxcValidator = unsafe { ) -> error::Result<(ID3D12DescriptorHeap, ID3D12DescriptorHeap, Vec<FilterPass>)> {
DxcCreateInstance(&CLSID_DxcValidator)? let validator: IDxcValidator = unsafe { DxcCreateInstance(&CLSID_DxcValidator)? };
};
let library: IDxcUtils = unsafe { let library: IDxcUtils = unsafe { DxcCreateInstance(&CLSID_DxcLibrary)? };
DxcCreateInstance(&CLSID_DxcLibrary)?
};
let compiler: IDxcCompiler = unsafe { let compiler: IDxcCompiler = unsafe { DxcCreateInstance(&CLSID_DxcCompiler)? };
DxcCreateInstance(&CLSID_DxcCompiler)?
};
let mut filters = Vec::new(); let mut filters = Vec::new();
let shader_count = passes.len(); let shader_count = passes.len();
let work_heap = let work_heap = D3D12DescriptorHeap::<ResourceWorkHeap>::new(
D3D12DescriptorHeap::<ResourceWorkHeap>::new(device, device,
(MAX_BINDINGS_COUNT as usize) * (MAX_BINDINGS_COUNT as usize) * shader_count,
shader_count)?; )?;
let (work_heaps, texture_heap_handle) = unsafe { let (work_heaps, texture_heap_handle) =
work_heap.suballocate(MAX_BINDINGS_COUNT as usize) unsafe { work_heap.suballocate(MAX_BINDINGS_COUNT as usize) };
};
let sampler_work_heap = let sampler_work_heap =
D3D12DescriptorHeap::new(device, D3D12DescriptorHeap::new(device, (MAX_BINDINGS_COUNT as usize) * shader_count)?;
(MAX_BINDINGS_COUNT as usize) * shader_count)?;
let (sampler_work_heaps, sampler_heap_handle) = unsafe { let (sampler_work_heaps, sampler_heap_handle) =
sampler_work_heap.suballocate(MAX_BINDINGS_COUNT as usize) unsafe { sampler_work_heap.suballocate(MAX_BINDINGS_COUNT as usize) };
};
for (index, ((((config, source, mut dxil), (_, _, mut hlsl)), for (
mut texture_heap), mut sampler_heap)) index,
in passes.into_iter() ((((config, source, mut dxil), (_, _, mut hlsl)), mut texture_heap), mut sampler_heap),
) in passes
.into_iter()
.zip(hlsl_passes) .zip(hlsl_passes)
.zip(work_heaps) .zip(work_heaps)
.zip(sampler_work_heaps) .zip(sampler_work_heaps)
.enumerate() { .enumerate()
{
let dxil_reflection = dxil.reflect(index, semantics)?; let dxil_reflection = dxil.reflect(index, semantics)?;
let dxil = dxil.compile(Some(librashader_reflect::back::dxil::ShaderModel::ShaderModel6_0))?; let dxil = dxil.compile(Some(
librashader_reflect::back::dxil::ShaderModel::ShaderModel6_0,
))?;
let hlsl_reflection = hlsl.reflect(index, semantics)?; let hlsl_reflection = hlsl.reflect(index, semantics)?;
let hlsl = hlsl.compile(Some(ShaderModel::V6_0))?; let hlsl = hlsl.compile(Some(ShaderModel::V6_0))?;
@ -408,27 +378,30 @@ impl FilterChainD3D12 {
source.format source.format
} else { } else {
ImageFormat::R8G8B8A8Unorm ImageFormat::R8G8B8A8Unorm
}.into(); }
.into();
eprintln!("building pipeline for pass {:?}", index); eprintln!("building pipeline for pass {:?}", index);
/// incredibly cursed. /// incredibly cursed.
let (reflection, graphics_pipeline) = if let Ok(graphics_pipeline) = let (reflection, graphics_pipeline) = if let Ok(graphics_pipeline) =
D3D12GraphicsPipeline::new_from_dxil(device, D3D12GraphicsPipeline::new_from_dxil(
&library, device,
&validator, &library,
&dxil, &validator,
root_signature, &dxil,
render_format root_signature,
render_format,
) { ) {
(dxil_reflection, graphics_pipeline) (dxil_reflection, graphics_pipeline)
} else { } else {
let graphics_pipeline = D3D12GraphicsPipeline::new_from_hlsl(device, let graphics_pipeline = D3D12GraphicsPipeline::new_from_hlsl(
&library, device,
&compiler, &library,
&hlsl, &compiler,
root_signature, &hlsl,
render_format root_signature,
render_format,
)?; )?;
(hlsl_reflection, graphics_pipeline) (hlsl_reflection, graphics_pipeline)
}; };
@ -460,18 +433,7 @@ impl FilterChainD3D12 {
None None
}; };
let mut uniform_bindings = FxHashMap::default(); let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
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);
}
let texture_heap = texture_heap.alloc_range()?; let texture_heap = texture_heap.alloc_range()?;
let sampler_heap = sampler_heap.alloc_range()?; let sampler_heap = sampler_heap.alloc_range()?;
@ -487,7 +449,6 @@ impl FilterChainD3D12 {
sampler_heap, sampler_heap,
source, source,
}) })
} }
Ok((texture_heap_handle, sampler_heap_handle, filters)) Ok((texture_heap_handle, sampler_heap_handle, filters))
@ -501,8 +462,7 @@ impl FilterChainD3D12 {
viewport: &Viewport<OutputTexture>, viewport: &Viewport<OutputTexture>,
frame_count: usize, frame_count: usize,
options: Option<&()>, options: Option<&()>,
) -> error::Result<()> ) -> error::Result<()> {
{
drop(self.residuals.drain(..)); drop(self.residuals.drain(..));
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled); let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
@ -521,9 +481,11 @@ impl FilterChainD3D12 {
.zip(self.feedback_framebuffers.iter()) .zip(self.feedback_framebuffers.iter())
.zip(passes.iter()) .zip(passes.iter())
{ {
*texture = Some(fbo.create_shader_resource_view(&mut self.staging_heap, *texture = Some(fbo.create_shader_resource_view(
pass.config.filter, &mut self.staging_heap,
pass.config.wrap_mode)?); pass.config.filter,
pass.config.wrap_mode,
)?);
} }
for (texture, fbo) in self for (texture, fbo) in self
@ -532,12 +494,10 @@ impl FilterChainD3D12 {
.iter_mut() .iter_mut()
.zip(self.history_framebuffers.iter()) .zip(self.history_framebuffers.iter())
{ {
*texture = Some(fbo.create_shader_resource_view(&mut self.staging_heap, *texture =
filter, Some(fbo.create_shader_resource_view(&mut self.staging_heap, filter, wrap_mode)?);
wrap_mode)?);
} }
let original = input; let original = input;
let mut source = unsafe { original.clone() }; let mut source = unsafe { original.clone() };
@ -576,33 +536,38 @@ impl FilterChainD3D12 {
// refresh inputs // refresh inputs
self.common.feedback_textures[index] = Some( self.common.feedback_textures[index] = Some(
self.feedback_framebuffers[index] self.feedback_framebuffers[index].create_shader_resource_view(
.create_shader_resource_view(&mut self.staging_heap, pass.config.filter, pass.config.wrap_mode)?, &mut self.staging_heap,
); pass.config.filter,
self.common.output_textures[index] = Some( pass.config.wrap_mode,
self.output_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 passes_len = passes.len();
let (pass, last) = passes.split_at_mut(passes_len - 1); let (pass, last) = passes.split_at_mut(passes_len - 1);
unsafe { unsafe {
let heaps = [self.texture_heap.clone(), self.sampler_heap.clone()]; let heaps = [self.texture_heap.clone(), self.sampler_heap.clone()];
cmd.SetDescriptorHeaps(&heaps); cmd.SetDescriptorHeaps(&heaps);
cmd.SetGraphicsRootSignature(&self.common.root_signature.handle); cmd.SetGraphicsRootSignature(&self.common.root_signature.handle);
} }
for (index, pass) in pass.iter_mut().enumerate() { for (index, pass) in pass.iter_mut().enumerate() {
source.filter = pass.config.filter; source.filter = pass.config.filter;
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
let target = &self.output_framebuffers[index]; let target = &self.output_framebuffers[index];
util::d3d12_resource_transition(&cmd, util::d3d12_resource_transition(
&target.handle, &cmd,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, &target.handle,
D3D12_RESOURCE_STATE_RENDER_TARGET); D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET,
);
let size = target.size; let size = target.size;
let view = target.create_render_target_view(&mut self.rtv_heap)?; let view = target.create_render_target_view(&mut self.rtv_heap)?;
@ -610,7 +575,10 @@ impl FilterChainD3D12 {
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
mvp: DEFAULT_MVP, mvp: DEFAULT_MVP,
output: OutputTexture { descriptor: view.descriptor, size }, output: OutputTexture {
descriptor: view.descriptor,
size,
},
}; };
pass.draw( pass.draw(
@ -627,13 +595,15 @@ impl FilterChainD3D12 {
&original, &original,
&source, &source,
&out, &out,
QuadType::Offscreen QuadType::Offscreen,
)?; )?;
util::d3d12_resource_transition(&cmd, util::d3d12_resource_transition(
&target.handle, &cmd,
D3D12_RESOURCE_STATE_RENDER_TARGET, &target.handle,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
);
// let target_handle = target.create_shader_resource_view( // let target_handle = target.create_shader_resource_view(
// &mut self.staging_heap, // &mut self.staging_heap,
// pass.config.filter, // pass.config.filter,
@ -670,12 +640,11 @@ impl FilterChainD3D12 {
&original, &original,
&source, &source,
&out, &out,
QuadType::Final QuadType::Final,
)?; )?;
} }
// todo: history // todo: history
Ok(()) Ok(())
} }
} }

View file

@ -17,11 +17,12 @@ use librashader_reflect::back::targets::GLSL;
use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::back::{CompileReflectShader, CompileShader};
use librashader_reflect::front::GlslangCompilation; use librashader_reflect::front::GlslangCompilation;
use librashader_reflect::reflect::semantics::{ use librashader_reflect::reflect::semantics::{
ShaderSemantics, TextureSemantics, UniformBinding, UniformMeta, BindingMeta, ShaderSemantics, TextureSemantics, UniformBinding, UniformMeta,
}; };
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_reflect::reflect::ReflectShader; use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::binding::BindingUtil;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use spirv_cross::spirv::Decoration; use spirv_cross::spirv::Decoration;
use std::collections::VecDeque; use std::collections::VecDeque;
@ -52,7 +53,7 @@ pub struct FilterMutable {
} }
impl<T: GLInterface> FilterChainImpl<T> { impl<T: GLInterface> FilterChainImpl<T> {
fn reflect_uniform_location(pipeline: GLuint, meta: &impl UniformMeta) -> VariableLocation { fn reflect_uniform_location(pipeline: GLuint, meta: &dyn UniformMeta) -> VariableLocation {
let mut location = VariableLocation { let mut location = VariableLocation {
ubo: None, ubo: None,
push: None, push: None,
@ -251,45 +252,12 @@ impl<T: GLInterface> FilterChainImpl<T> {
.unwrap_or(0), .unwrap_or(0),
); );
let mut uniform_bindings = FxHashMap::default(); let uniform_bindings = reflection.meta.create_binding_map(|param| {
for param in reflection.meta.parameter_meta.values() { UniformOffset::new(
uniform_bindings.insert( Self::reflect_uniform_location(program, param),
UniformBinding::Parameter(param.id.clone()), param.offset(),
UniformOffset::new( )
Self::reflect_uniform_location(program, param), });
param.offset,
),
);
}
for (semantics, param) in &reflection.meta.unique_meta {
uniform_bindings.insert(
UniformBinding::SemanticVariable(*semantics),
UniformOffset::new(
Self::reflect_uniform_location(program, param),
param.offset,
),
);
}
for (semantics, param) in &reflection.meta.texture_size_meta {
uniform_bindings.insert(
UniformBinding::TextureSize(*semantics),
UniformOffset::new(
Self::reflect_uniform_location(program, param),
param.offset,
),
);
}
// eprintln!("{:#?}", reflection.meta.texture_meta);
// eprintln!("{:#?}", reflection.meta);
// eprintln!("{:#?}", locations);
// eprintln!("{:#?}", reflection.push_constant);
// eprintln!("====fragment====");
// eprintln!("{:#}", glsl.fragment);
// eprintln!("====vertex====");
// eprintln!("{:#}", glsl.vertex);
filters.push(FilterPass { filters.push(FilterPass {
reflection, reflection,
@ -312,28 +280,8 @@ impl<T: GLInterface> FilterChainImpl<T> {
filter: FilterMode, filter: FilterMode,
wrap_mode: WrapMode, wrap_mode: WrapMode,
) -> (VecDeque<Framebuffer>, Box<[InputTexture]>) { ) -> (VecDeque<Framebuffer>, Box<[InputTexture]>) {
let mut required_images = 0; let mut required_images =
BindingMeta::calculate_required_history(filters.iter().map(|f| &f.reflection.meta));
for pass in filters {
// If a shader uses history size, but not history, we still need to keep the texture.
let texture_count = pass
.reflection
.meta
.texture_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
let texture_size_count = pass
.reflection
.meta
.texture_size_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
required_images = std::cmp::max(required_images, texture_count);
required_images = std::cmp::max(required_images, texture_size_count);
}
// not using frame history; // not using frame history;
if required_images <= 1 { if required_images <= 1 {

View file

@ -20,15 +20,18 @@ use librashader_reflect::back::targets::SPIRV;
use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::back::{CompileReflectShader, CompileShader};
use librashader_reflect::front::GlslangCompilation; use librashader_reflect::front::GlslangCompilation;
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_reflect::reflect::semantics::{ShaderSemantics, TextureSemantics, UniformBinding}; use librashader_reflect::reflect::semantics::{
BindingMeta, ShaderSemantics, TextureSemantics, UniformBinding,
};
use librashader_reflect::reflect::ReflectShader; use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::binding::BindingUtil;
use librashader_runtime::image::{Image, UVDirection}; use librashader_runtime::image::{Image, UVDirection};
use librashader_runtime::quad::{QuadType, DEFAULT_MVP, IDENTITY_MVP};
use librashader_runtime::uniforms::UniformStorage; use librashader_runtime::uniforms::UniformStorage;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use librashader_runtime::quad::{DEFAULT_MVP, IDENTITY_MVP, QuadType};
/// A Vulkan device and metadata that is required by the shader runtime. /// A Vulkan device and metadata that is required by the shader runtime.
pub struct VulkanObjects { pub struct VulkanObjects {
@ -238,9 +241,7 @@ impl FilterChainVulkan {
passes, passes,
&semantics, &semantics,
frames_in_flight, frames_in_flight,
options options.map(|o| o.use_render_pass).unwrap_or(false),
.map(|o| o.use_render_pass)
.unwrap_or(false),
)?; )?;
let luts = FilterChainVulkan::load_luts(&device, &preset.textures)?; let luts = FilterChainVulkan::load_luts(&device, &preset.textures)?;
@ -336,19 +337,7 @@ impl FilterChainVulkan {
.unwrap_or(0), .unwrap_or(0),
); );
let mut uniform_bindings = FxHashMap::default(); let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
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);
}
let render_pass_format = if !use_render_pass { let render_pass_format = if !use_render_pass {
vk::Format::UNDEFINED vk::Format::UNDEFINED
@ -456,28 +445,8 @@ impl FilterChainVulkan {
vulkan: &VulkanObjects, vulkan: &VulkanObjects,
filters: &[FilterPass], filters: &[FilterPass],
) -> error::Result<(VecDeque<OwnedImage>, Box<[Option<InputImage>]>)> { ) -> error::Result<(VecDeque<OwnedImage>, Box<[Option<InputImage>]>)> {
let mut required_images = 0; let mut required_images =
BindingMeta::calculate_required_history(filters.iter().map(|f| &f.reflection.meta));
for pass in filters {
// If a shader uses history size, but not history, we still need to keep the texture.
let texture_count = pass
.reflection
.meta
.texture_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
let texture_size_count = pass
.reflection
.meta
.texture_size_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
required_images = std::cmp::max(required_images, texture_count);
required_images = std::cmp::max(required_images, texture_size_count);
}
// not using frame history; // not using frame history;
if required_images <= 1 { if required_images <= 1 {
@ -738,7 +707,7 @@ impl FilterChainVulkan {
&original, &original,
&source, &source,
&out, &out,
QuadType::Offscreen QuadType::Offscreen,
)?; )?;
if target.max_miplevels > 1 && !self.disable_mipmaps { if target.max_miplevels > 1 && !self.disable_mipmaps {
@ -776,7 +745,7 @@ impl FilterChainVulkan {
&original, &original,
&source, &source,
&out, &out,
QuadType::Final QuadType::Final,
)?; )?;
intermediates.dispose_outputs(out.output); intermediates.dispose_outputs(out.output);

View file

@ -2,8 +2,10 @@ use crate::uniforms::{BindUniform, NoUniformBinder, UniformStorage};
use librashader_common::Size; use librashader_common::Size;
use librashader_preprocess::ShaderParameter; use librashader_preprocess::ShaderParameter;
use librashader_reflect::reflect::semantics::{ use librashader_reflect::reflect::semantics::{
MemberOffset, Semantic, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics, BindingMeta, MemberOffset, Semantic, TextureBinding, TextureSemantics, UniformBinding,
UniformMeta, UniqueSemantics,
}; };
use rustc_hash::FxHashMap;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::BuildHasher; use std::hash::BuildHasher;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
@ -266,3 +268,65 @@ where
} }
} }
} }
/// Trait for objects that can be used to create a binding map.
pub trait BindingUtil {
/// Create the uniform binding map with the given reflection information.
fn create_binding_map<T>(
&self,
f: impl Fn(&dyn UniformMeta) -> T,
) -> FxHashMap<UniformBinding, T>;
/// Calculate the number of required images for history.
fn calculate_required_history<'a>(pass_meta: impl Iterator<Item = &'a Self>) -> usize
where
Self: 'a;
}
impl BindingUtil for BindingMeta {
fn create_binding_map<T>(
&self,
f: impl Fn(&dyn UniformMeta) -> T,
) -> FxHashMap<UniformBinding, T> {
let mut uniform_bindings = FxHashMap::default();
for param in self.parameter_meta.values() {
uniform_bindings.insert(UniformBinding::Parameter(param.id.clone()), f(param));
}
for (semantics, param) in &self.unique_meta {
uniform_bindings.insert(UniformBinding::SemanticVariable(*semantics), f(param));
}
for (semantics, param) in &self.texture_size_meta {
uniform_bindings.insert(UniformBinding::TextureSize(*semantics), f(param));
}
uniform_bindings
}
fn calculate_required_history<'a>(pass_meta: impl Iterator<Item = &'a Self>) -> usize
where
Self: 'a,
{
let mut required_images = 0;
for pass in pass_meta {
// If a shader uses history size, but not history, we still need to keep the texture.
let texture_count = pass
.texture_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
let texture_size_count = pass
.texture_size_meta
.iter()
.filter(|(semantics, _)| semantics.semantics == TextureSemantics::OriginalHistory)
.count();
required_images = std::cmp::max(required_images, texture_count);
required_images = std::cmp::max(required_images, texture_size_count);
}
required_images
}
}