vk: fix frame_count logic

This commit is contained in:
chyyran 2023-01-12 21:11:44 -05:00
parent 8474dcd6dc
commit d55b057e44
5 changed files with 56 additions and 32 deletions

View file

@ -6,8 +6,8 @@ use crate::samplers::SamplerSet;
use crate::texture::{OwnedImage, InputImage, VulkanImage, OwnedImageLayout}; use crate::texture::{OwnedImage, InputImage, VulkanImage, OwnedImageLayout};
use crate::ubo_ring::VkUboRing; use crate::ubo_ring::VkUboRing;
use crate::vulkan_state::VulkanGraphicsPipeline; use crate::vulkan_state::VulkanGraphicsPipeline;
use ash::vk::{CommandPoolCreateFlags, PFN_vkGetInstanceProcAddr, Queue, StaticFn}; use ash::vk::{CommandPoolCreateFlags, DebugUtilsObjectNameInfoEXT, Handle, PFN_vkGetInstanceProcAddr, Queue, StaticFn};
use ash::{vk, Device}; use ash::{vk, Device, Entry};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
@ -22,7 +22,9 @@ use librashader_runtime::image::{Image, UVDirection};
use librashader_runtime::uniforms::UniformStorage; use librashader_runtime::uniforms::UniformStorage;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::error::Error; use std::error::Error;
use std::ffi::CStr;
use std::path::Path; use std::path::Path;
use ash::extensions::ext::DebugUtils;
use crate::draw_quad::DrawQuad; use crate::draw_quad::DrawQuad;
use crate::framebuffer::OutputImage; use crate::framebuffer::OutputImage;
use crate::render_target::{DEFAULT_MVP, RenderTarget}; use crate::render_target::{DEFAULT_MVP, RenderTarget};
@ -36,6 +38,7 @@ pub struct Vulkan {
command_pool: vk::CommandPool, command_pool: vk::CommandPool,
pipeline_cache: vk::PipelineCache, pipeline_cache: vk::PipelineCache,
pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties, pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties,
debug: DebugUtils
} }
type ShaderPassMeta = ( type ShaderPassMeta = (
@ -82,6 +85,10 @@ impl TryFrom<VulkanInfo<'_>> for Vulkan {
)? )?
}; };
let debug = DebugUtils::new(&Entry::from_static_fn(StaticFn {
get_instance_proc_addr: vulkan.get_instance_proc_addr,
}), &instance);
Ok(Vulkan { Ok(Vulkan {
device, device,
// instance, // instance,
@ -89,15 +96,16 @@ impl TryFrom<VulkanInfo<'_>> for Vulkan {
command_pool, command_pool,
pipeline_cache, pipeline_cache,
memory_properties: vulkan.memory_properties.clone(), memory_properties: vulkan.memory_properties.clone(),
debug
}) })
} }
} }
} }
impl TryFrom<(ash::Device, vk::Queue, vk::PhysicalDeviceMemoryProperties)> for Vulkan { impl TryFrom<(ash::Device, vk::Queue, vk::PhysicalDeviceMemoryProperties, DebugUtils)> for Vulkan {
type Error = Box<dyn Error>; type Error = Box<dyn Error>;
fn try_from(value: (Device, Queue, vk::PhysicalDeviceMemoryProperties)) -> error::Result<Self> { fn try_from(value: (Device, Queue, vk::PhysicalDeviceMemoryProperties, DebugUtils)) -> error::Result<Self> {
unsafe { unsafe {
let device = value.0; let device = value.0;
@ -120,6 +128,7 @@ impl TryFrom<(ash::Device, vk::Queue, vk::PhysicalDeviceMemoryProperties)> for V
command_pool, command_pool,
pipeline_cache, pipeline_cache,
memory_properties: value.2, memory_properties: value.2,
debug: value.3
}) })
} }
} }
@ -144,8 +153,8 @@ pub(crate) struct FilterCommon {
pub samplers: SamplerSet, pub samplers: SamplerSet,
pub(crate) draw_quad: DrawQuad, pub(crate) draw_quad: DrawQuad,
pub output_textures: Box<[Option<InputImage>]>, pub output_inputs: Box<[Option<InputImage>]>,
pub feedback_textures: Box<[Option<InputImage>]>, pub feedback_inputs: Box<[Option<InputImage>]>,
pub history_textures: Box<[Option<InputImage>]>, pub history_textures: Box<[Option<InputImage>]>,
pub config: FilterMutable, pub config: FilterMutable,
pub device: ash::Device, pub device: ash::Device,
@ -267,8 +276,8 @@ impl FilterChainVulkan {
}, },
draw_quad: DrawQuad::new(&device.device, &device.memory_properties)?, draw_quad: DrawQuad::new(&device.device, &device.memory_properties)?,
device: device.device.clone(), device: device.device.clone(),
output_textures: output_textures.into_boxed_slice(), output_inputs: output_textures.into_boxed_slice(),
feedback_textures: feedback_textures.into_boxed_slice(), feedback_inputs: feedback_textures.into_boxed_slice(),
history_textures, history_textures,
}, },
passes: filters, passes: filters,
@ -609,7 +618,7 @@ impl FilterChainVulkan {
.iter_mut() .iter_mut()
.zip(self.history_framebuffers.iter()) .zip(self.history_framebuffers.iter())
{ {
*texture = Some(image.as_input(filter, wrap_mode)?); *texture = Some(image.as_input(filter, wrap_mode));
} }
let original = InputImage { let original = InputImage {
@ -620,7 +629,10 @@ impl FilterChainVulkan {
mip_filter: filter, mip_filter: filter,
}; };
let mut source = original.clone(); let mut source = &original;
// swap output and feedback **before** recording command buffers
std::mem::swap(&mut self.output_framebuffers, &mut self.feedback_framebuffers);
// rescale render buffers to ensure all bindings are valid. // rescale render buffers to ensure all bindings are valid.
for (index, pass) in passes.iter_mut().enumerate() { for (index, pass) in passes.iter_mut().enumerate() {
@ -629,7 +641,7 @@ impl FilterChainVulkan {
pass.get_format(), pass.get_format(),
&viewport.output.size, &viewport.output.size,
&original, &original,
&source, source,
// todo: need to check **next** // todo: need to check **next**
pass.config.mipmap_input, pass.config.mipmap_input,
None, None,
@ -640,16 +652,18 @@ impl FilterChainVulkan {
pass.get_format(), pass.get_format(),
&viewport.output.size, &viewport.output.size,
&original, &original,
&source, source,
// todo: need to check **next** // todo: need to check **next**
pass.config.mipmap_input, pass.config.mipmap_input,
None None
)?; )?;
if self.common.feedback_textures[index].is_none() { // self.feedback_framebuffers[index].image.image
self.common.feedback_textures[index] = // refresh inputs
Some(source.clone()); self.common.feedback_inputs[index] =
} Some(self.feedback_framebuffers[index].as_input(pass.config.filter, pass.config.wrap_mode));
self.common.output_inputs[index] =
Some(self.output_framebuffers[index].as_input(pass.config.filter, pass.config.wrap_mode));
} }
let passes_len = passes.len(); let passes_len = passes.len();
@ -657,6 +671,7 @@ impl FilterChainVulkan {
for (index, pass) in pass.iter_mut().enumerate() { for (index, pass) in pass.iter_mut().enumerate() {
let target = &self.output_framebuffers[index]; let target = &self.output_framebuffers[index];
// todo: use proper mode // todo: use proper mode
// todo: the output framebuffers can only be dropped after command queue submission. // todo: the output framebuffers can only be dropped after command queue submission.
@ -668,7 +683,12 @@ impl FilterChainVulkan {
target.image.clone())?, target.image.clone())?,
}; };
pass.draw(cmd, index, &self.common, count as u32, 0, pass.draw(cmd, index, &self.common, if pass.config.frame_count_mod > 0 {
count % pass.config.frame_count_mod as usize
} else {
count
} as u32
, 0,
viewport, &original, &source, &out)?; viewport, &original, &source, &out)?;
if target.max_miplevels > 1 { if target.max_miplevels > 1 {
@ -677,17 +697,15 @@ impl FilterChainVulkan {
out.output.end_pass(cmd); out.output.end_pass(cmd);
} }
source = target.as_input(pass.config.filter, pass.config.wrap_mode)?; source = &self.common.output_inputs[index].as_ref().unwrap();
let feedback = self.common.output_textures[index].replace(source.clone());
intermediates.dispose_outputs(out.output); intermediates.dispose_outputs(out.output);
} }
// 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() {
source.filter_mode = pass.config.filter; // source.filter_mode = pass.config.filter;
source.mip_filter = pass.config.filter; // source.mip_filter = pass.config.filter;
let out = RenderTarget { let out = RenderTarget {
x: viewport.x, x: viewport.x,
@ -700,7 +718,7 @@ impl FilterChainVulkan {
pass.draw(cmd, passes_len - 1, pass.draw(cmd, passes_len - 1,
&self.common, &self.common,
count as u32, count as u32,
0, viewport, &original, &source, &out)?; 0, viewport, &original, source, &out)?;
intermediates.dispose_outputs(out.output); intermediates.dispose_outputs(out.output);
} }

View file

@ -312,7 +312,7 @@ impl FilterPass {
} }
// PassOutput // PassOutput
for (index, output) in parent.output_textures.iter().enumerate() { for (index, output) in parent.output_inputs.iter().enumerate() {
let Some(output) = output else { let Some(output) = output else {
continue; continue;
}; };
@ -341,7 +341,7 @@ impl FilterPass {
} }
// PassFeedback // PassFeedback
for (index, feedback) in parent.feedback_textures.iter().enumerate() { for (index, feedback) in parent.feedback_inputs.iter().enumerate() {
let Some(feedback) = feedback else { let Some(feedback) = feedback else {
eprintln!("no passfeedback {index}"); eprintln!("no passfeedback {index}");
continue; continue;

View file

@ -49,7 +49,9 @@ impl VulkanWindow {
vulkan: VulkanDraw, vulkan: VulkanDraw,
mut filter_chain: FilterChainVulkan, mut filter_chain: FilterChainVulkan,
) { ) {
event_loop.run(move |event, _, control_flow| match event { let mut counter = 0;
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent { event, .. } => match event { Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput { input, .. } => match input { WindowEvent::KeyboardInput { input, .. } => match input {
@ -70,10 +72,13 @@ impl VulkanWindow {
window.request_redraw(); window.request_redraw();
} }
Event::RedrawRequested(_window_id) => { Event::RedrawRequested(_window_id) => {
VulkanWindow::draw_frame(&vulkan, &mut filter_chain); VulkanWindow::draw_frame(counter, &vulkan, &mut filter_chain);
counter += 1;
} }
_ => (), _ => (),
}
}) })
} }
unsafe fn record_command_buffer( unsafe fn record_command_buffer(
@ -133,7 +138,7 @@ impl VulkanWindow {
vulkan.base.device.cmd_end_render_pass(cmd); vulkan.base.device.cmd_end_render_pass(cmd);
} }
fn draw_frame(vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) { fn draw_frame(frame: usize, vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) {
unsafe { unsafe {
vulkan vulkan
.base .base
@ -207,7 +212,7 @@ impl VulkanWindow {
// vk::QUEUE_FAMILY_IGNORED // vk::QUEUE_FAMILY_IGNORED
// ); // );
let intermediates = filter.frame(0, &Viewport { let intermediates = filter.frame(frame, &Viewport {
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
output: VulkanImage { output: VulkanImage {

View file

@ -166,6 +166,7 @@ impl TryFrom<&VulkanBase> for Vulkan {
value.device.clone(), value.device.clone(),
value.graphics_queue.clone(), value.graphics_queue.clone(),
value.mem_props, value.mem_props,
value.debug.loader.clone()
)) ))
} }
} }

View file

@ -165,14 +165,14 @@ impl OwnedImage {
Ok(size) Ok(size)
} }
pub fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> error::Result<InputImage> { pub fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputImage {
Ok(InputImage { InputImage {
image: self.image.clone(), image: self.image.clone(),
image_view: self.image_view.clone(), image_view: self.image_view.clone(),
wrap_mode, wrap_mode,
filter_mode: filter, filter_mode: filter,
mip_filter: filter, mip_filter: filter,
}) }
} }
pub fn generate_mipmaps_and_end_pass(&self, cmd: vk::CommandBuffer) { pub fn generate_mipmaps_and_end_pass(&self, cmd: vk::CommandBuffer) {