rt(vk): draw final pass to output targets
This commit is contained in:
parent
336f540ce9
commit
666588ef0d
|
@ -518,6 +518,7 @@ impl FilterChainD3D11 {
|
|||
QuadType::Final,
|
||||
)?;
|
||||
|
||||
|
||||
pass.draw(
|
||||
&ctx,
|
||||
index,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}),
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue