rt: abstract reusable bindingmeta ops
This commit is contained in:
parent
4e9cc26093
commit
7d8c137083
5 changed files with 254 additions and 333 deletions
|
@ -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,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue