vk: fix image format conversions
This commit is contained in:
parent
ace6774a15
commit
02b3b8baff
|
@ -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.
|
||||
|
|
|
@ -54,14 +54,15 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_texture(
|
||||
samplers: &SamplerSet,
|
||||
|
|
|
@ -104,14 +104,15 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
// framecount should be pre-modded
|
||||
fn build_semantics(
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,14 +58,15 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn draw(
|
||||
&mut self,
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue