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,
)?;
pass.draw(
&ctx,
index,

View file

@ -10,9 +10,9 @@ fn triangle_d3d12() {
// "../test/basic.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/shaders_slang/test/feedback.slangp",
// "../test/shaders_slang/test/feedback.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",
&SampleCommandLine {
use_warp_device: false,

View file

@ -678,6 +678,7 @@ impl FilterChainVulkan {
let residual_fb = pass.draw(
cmd,
target.image.format,
index,
&self.common,
pass.config.get_frame_count(frame_count),
@ -687,6 +688,7 @@ impl FilterChainVulkan {
&source,
&out,
QuadType::Offscreen,
false,
)?;
if target.max_miplevels > 1 && !self.disable_mipmaps {
@ -703,12 +705,12 @@ impl FilterChainVulkan {
// try to hint the optimizer
assert_eq!(last.len(), 1);
if let Some(pass) = last.iter_mut().next() {
if let Some(format) = pass
let index = passes_len - 1;
if pass
.graphics_pipeline
.render_pass
.as_ref()
.map(|r| r.format)
&& format != viewport.output.format
.render_passes
.get(&viewport.output.format)
.is_none()
{
// need to recompile
pass.graphics_pipeline.recompile(viewport.output.format)?;
@ -718,12 +720,15 @@ impl FilterChainVulkan {
source.wrap_mode = pass.config.wrap_mode;
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 residual_fb = pass.draw(
cmd,
passes_len - 1,
target.image.format,
index,
&self.common,
pass.config.get_frame_count(frame_count),
options,
@ -732,6 +737,28 @@ impl FilterChainVulkan {
&source,
&out,
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);

View file

@ -87,6 +87,7 @@ impl FilterPass {
pub(crate) fn draw(
&mut self,
cmd: vk::CommandBuffer,
format: vk::Format,
pass_index: usize,
parent: &FilterCommon,
frame_count: u32,
@ -96,9 +97,15 @@ impl FilterPass {
source: &InputImage,
output: &RenderTarget<OutputImage>,
vbo_type: QuadType,
use_alt_descriptors: bool,
) -> error::Result<Option<vk::Framebuffer>> {
let mut descriptor = self.graphics_pipeline.layout.descriptor_sets
[parent.internal_frame_count % self.frames_in_flight as usize];
let mut descriptor = if use_alt_descriptors {
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(
pass_index,
@ -113,6 +120,15 @@ impl FilterPass {
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 {
self.uniform_storage.inner_ubo().bind_to_descriptor_set(
descriptor,
@ -123,14 +139,14 @@ impl FilterPass {
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 {
parent.device.cmd_bind_pipeline(
cmd,
vk::PipelineBindPoint::GRAPHICS,
self.graphics_pipeline.pipeline,
);
parent
.device
.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, *pipeline);
parent.device.cmd_bind_descriptor_sets(
cmd,

View file

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

View file

@ -6,7 +6,7 @@ use ash::vk::{
pub struct VulkanRenderPass {
pub handle: vk::RenderPass,
pub format: vk::Format,
pub _format: vk::Format,
}
impl VulkanRenderPass {
@ -38,7 +38,10 @@ impl VulkanRenderPass {
unsafe {
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 {
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",
&base,
// "../test/slang-shaders/test/feedback.slancargogp",
// "../test/basic.slangp",
Some(&FilterChainOptionsVulkan {
frames_in_flight: 3,
force_no_mipmaps: false,
use_dynamic_rendering: true,
use_dynamic_rendering: false,
disable_cache: true,
}),
)