rt(vk): draw final pass to output targets

This commit is contained in:
chyyran 2024-09-11 23:44:33 -04:00 committed by Ronny Chan
parent 336f540ce9
commit 666588ef0d
7 changed files with 113 additions and 40 deletions

View file

@ -518,6 +518,7 @@ impl FilterChainD3D11 {
QuadType::Final, QuadType::Final,
)?; )?;
pass.draw( pass.draw(
&ctx, &ctx,
index, index,

View file

@ -10,9 +10,9 @@ fn triangle_d3d12() {
// "../test/basic.slangp", // "../test/basic.slangp",
// "../test/shaders_slang/handheld/console-border/gbc-lcd-grid-v2.slangp", // "../test/shaders_slang/handheld/console-border/gbc-lcd-grid-v2.slangp",
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp", // "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp",
"../test/shaders_slang/test/feedback.slangp", // "../test/shaders_slang/test/feedback.slangp",
// "../test/shaders_slang/test/history.slangp", // "../test/shaders_slang/test/history.slangp",
// "../test/shaders_slang/crt/crt-royale.slangp", "../test/shaders_slang/crt/crt-geom-deluxe.slangp",
// "../test/slang-shaders/vhs/VHSPro.slangp", // "../test/slang-shaders/vhs/VHSPro.slangp",
&SampleCommandLine { &SampleCommandLine {
use_warp_device: false, use_warp_device: false,

View file

@ -678,6 +678,7 @@ impl FilterChainVulkan {
let residual_fb = pass.draw( let residual_fb = pass.draw(
cmd, cmd,
target.image.format,
index, index,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
@ -687,6 +688,7 @@ impl FilterChainVulkan {
&source, &source,
&out, &out,
QuadType::Offscreen, QuadType::Offscreen,
false,
)?; )?;
if target.max_miplevels > 1 && !self.disable_mipmaps { if target.max_miplevels > 1 && !self.disable_mipmaps {
@ -703,12 +705,12 @@ impl FilterChainVulkan {
// try to hint the optimizer // try to hint the optimizer
assert_eq!(last.len(), 1); assert_eq!(last.len(), 1);
if let Some(pass) = last.iter_mut().next() { if let Some(pass) = last.iter_mut().next() {
if let Some(format) = pass let index = passes_len - 1;
if pass
.graphics_pipeline .graphics_pipeline
.render_pass .render_passes
.as_ref() .get(&viewport.output.format)
.map(|r| r.format) .is_none()
&& format != viewport.output.format
{ {
// need to recompile // need to recompile
pass.graphics_pipeline.recompile(viewport.output.format)?; pass.graphics_pipeline.recompile(viewport.output.format)?;
@ -718,12 +720,15 @@ impl FilterChainVulkan {
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
source.mip_filter = pass.config.filter; source.mip_filter = pass.config.filter;
let output_image = OutputImage::new(&self.vulkan.device, viewport.output.clone())?; let target = &self.output_framebuffers[index];
let output_image = OutputImage::new(&self.vulkan.device, target.image.clone())?;
let out = RenderTarget::viewport_with_output(&output_image, viewport); let out = RenderTarget::viewport_with_output(&output_image, viewport);
let residual_fb = pass.draw( let residual_fb = pass.draw(
cmd, cmd,
passes_len - 1, target.image.format,
index,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
options, options,
@ -732,6 +737,28 @@ impl FilterChainVulkan {
&source, &source,
&out, &out,
QuadType::Final, QuadType::Final,
true,
)?;
out.output.end_pass(&self.vulkan.device, cmd);
intermediates.dispose_outputs(output_image);
intermediates.dispose_framebuffers(residual_fb);
let output_image = OutputImage::new(&self.vulkan.device, viewport.output.clone())?;
let out = RenderTarget::viewport_with_output(&output_image, viewport);
let residual_fb = pass.draw(
cmd,
viewport.output.format,
index,
&self.common,
pass.config.get_frame_count(frame_count),
options,
viewport,
&original,
&source,
&out,
QuadType::Final,
false,
)?; )?;
intermediates.dispose_outputs(output_image); intermediates.dispose_outputs(output_image);

View file

@ -87,6 +87,7 @@ impl FilterPass {
pub(crate) fn draw( pub(crate) fn draw(
&mut self, &mut self,
cmd: vk::CommandBuffer, cmd: vk::CommandBuffer,
format: vk::Format,
pass_index: usize, pass_index: usize,
parent: &FilterCommon, parent: &FilterCommon,
frame_count: u32, frame_count: u32,
@ -96,9 +97,15 @@ impl FilterPass {
source: &InputImage, source: &InputImage,
output: &RenderTarget<OutputImage>, output: &RenderTarget<OutputImage>,
vbo_type: QuadType, vbo_type: QuadType,
use_alt_descriptors: bool,
) -> error::Result<Option<vk::Framebuffer>> { ) -> error::Result<Option<vk::Framebuffer>> {
let mut descriptor = self.graphics_pipeline.layout.descriptor_sets let mut descriptor = if use_alt_descriptors {
[parent.internal_frame_count % self.frames_in_flight as usize]; self.graphics_pipeline.layout.descriptor_sets_alt
[parent.internal_frame_count % self.frames_in_flight as usize]
} else {
self.graphics_pipeline.layout.descriptor_sets
[parent.internal_frame_count % self.frames_in_flight as usize]
};
self.build_semantics( self.build_semantics(
pass_index, pass_index,
@ -113,6 +120,15 @@ impl FilterPass {
source, source,
); );
let Some(pipeline) = self
.graphics_pipeline
.pipelines
.get(&format)
.or_else(|| self.graphics_pipeline.pipelines.values().next())
else {
panic!("No available render pipelines found")
};
if let Some(ubo) = &self.reflection.ubo { if let Some(ubo) = &self.reflection.ubo {
self.uniform_storage.inner_ubo().bind_to_descriptor_set( self.uniform_storage.inner_ubo().bind_to_descriptor_set(
descriptor, descriptor,
@ -123,14 +139,14 @@ impl FilterPass {
output.output.begin_pass(&parent.device, cmd); output.output.begin_pass(&parent.device, cmd);
let residual = self.graphics_pipeline.begin_rendering(output, cmd)?; let residual = self
.graphics_pipeline
.begin_rendering(output, format, cmd)?;
unsafe { unsafe {
parent.device.cmd_bind_pipeline( parent
cmd, .device
vk::PipelineBindPoint::GRAPHICS, .cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, *pipeline);
self.graphics_pipeline.pipeline,
);
parent.device.cmd_bind_descriptor_sets( parent.device.cmd_bind_descriptor_sets(
cmd, cmd,

View file

@ -7,6 +7,7 @@ use crate::render_pass::VulkanRenderPass;
use ash::vk::PushConstantRange; use ash::vk::PushConstantRange;
use bytemuck::offset_of; use bytemuck::offset_of;
use librashader_cache::cache_pipeline; use librashader_cache::cache_pipeline;
use librashader_common::map::FastHashMap;
use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::semantics::{BufferReflection, TextureBinding}; use librashader_reflect::reflect::semantics::{BufferReflection, TextureBinding};
use librashader_reflect::reflect::ShaderReflection; use librashader_reflect::reflect::ShaderReflection;
@ -14,6 +15,7 @@ use librashader_runtime::quad::VertexInput;
use librashader_runtime::render_target::RenderTarget; use librashader_runtime::render_target::RenderTarget;
use std::ffi::CStr; use std::ffi::CStr;
use std::sync::Arc; use std::sync::Arc;
const ENTRY_POINT: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"main\0") }; const ENTRY_POINT: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"main\0") };
pub struct PipelineDescriptors<'a> { pub struct PipelineDescriptors<'a> {
@ -93,6 +95,8 @@ impl PipelineDescriptors<'_> {
pub struct PipelineLayoutObjects { pub struct PipelineLayoutObjects {
pub layout: vk::PipelineLayout, pub layout: vk::PipelineLayout,
pub descriptor_sets: Vec<vk::DescriptorSet>, pub descriptor_sets: Vec<vk::DescriptorSet>,
pub descriptor_sets_alt: Vec<vk::DescriptorSet>,
pub _pool: vk::DescriptorPool, pub _pool: vk::DescriptorPool,
pub _descriptor_set_layout: [vk::DescriptorSetLayout; 1], pub _descriptor_set_layout: [vk::DescriptorSetLayout; 1],
} }
@ -127,7 +131,7 @@ impl PipelineLayoutObjects {
let layout = unsafe { device.create_pipeline_layout(&pipeline_create_info, None)? }; let layout = unsafe { device.create_pipeline_layout(&pipeline_create_info, None)? };
let pool_info = vk::DescriptorPoolCreateInfo::default() let pool_info = vk::DescriptorPoolCreateInfo::default()
.max_sets(replicas) .max_sets(replicas * 2)
.pool_sizes(&descriptors.pool_sizes); .pool_sizes(&descriptors.pool_sizes);
let pool = unsafe { device.create_descriptor_pool(&pool_info, None)? }; let pool = unsafe { device.create_descriptor_pool(&pool_info, None)? };
@ -145,10 +149,24 @@ impl PipelineLayoutObjects {
let descriptor_sets: Vec<vk::DescriptorSet> = let descriptor_sets: Vec<vk::DescriptorSet> =
descriptor_sets.into_iter().flatten().collect(); descriptor_sets.into_iter().flatten().collect();
let mut descriptor_sets_alt = Vec::new();
let alloc_info = vk::DescriptorSetAllocateInfo::default()
.descriptor_pool(pool)
.set_layouts(&descriptor_set_layout);
for _ in 0..replicas {
let set = unsafe { device.allocate_descriptor_sets(&alloc_info)? };
descriptor_sets_alt.push(set)
}
let descriptor_sets_alt: Vec<vk::DescriptorSet> =
descriptor_sets_alt.into_iter().flatten().collect();
Ok(PipelineLayoutObjects { Ok(PipelineLayoutObjects {
layout, layout,
_descriptor_set_layout: descriptor_set_layout, _descriptor_set_layout: descriptor_set_layout,
descriptor_sets, descriptor_sets,
descriptor_sets_alt,
_pool: pool, _pool: pool,
}) })
} }
@ -179,12 +197,13 @@ impl Drop for VulkanShaderModule {
pub struct VulkanGraphicsPipeline { pub struct VulkanGraphicsPipeline {
pub layout: PipelineLayoutObjects, pub layout: PipelineLayoutObjects,
pub pipeline: vk::Pipeline, pub pipelines: FastHashMap<vk::Format, vk::Pipeline>,
pub render_pass: Option<VulkanRenderPass>, pub render_passes: FastHashMap<vk::Format, Option<VulkanRenderPass>>,
device: Arc<ash::Device>, device: Arc<ash::Device>,
vertex: VulkanShaderModule, vertex: VulkanShaderModule,
fragment: VulkanShaderModule, fragment: VulkanShaderModule,
cache: vk::PipelineCache, cache: vk::PipelineCache,
use_render_pass: bool,
} }
impl VulkanGraphicsPipeline { impl VulkanGraphicsPipeline {
@ -315,11 +334,13 @@ impl VulkanGraphicsPipeline {
let fragment_module = VulkanShaderModule::new(device, &fragment_info)?; let fragment_module = VulkanShaderModule::new(device, &fragment_info)?;
let mut render_pass = None; let mut render_pass = None;
let mut use_render_pass = false;
if render_pass_format != vk::Format::UNDEFINED { if render_pass_format != vk::Format::UNDEFINED {
render_pass = Some(VulkanRenderPass::create_render_pass( render_pass = Some(VulkanRenderPass::create_render_pass(
device, device,
render_pass_format, render_pass_format,
)?); )?);
use_render_pass = true;
} }
let (pipeline, pipeline_cache) = cache_pipeline( let (pipeline, pipeline_cache) = cache_pipeline(
@ -348,25 +369,32 @@ impl VulkanGraphicsPipeline {
bypass_cache, bypass_cache,
)?; )?;
let mut pipelines = FastHashMap::default();
let mut render_passes = FastHashMap::default();
pipelines.insert(render_pass_format, pipeline);
render_passes.insert(render_pass_format, render_pass);
Ok(VulkanGraphicsPipeline { Ok(VulkanGraphicsPipeline {
device: Arc::clone(device), device: Arc::clone(device),
layout: pipeline_layout, layout: pipeline_layout,
pipeline, pipelines,
render_pass, render_passes,
vertex: vertex_module, vertex: vertex_module,
fragment: fragment_module, fragment: fragment_module,
cache: pipeline_cache, cache: pipeline_cache,
use_render_pass,
}) })
} }
pub(crate) fn recompile(&mut self, format: vk::Format) -> error::Result<()> { pub(crate) fn recompile(&mut self, format: vk::Format) -> error::Result<()> {
let mut new_renderpass = if self.render_pass.is_some() { let new_renderpass = if self.use_render_pass {
Some(VulkanRenderPass::create_render_pass(&self.device, format)?) Some(VulkanRenderPass::create_render_pass(&self.device, format)?)
} else { } else {
None None
}; };
let mut new_pipeline = Self::create_pipeline( let new_pipeline = Self::create_pipeline(
&self.device, &self.device,
&self.cache, &self.cache,
&self.layout, &self.layout,
@ -375,23 +403,19 @@ impl VulkanGraphicsPipeline {
new_renderpass.as_ref(), new_renderpass.as_ref(),
)?; )?;
std::mem::swap(&mut self.render_pass, &mut new_renderpass); self.render_passes.insert(format, new_renderpass);
std::mem::swap(&mut self.pipeline, &mut new_pipeline); self.pipelines.insert(format, new_pipeline);
unsafe {
if new_pipeline != vk::Pipeline::null() {
self.device.destroy_pipeline(new_pipeline, None)
}
}
Ok(()) Ok(())
} }
#[inline(always)] #[inline(always)]
pub(crate) fn begin_rendering( pub(crate) fn begin_rendering(
&self, &self,
output: &RenderTarget<OutputImage>, output: &RenderTarget<OutputImage>,
format: vk::Format,
cmd: vk::CommandBuffer, cmd: vk::CommandBuffer,
) -> error::Result<Option<vk::Framebuffer>> { ) -> error::Result<Option<vk::Framebuffer>> {
if let Some(render_pass) = &self.render_pass { if let Some(Some(render_pass)) = &self.render_passes.get(&format) {
let attachments = [output.output.image_view]; let attachments = [output.output.image_view];
let framebuffer = unsafe { let framebuffer = unsafe {
self.device.create_framebuffer( self.device.create_framebuffer(
@ -452,7 +476,7 @@ impl VulkanGraphicsPipeline {
pub(crate) fn end_rendering(&self, cmd: vk::CommandBuffer) { pub(crate) fn end_rendering(&self, cmd: vk::CommandBuffer) {
unsafe { unsafe {
if self.render_pass.is_none() { if !self.use_render_pass {
self.device.cmd_end_rendering(cmd); self.device.cmd_end_rendering(cmd);
} else { } else {
self.device.cmd_end_render_pass(cmd) self.device.cmd_end_render_pass(cmd)
@ -464,8 +488,10 @@ impl VulkanGraphicsPipeline {
impl Drop for VulkanGraphicsPipeline { impl Drop for VulkanGraphicsPipeline {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if self.pipeline != vk::Pipeline::null() { for (_, pipeline) in self.pipelines.iter_mut() {
self.device.destroy_pipeline(self.pipeline, None) if *pipeline != vk::Pipeline::null() {
self.device.destroy_pipeline(*pipeline, None)
}
} }
if self.cache != vk::PipelineCache::null() { if self.cache != vk::PipelineCache::null() {

View file

@ -6,7 +6,7 @@ use ash::vk::{
pub struct VulkanRenderPass { pub struct VulkanRenderPass {
pub handle: vk::RenderPass, pub handle: vk::RenderPass,
pub format: vk::Format, pub _format: vk::Format,
} }
impl VulkanRenderPass { impl VulkanRenderPass {
@ -38,7 +38,10 @@ impl VulkanRenderPass {
unsafe { unsafe {
let rp = device.create_render_pass(&renderpass_info, None)?; let rp = device.create_render_pass(&renderpass_info, None)?;
Ok(Self { handle: rp, format }) Ok(Self {
handle: rp,
_format: format,
})
} }
} }
} }

View file

@ -11,15 +11,15 @@ fn triangle_vk() {
unsafe { unsafe {
let filter = FilterChainVulkan::load_from_path( let filter = FilterChainVulkan::load_from_path(
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", "../test/shaders_slang/test/feedback.slangp",
// "../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp", // "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp",
&base, &base,
// "../test/slang-shaders/test/feedback.slancargogp",
// "../test/basic.slangp", // "../test/basic.slangp",
Some(&FilterChainOptionsVulkan { Some(&FilterChainOptionsVulkan {
frames_in_flight: 3, frames_in_flight: 3,
force_no_mipmaps: false, force_no_mipmaps: false,
use_dynamic_rendering: true, use_dynamic_rendering: false,
disable_cache: true, disable_cache: true,
}), }),
) )