vk: fix image format conversions

This commit is contained in:
chyyran 2023-01-11 17:28:09 -05:00
parent ace6774a15
commit 02b3b8baff
7 changed files with 140 additions and 86 deletions

View file

@ -1,5 +1,5 @@
use crate::error::ParsePresetError;
use librashader_common::{FilterMode, WrapMode};
use librashader_common::{FilterMode, ImageFormat, WrapMode};
use std::ops::Mul;
use std::path::PathBuf;
use std::str::FromStr;
@ -29,6 +29,19 @@ pub struct ShaderPassConfig {
pub scaling: Scale2D,
}
impl ShaderPassConfig {
/// If the framebuffer expects a different format than what was defined in the
/// shader source, returns such format.
pub fn get_format_override(&self) -> Option<ImageFormat> {
if self.srgb_framebuffer {
return Some(ImageFormat::R8G8B8A8Srgb)
} else if self.float_framebuffer {
return Some(ImageFormat::R16G16B16A16Sfloat)
}
return None
}
}
#[repr(i32)]
#[derive(Default, Copy, Clone, Debug)]
/// The scaling type for the shader pass.

View file

@ -54,13 +54,14 @@ const NULL_TEXTURES: &[Option<ID3D11ShaderResourceView>; 16] = &[
// slang_process.cpp 229
impl FilterPass {
pub fn get_format(&self) -> ImageFormat {
let mut fb_format = ImageFormat::R8G8B8A8Unorm;
if self.config.srgb_framebuffer {
fb_format = ImageFormat::R8G8B8A8Srgb;
} else if self.config.float_framebuffer {
fb_format = ImageFormat::R16G16B16A16Sfloat;
let mut fb_format = self.source.format;
if let Some(format) = self.config.get_format_override() {
format
} else if fb_format == ImageFormat::Unknown {
ImageFormat::R8G8B8A8Unorm
} else {
fb_format
}
fb_format
}
fn bind_texture(

View file

@ -104,13 +104,14 @@ impl<T: GLInterface> FilterPass<T> {
impl<T: GLInterface> FilterPass<T> {
pub fn get_format(&self) -> ImageFormat {
let mut fb_format = ImageFormat::R8G8B8A8Unorm;
if self.config.srgb_framebuffer {
fb_format = ImageFormat::R8G8B8A8Srgb;
} else if self.config.float_framebuffer {
fb_format = ImageFormat::R16G16B16A16Sfloat;
let mut fb_format = self.source.format;
if let Some(format) = self.config.get_format_override() {
format
} else if fb_format == ImageFormat::Unknown {
ImageFormat::R8G8B8A8Unorm
} else {
fb_format
}
fb_format
}
// framecount should be pre-modded

View file

@ -367,6 +367,11 @@ impl FilterChainVulkan {
source.format = ImageFormat::R8G8B8A8Unorm
}
// preset overrides shader
if let Some(format) = config.get_format_override() {
source.format = format;
}
let graphics_pipeline = VulkanGraphicsPipeline::new(
&vulkan.device,
&vulkan.pipeline_cache,
@ -463,6 +468,10 @@ impl FilterChainVulkan {
let passes = &mut self.passes[0..self.common.config.passes_enabled];
let mut intermediates = FilterChainFrameIntermediates::new(&self.vulkan.device);
if passes.is_empty() {
return Ok(intermediates);
}
let original_image_view = unsafe {
let create_info = vk::ImageViewCreateInfo::builder()
@ -510,7 +519,10 @@ impl FilterChainVulkan {
}
for (index, pass) in passes.iter_mut().enumerate() {
let passes_len = passes.len();
let (pass, last) = passes.split_at_mut(passes_len - 1);
for (index, pass) in pass.iter_mut().enumerate() {
let target = &self.output_framebuffers[index];
// todo: use proper mode
// todo: the output framebuffers can only be dropped after command queue submission.
@ -519,7 +531,8 @@ impl FilterChainVulkan {
x: 0.0,
y: 0.0,
mvp: DEFAULT_MVP,
output: OutputFramebuffer::new(&self.vulkan, &pass.graphics_pipeline.render_pass, target.image.image, target.image.size)?,
output: OutputFramebuffer::new(&self.vulkan, &pass.graphics_pipeline.render_pass,
target.image.clone())?,
};
pass.draw(cmd, index, &self.common, count as u32, 0, viewport, &original, &source, &out)?;
@ -527,7 +540,8 @@ impl FilterChainVulkan {
out.output.end_pass(cmd);
source = target.as_input(pass.config.filter, pass.config.wrap_mode)?;
let prev_frame_output = self.common.output_textures[index].replace(source.clone());
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);
}
@ -535,6 +549,28 @@ impl FilterChainVulkan {
intermediates.dispose_outputs(out.output);
}
// try to hint the optimizer
assert_eq!(last.len(), 1);
if let Some(pass) = last.iter_mut().next() {
source.filter_mode = pass.config.filter;
source.mip_filter = pass.config.filter;
let out = RenderTarget {
x: viewport.x,
y: viewport.y,
mvp: viewport.mvp.unwrap_or(DEFAULT_MVP),
output: OutputFramebuffer::new(&self.vulkan,
&pass.graphics_pipeline.render_pass,
viewport.output.clone())?,
};
pass.draw(cmd, passes_len - 1,
&self.common,
count as u32,
0, viewport, &original, &source, &out)?;
intermediates.dispose_outputs(out.output);
}
Ok(intermediates)
}
}

View file

@ -58,13 +58,14 @@ impl FilterPass {
}
pub fn get_format(&self) -> ImageFormat {
let mut fb_format = ImageFormat::R8G8B8A8Unorm;
if self.config.srgb_framebuffer {
fb_format = ImageFormat::R8G8B8A8Srgb;
} else if self.config.float_framebuffer {
fb_format = ImageFormat::R16G16B16A16Sfloat;
let mut fb_format = self.source.format;
if let Some(format) = self.config.get_format_override() {
format
} else if fb_format == ImageFormat::Unknown {
ImageFormat::R8G8B8A8Unorm
} else {
fb_format
}
fb_format
}
pub(crate) fn draw(

View file

@ -1,7 +1,7 @@
use crate::{error, util};
use crate::filter_chain::Vulkan;
use crate::renderpass::VulkanRenderPass;
use crate::texture::OwnedTexture;
use crate::texture::{OwnedTexture, VulkanImage};
use ash::vk;
use ash::vk::{ImageAspectFlags, ImageViewType};
use librashader_common::Size;
@ -16,7 +16,8 @@ pub(crate) struct OutputFramebuffer {
}
impl OutputFramebuffer {
pub fn new(vulkan: &Vulkan, render_pass: &VulkanRenderPass, image: vk::Image, size: Size<u32>) -> error::Result<OutputFramebuffer> {
pub fn new(vulkan: &Vulkan, render_pass: &VulkanRenderPass,
image: VulkanImage) -> error::Result<OutputFramebuffer> {
let image_subresource = vk::ImageSubresourceRange::builder()
.base_mip_level(0)
.base_array_layer(0)
@ -34,21 +35,22 @@ impl OutputFramebuffer {
let mut view_info = vk::ImageViewCreateInfo::builder()
.view_type(ImageViewType::TYPE_2D)
.format(render_pass.format.into())
.image(image.clone())
.format(image.format)
.image(image.image.clone())
.subresource_range(image_subresource)
.components(swizzle_components)
.build();
let image_view = unsafe { vulkan.device.create_image_view(&view_info, None)? };
let image_view = unsafe { vulkan.device.create_image_view(
&view_info, None)? };
let framebuffer = unsafe {
vulkan.device.create_framebuffer(
&vk::FramebufferCreateInfo::builder()
.render_pass(render_pass.handle)
.attachments(&[image_view])
.width(size.width)
.height(size.height)
.width(image.size.width)
.height(image.size.height)
.layers(1)
.build(),
None,
@ -57,8 +59,8 @@ impl OutputFramebuffer {
Ok(OutputFramebuffer {
device: vulkan.device.clone(),
size,
image,
size: image.size,
image: image.image,
framebuffer,
image_view,
})

View file

@ -223,67 +223,67 @@ impl VulkanWindow {
}, cmd, None)
.unwrap();
eprintln!("{:x}", framebuffer_image.as_raw());
// todo: output image will remove need for ImageLayout::GENERAL
// todo: make `frame` render into swapchain image rather than blit.
util::vulkan_image_layout_transition_levels(
&vulkan.base.device,
cmd,
framebuffer_image,
1,
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
vk::AccessFlags::SHADER_READ,
vk::AccessFlags::TRANSFER_READ,
vk::PipelineStageFlags::VERTEX_SHADER,
vk::PipelineStageFlags::TRANSFER,
vk::QUEUE_FAMILY_IGNORED,
vk::QUEUE_FAMILY_IGNORED,
);
let blit_subresource = vk::ImageSubresourceLayers::builder()
.layer_count(1)
.aspect_mask(vk::ImageAspectFlags::COLOR)
.build();
let src_offsets = [
vk::Offset3D { x: 0, y: 0, z: 0 },
vk::Offset3D {
x: vulkan.swapchain.extent.width as i32,
y: vulkan.swapchain.extent.height as i32,
z: 1,
},
];
let dst_offsets = [
vk::Offset3D { x: 0, y: 0, z: 0 },
vk::Offset3D {
x: vulkan.swapchain.extent.width as i32,
y: vulkan.swapchain.extent.height as i32,
z: 1,
},
];
vulkan.base.device.cmd_blit_image(
cmd,
framebuffer_image,
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
swapchain_image,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&[vk::ImageBlit {
src_subresource: blit_subresource,
src_offsets,
dst_subresource: blit_subresource,
dst_offsets,
}],
vk::Filter::LINEAR,
);
// eprintln!("{:x}", framebuffer_image.as_raw());
// // todo: output image will remove need for ImageLayout::GENERAL
// // todo: make `frame` render into swapchain image rather than blit.
// util::vulkan_image_layout_transition_levels(
// &vulkan.base.device,
// cmd,
// framebuffer_image,
// 1,
// vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
// vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
// vk::AccessFlags::SHADER_READ,
// vk::AccessFlags::TRANSFER_READ,
// vk::PipelineStageFlags::VERTEX_SHADER,
// vk::PipelineStageFlags::TRANSFER,
// vk::QUEUE_FAMILY_IGNORED,
// vk::QUEUE_FAMILY_IGNORED,
// );
//
// let blit_subresource = vk::ImageSubresourceLayers::builder()
// .layer_count(1)
// .aspect_mask(vk::ImageAspectFlags::COLOR)
// .build();
//
// let src_offsets = [
// vk::Offset3D { x: 0, y: 0, z: 0 },
// vk::Offset3D {
// x: vulkan.swapchain.extent.width as i32,
// y: vulkan.swapchain.extent.height as i32,
// z: 1,
// },
// ];
//
// let dst_offsets = [
// vk::Offset3D { x: 0, y: 0, z: 0 },
// vk::Offset3D {
// x: vulkan.swapchain.extent.width as i32,
// y: vulkan.swapchain.extent.height as i32,
// z: 1,
// },
// ];
// vulkan.base.device.cmd_blit_image(
// cmd,
// framebuffer_image,
// vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
// swapchain_image,
// vk::ImageLayout::TRANSFER_DST_OPTIMAL,
// &[vk::ImageBlit {
// src_subresource: blit_subresource,
// src_offsets,
// dst_subresource: blit_subresource,
// dst_offsets,
// }],
// vk::Filter::LINEAR,
// );
util::vulkan_image_layout_transition_levels(
&vulkan.base.device,
cmd,
swapchain_image,
1,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
vk::ImageLayout::PRESENT_SRC_KHR,
vk::AccessFlags::empty(),
vk::AccessFlags::TRANSFER_READ,