From 857e9945702a1fcccfddf84cb4dd75e8ae4297aa Mon Sep 17 00:00:00 2001 From: chyyran Date: Wed, 11 Jan 2023 23:05:08 -0500 Subject: [PATCH] vk: implement feedback framebuffers --- librashader-runtime-vk/src/filter_chain.rs | 83 ++++++++++++--------- librashader-runtime-vk/src/filter_pass.rs | 69 +++++++++-------- librashader-runtime-vk/src/framebuffer.rs | 8 +- librashader-runtime-vk/src/luts.rs | 6 +- librashader-runtime-vk/src/render_target.rs | 4 +- librashader-runtime-vk/src/texture.rs | 55 ++++---------- 6 files changed, 102 insertions(+), 123 deletions(-) diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index 52f59d7..a451906 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -2,7 +2,7 @@ use crate::{error, util}; use crate::filter_pass::FilterPass; use crate::luts::LutTexture; use crate::samplers::SamplerSet; -use crate::texture::{OwnedTexture, InputTexture, VulkanImage}; +use crate::texture::{OwnedImage, InputImage, VulkanImage}; use crate::ubo_ring::VkUboRing; use crate::vulkan_state::VulkanGraphicsPipeline; use ash::vk::{CommandPoolCreateFlags, PFN_vkGetInstanceProcAddr, Queue, StaticFn}; @@ -23,7 +23,7 @@ use rustc_hash::FxHashMap; use std::error::Error; use std::path::Path; use crate::draw_quad::DrawQuad; -use crate::framebuffer::OutputFramebuffer; +use crate::framebuffer::OutputImage; use crate::render_target::{DEFAULT_MVP, RenderTarget}; use crate::viewport::Viewport; @@ -128,8 +128,8 @@ pub struct FilterChainVulkan { pub(crate) common: FilterCommon, pub(crate) passes: Box<[FilterPass]>, pub(crate) vulkan: Vulkan, - pub(crate) output_framebuffers: Box<[OwnedTexture]>, - // pub(crate) feedback_framebuffers: Box<[OwnedFramebuffer]>, + pub(crate) output_framebuffers: Box<[OwnedImage]>, + pub(crate) feedback_framebuffers: Box<[OwnedImage]>, // pub(crate) history_framebuffers: VecDeque, } @@ -143,8 +143,8 @@ pub(crate) struct FilterCommon { pub samplers: SamplerSet, pub(crate) draw_quad: DrawQuad, - pub output_textures: Box<[Option]>, - // pub feedback_textures: Box<[Option]>, + pub output_textures: Box<[Option]>, + pub feedback_textures: Box<[Option]>, // pub history_textures: Box<[Option]>, pub config: FilterMutable, pub device: ash::Device, @@ -153,7 +153,6 @@ pub(crate) struct FilterCommon { #[must_use] pub struct FilterChainFrameIntermediates { device: ash::Device, - framebuffers: Vec, image_views: Vec } @@ -161,24 +160,15 @@ impl FilterChainFrameIntermediates { pub(crate) fn new(device: &ash::Device) -> Self { FilterChainFrameIntermediates { device: device.clone(), - framebuffers: Vec::new(), image_views: Vec::new(), } } - pub(crate) fn dispose_input(&mut self, input_texture_texture: InputTexture) { - self.image_views.push(input_texture_texture.image_view); - } - - pub(crate) fn dispose_outputs(&mut self, output_framebuffer: OutputFramebuffer) { + pub(crate) fn dispose_outputs(&mut self, output_framebuffer: OutputImage) { // self.framebuffers.push(output_framebuffer.framebuffer); self.image_views.push(output_framebuffer.image_view); } - pub(crate) fn dispose_framebuffer(&mut self, framebuffer: vk::Framebuffer) { - self.framebuffers.push(framebuffer) - } - pub(crate) fn dispose_image_views(&mut self, image_view: vk::ImageView) { self.image_views.push(image_view) } @@ -186,14 +176,6 @@ impl FilterChainFrameIntermediates { impl Drop for FilterChainFrameIntermediates { fn drop(&mut self) { - for framebuffer in &self.framebuffers { - if *framebuffer != vk::Framebuffer::null() { - unsafe { - self.device.destroy_framebuffer(*framebuffer, None); - } - } - } - for image_view in &self.image_views { if *image_view != vk::ImageView::null() { unsafe { @@ -234,7 +216,7 @@ impl FilterChainVulkan { let mut output_framebuffers = Vec::new(); output_framebuffers.resize_with(filters.len(), || { - OwnedTexture::new( + OwnedImage::new( &device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, @@ -242,9 +224,24 @@ impl FilterChainVulkan { ) }); - let output_framebuffers: error::Result> = output_framebuffers.into_iter().collect(); + let mut feedback_framebuffers = Vec::new(); + feedback_framebuffers.resize_with(filters.len(), || { + OwnedImage::new( + &device, + Size::new(1, 1), + ImageFormat::R8G8B8A8Unorm, + 1 + ) + }); + + let output_framebuffers: error::Result> = output_framebuffers.into_iter().collect(); let mut output_textures = Vec::new(); output_textures.resize_with(filters.len(), || None); + + let feedback_framebuffers: error::Result> = feedback_framebuffers.into_iter().collect(); + let mut feedback_textures = Vec::new(); + feedback_textures.resize_with(filters.len(), || None); + eprintln!("filters initialized ok."); Ok(FilterChainVulkan { common: FilterCommon { @@ -260,11 +257,13 @@ impl FilterChainVulkan { }, draw_quad: DrawQuad::new(&device.device, &device.memory_properties)?, device: device.device.clone(), - output_textures: output_textures.into_boxed_slice() + output_textures: output_textures.into_boxed_slice(), + feedback_textures: feedback_textures.into_boxed_slice() }, passes: filters, vulkan: device, output_framebuffers: output_framebuffers?.into_boxed_slice(), + feedback_framebuffers: feedback_framebuffers?.into_boxed_slice(), }) } @@ -491,7 +490,7 @@ impl FilterChainVulkan { let filter = passes[0].config.filter; let wrap_mode = passes[0].config.wrap_mode; - let original = InputTexture { + let original = InputImage { image: input.clone(), image_view: original_image_view, wrap_mode, @@ -512,6 +511,16 @@ impl FilterChainVulkan { // todo: need to check **next** pass.config.mipmap_input )?; + + self.feedback_framebuffers[index].scale( + pass.config.scaling.clone(), + pass.get_format(), + &viewport.output.size, + &original, + &source, + // todo: need to check **next** + pass.config.mipmap_input + )?; } @@ -527,7 +536,7 @@ impl FilterChainVulkan { x: 0.0, y: 0.0, mvp: DEFAULT_MVP, - output: OutputFramebuffer::new(&self.vulkan, /*&pass.graphics_pipeline.render_pass,*/ + output: OutputImage::new(&self.vulkan, /*&pass.graphics_pipeline.render_pass,*/ target.image.clone())?, }; @@ -541,12 +550,8 @@ impl FilterChainVulkan { } source = target.as_input(pass.config.filter, pass.config.wrap_mode)?; - let prev_frame_output = self.common - .output_textures[index].replace(source.clone()); - if let Some(prev_frame_output) = prev_frame_output { - intermediates.dispose_input(prev_frame_output); - } + self.common.output_textures[index] = Some(source.clone()); intermediates.dispose_outputs(out.output); } @@ -560,8 +565,8 @@ impl FilterChainVulkan { x: viewport.x, y: viewport.y, mvp: viewport.mvp.unwrap_or(DEFAULT_MVP), - output: OutputFramebuffer::new(&self.vulkan, - viewport.output.clone())?, + output: OutputImage::new(&self.vulkan, + viewport.output.clone())?, }; pass.draw(cmd, passes_len - 1, @@ -569,6 +574,10 @@ impl FilterChainVulkan { count as u32, 0, viewport, &original, &source, &out)?; + std::mem::swap( + &mut self.output_framebuffers, + &mut self.feedback_framebuffers, + ); intermediates.dispose_outputs(out.output); } Ok(intermediates) diff --git a/librashader-runtime-vk/src/filter_pass.rs b/librashader-runtime-vk/src/filter_pass.rs index 1ecbd71..2f5caf6 100644 --- a/librashader-runtime-vk/src/filter_pass.rs +++ b/librashader-runtime-vk/src/filter_pass.rs @@ -2,7 +2,7 @@ use crate::{error, util}; use crate::filter_chain::FilterCommon; use crate::render_target::RenderTarget; use crate::samplers::{SamplerSet, VulkanSampler}; -use crate::texture::InputTexture; +use crate::texture::InputImage; use crate::ubo_ring::VkUboRing; use crate::vulkan_state::VulkanGraphicsPipeline; use ash::vk; @@ -36,7 +36,7 @@ impl FilterPass { samplers: &SamplerSet, descriptor_set: vk::DescriptorSet, binding: &TextureBinding, - texture: &InputTexture, + texture: &InputImage, ) { let sampler = samplers.get(texture.wrap_mode, texture.filter_mode, texture.mip_filter); let image_info = [vk::DescriptorImageInfo::builder() @@ -76,8 +76,8 @@ impl FilterPass { frame_count: u32, frame_direction: i32, viewport: &Viewport, - original: &InputTexture, - source: &InputTexture, + original: &InputImage, + source: &InputImage, output: &RenderTarget, ) -> error::Result<()> { let descriptor = *&self.graphics_pipeline.layout.descriptor_sets[0]; @@ -124,7 +124,6 @@ impl FilterPass { unsafe { parent.device.cmd_begin_rendering(cmd, &rendering_info); - // parent.device.cmd_begin_render_pass(cmd, &render_pass_info, vk::SubpassContents::INLINE); parent.device.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, self.graphics_pipeline.pipeline); // todo: allow frames in flight. @@ -171,8 +170,8 @@ impl FilterPass { fb_size: Size, viewport_size: Size, descriptor_set: &vk::DescriptorSet, - original: &InputTexture, - source: &InputTexture, + original: &InputImage, + source: &InputImage, ) { if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) { self.uniform_storage.bind_mat4(*offset, mvp, None); @@ -342,34 +341,34 @@ impl FilterPass { } // // PassFeedback - // for (index, feedback) in parent.feedback_textures.iter().enumerate() { - // let Some(feedback) = feedback else { - // eprintln!("no passfeedback {index}"); - // continue; - // }; - // if let Some(binding) = self - // .reflection - // .meta - // .texture_meta - // .get(&TextureSemantics::PassFeedback.semantics(index)) - // { - // FilterPass::bind_texture( - // &parent.samplers, - // &mut textures, - // &mut samplers, - // binding, - // feedback, - // ); - // } - // - // if let Some(offset) = self - // .uniform_bindings - // .get(&TextureSemantics::PassFeedback.semantics(index).into()) - // { - // self.uniform_storage - // .bind_vec4(*offset, feedback.view.size, None); - // } - // } + for (index, feedback) in parent.feedback_textures.iter().enumerate() { + let Some(feedback) = feedback else { + eprintln!("no passfeedback {index}"); + continue; + }; + if let Some(binding) = self + .reflection + .meta + .texture_meta + .get(&TextureSemantics::PassFeedback.semantics(index)) + { + FilterPass::bind_texture( + &self.device, + &parent.samplers, + *descriptor_set, + binding, + feedback, + ); + } + + if let Some(offset) = self + .uniform_bindings + .get(&TextureSemantics::PassFeedback.semantics(index).into()) + { + self.uniform_storage + .bind_vec4(*offset, feedback.image.size, None); + } + } // bind float parameters for (id, offset) in diff --git a/librashader-runtime-vk/src/framebuffer.rs b/librashader-runtime-vk/src/framebuffer.rs index 86c5237..eda0dae 100644 --- a/librashader-runtime-vk/src/framebuffer.rs +++ b/librashader-runtime-vk/src/framebuffer.rs @@ -5,16 +5,16 @@ use ash::vk; use librashader_common::Size; #[derive(Clone)] -pub(crate) struct OutputFramebuffer { +pub(crate) struct OutputImage { pub size: Size, pub image_view: vk::ImageView, device: ash::Device, image: vk::Image, } -impl OutputFramebuffer { +impl OutputImage { pub fn new(vulkan: &Vulkan, - image: VulkanImage) -> error::Result { + image: VulkanImage) -> error::Result { let image_subresource = vk::ImageSubresourceRange::builder() .base_mip_level(0) .base_array_layer(0) @@ -41,7 +41,7 @@ impl OutputFramebuffer { let image_view = unsafe { vulkan.device.create_image_view( &view_info, None)? }; - Ok(OutputFramebuffer { + Ok(OutputImage { device: vulkan.device.clone(), size: image.size, image: image.image, diff --git a/librashader-runtime-vk/src/luts.rs b/librashader-runtime-vk/src/luts.rs index 07b93c4..c65c94b 100644 --- a/librashader-runtime-vk/src/luts.rs +++ b/librashader-runtime-vk/src/luts.rs @@ -1,5 +1,5 @@ use crate::filter_chain::Vulkan; -use crate::texture::{InputTexture, VulkanImage}; +use crate::texture::{InputImage, VulkanImage}; use crate::vulkan_primitives::{VulkanBuffer, VulkanImageMemory}; use crate::{error, util}; use ash::vk; @@ -10,7 +10,7 @@ use librashader_runtime::scaling::MipmapSize; pub struct LutTexture { pub memory: VulkanImageMemory, pub staging: VulkanBuffer, - pub image: InputTexture, + pub image: InputImage, } impl LutTexture { @@ -233,7 +233,7 @@ impl LutTexture { Ok(LutTexture { memory, staging, - image: InputTexture { + image: InputImage { image_view: texture_view, image: VulkanImage { size: image.size, diff --git a/librashader-runtime-vk/src/render_target.rs b/librashader-runtime-vk/src/render_target.rs index 661c81e..ebb25f2 100644 --- a/librashader-runtime-vk/src/render_target.rs +++ b/librashader-runtime-vk/src/render_target.rs @@ -1,4 +1,4 @@ -use crate::framebuffer::OutputFramebuffer; +use crate::framebuffer::OutputImage; use ash::vk; #[rustfmt::skip] @@ -14,5 +14,5 @@ pub(crate) struct RenderTarget<'a> { pub x: f32, pub y: f32, pub mvp: &'a [f32; 16], - pub output: OutputFramebuffer, + pub output: OutputImage, } diff --git a/librashader-runtime-vk/src/texture.rs b/librashader-runtime-vk/src/texture.rs index 31d0fa0..3ea9ec4 100644 --- a/librashader-runtime-vk/src/texture.rs +++ b/librashader-runtime-vk/src/texture.rs @@ -8,7 +8,7 @@ use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_presets::Scale2D; use librashader_runtime::scaling::{MipmapSize, ViewportSize}; -pub struct OwnedTexture { +pub struct OwnedImage { pub device: ash::Device, pub mem_props: vk::PhysicalDeviceMemoryProperties, pub image_view: vk::ImageView, @@ -18,14 +18,14 @@ pub struct OwnedTexture { pub levels: u32, } -impl OwnedTexture { +impl OwnedImage { fn new_internal( device: ash::Device, mem_props: vk::PhysicalDeviceMemoryProperties, size: Size, format: ImageFormat, max_miplevels: u32, - ) -> error::Result { + ) -> error::Result { let image_create_info = vk::ImageCreateInfo::builder() .image_type(vk::ImageType::TYPE_2D) .format(format.into()) @@ -86,7 +86,7 @@ impl OwnedTexture { let image_view = unsafe { device.create_image_view(&view_info, None)? }; - Ok(OwnedTexture { + Ok(OwnedImage { device, mem_props, image_view, @@ -106,7 +106,7 @@ impl OwnedTexture { size: Size, format: ImageFormat, max_miplevels: u32, - ) -> error::Result { + ) -> error::Result { Self::new_internal(vulkan.device.clone(), vulkan.memory_properties, size, format, max_miplevels) } @@ -115,8 +115,8 @@ impl OwnedTexture { scaling: Scale2D, format: ImageFormat, viewport_size: &Size, - _original: &InputTexture, - source: &InputTexture, + _original: &InputImage, + source: &InputImage, mipmap: bool, ) -> error::Result> { let size = source.image.size.scale_viewport(scaling, *viewport_size); @@ -127,7 +127,7 @@ impl OwnedTexture { 1 }; - let mut new = OwnedTexture::new_internal(self.device.clone(), self.mem_props, size, if format == ImageFormat::Unknown { + let mut new = OwnedImage::new_internal(self.device.clone(), self.mem_props, size, if format == ImageFormat::Unknown { ImageFormat::R8G8B8A8Unorm } else { format @@ -139,39 +139,10 @@ impl OwnedTexture { Ok(size) } - - pub fn create_image_view(&self) -> error::Result { - let image_subresource = vk::ImageSubresourceRange::builder() - .base_mip_level(0) - .base_array_layer(0) - .level_count(1) - .layer_count(1) - .aspect_mask(vk::ImageAspectFlags::COLOR) - .build(); - - let swizzle_components = vk::ComponentMapping::builder() - .r(vk::ComponentSwizzle::R) - .g(vk::ComponentSwizzle::G) - .b(vk::ComponentSwizzle::B) - .a(vk::ComponentSwizzle::A) - .build(); - - let mut view_info = vk::ImageViewCreateInfo::builder() - .view_type(vk::ImageViewType::TYPE_2D) - .format(self.image.format) - .image(self.image.image.clone()) - .subresource_range(image_subresource) - .components(swizzle_components) - .build(); - - let image_view = unsafe { self.device.create_image_view(&view_info, None)? }; - Ok(image_view) - } - - pub fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> error::Result { - Ok(InputTexture { + pub fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> error::Result { + Ok(InputImage { image: self.image.clone(), - image_view: self.create_image_view()?, + image_view: self.image_view.clone(), wrap_mode, filter_mode: filter, mip_filter: filter, @@ -459,7 +430,7 @@ impl OwnedTexture { } } -impl Drop for OwnedTexture { +impl Drop for OwnedImage { fn drop(&mut self) { unsafe { if self.image_view != vk::ImageView::null() { @@ -481,7 +452,7 @@ pub struct VulkanImage { #[derive(Clone)] -pub struct InputTexture { +pub struct InputImage { pub image: VulkanImage, pub image_view: vk::ImageView, pub wrap_mode: WrapMode,