vk: fix image format conversions
This commit is contained in:
parent
ace6774a15
commit
02b3b8baff
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::ParsePresetError;
|
use crate::error::ParsePresetError;
|
||||||
use librashader_common::{FilterMode, WrapMode};
|
use librashader_common::{FilterMode, ImageFormat, WrapMode};
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -29,6 +29,19 @@ pub struct ShaderPassConfig {
|
||||||
pub scaling: Scale2D,
|
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)]
|
#[repr(i32)]
|
||||||
#[derive(Default, Copy, Clone, Debug)]
|
#[derive(Default, Copy, Clone, Debug)]
|
||||||
/// The scaling type for the shader pass.
|
/// The scaling type for the shader pass.
|
||||||
|
|
|
@ -54,14 +54,15 @@ const NULL_TEXTURES: &[Option<ID3D11ShaderResourceView>; 16] = &[
|
||||||
// slang_process.cpp 229
|
// slang_process.cpp 229
|
||||||
impl FilterPass {
|
impl FilterPass {
|
||||||
pub fn get_format(&self) -> ImageFormat {
|
pub fn get_format(&self) -> ImageFormat {
|
||||||
let mut fb_format = ImageFormat::R8G8B8A8Unorm;
|
let mut fb_format = self.source.format;
|
||||||
if self.config.srgb_framebuffer {
|
if let Some(format) = self.config.get_format_override() {
|
||||||
fb_format = ImageFormat::R8G8B8A8Srgb;
|
format
|
||||||
} else if self.config.float_framebuffer {
|
} else if fb_format == ImageFormat::Unknown {
|
||||||
fb_format = ImageFormat::R16G16B16A16Sfloat;
|
ImageFormat::R8G8B8A8Unorm
|
||||||
}
|
} else {
|
||||||
fb_format
|
fb_format
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn bind_texture(
|
fn bind_texture(
|
||||||
samplers: &SamplerSet,
|
samplers: &SamplerSet,
|
||||||
|
|
|
@ -104,14 +104,15 @@ impl<T: GLInterface> FilterPass<T> {
|
||||||
|
|
||||||
impl<T: GLInterface> FilterPass<T> {
|
impl<T: GLInterface> FilterPass<T> {
|
||||||
pub fn get_format(&self) -> ImageFormat {
|
pub fn get_format(&self) -> ImageFormat {
|
||||||
let mut fb_format = ImageFormat::R8G8B8A8Unorm;
|
let mut fb_format = self.source.format;
|
||||||
if self.config.srgb_framebuffer {
|
if let Some(format) = self.config.get_format_override() {
|
||||||
fb_format = ImageFormat::R8G8B8A8Srgb;
|
format
|
||||||
} else if self.config.float_framebuffer {
|
} else if fb_format == ImageFormat::Unknown {
|
||||||
fb_format = ImageFormat::R16G16B16A16Sfloat;
|
ImageFormat::R8G8B8A8Unorm
|
||||||
}
|
} else {
|
||||||
fb_format
|
fb_format
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// framecount should be pre-modded
|
// framecount should be pre-modded
|
||||||
fn build_semantics(
|
fn build_semantics(
|
||||||
|
|
|
@ -367,6 +367,11 @@ impl FilterChainVulkan {
|
||||||
source.format = ImageFormat::R8G8B8A8Unorm
|
source.format = ImageFormat::R8G8B8A8Unorm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// preset overrides shader
|
||||||
|
if let Some(format) = config.get_format_override() {
|
||||||
|
source.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
let graphics_pipeline = VulkanGraphicsPipeline::new(
|
let graphics_pipeline = VulkanGraphicsPipeline::new(
|
||||||
&vulkan.device,
|
&vulkan.device,
|
||||||
&vulkan.pipeline_cache,
|
&vulkan.pipeline_cache,
|
||||||
|
@ -463,6 +468,10 @@ impl FilterChainVulkan {
|
||||||
let passes = &mut self.passes[0..self.common.config.passes_enabled];
|
let passes = &mut self.passes[0..self.common.config.passes_enabled];
|
||||||
|
|
||||||
let mut intermediates = FilterChainFrameIntermediates::new(&self.vulkan.device);
|
let mut intermediates = FilterChainFrameIntermediates::new(&self.vulkan.device);
|
||||||
|
if passes.is_empty() {
|
||||||
|
return Ok(intermediates);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let original_image_view = unsafe {
|
let original_image_view = unsafe {
|
||||||
let create_info = vk::ImageViewCreateInfo::builder()
|
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];
|
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.
|
||||||
|
@ -519,7 +531,8 @@ impl FilterChainVulkan {
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.0,
|
y: 0.0,
|
||||||
mvp: DEFAULT_MVP,
|
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)?;
|
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);
|
out.output.end_pass(cmd);
|
||||||
|
|
||||||
source = target.as_input(pass.config.filter, pass.config.wrap_mode)?;
|
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 {
|
if let Some(prev_frame_output) = prev_frame_output {
|
||||||
intermediates.dispose_input(prev_frame_output);
|
intermediates.dispose_input(prev_frame_output);
|
||||||
}
|
}
|
||||||
|
@ -535,6 +549,28 @@ impl FilterChainVulkan {
|
||||||
intermediates.dispose_outputs(out.output);
|
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)
|
Ok(intermediates)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,14 +58,15 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_format(&self) -> ImageFormat {
|
pub fn get_format(&self) -> ImageFormat {
|
||||||
let mut fb_format = ImageFormat::R8G8B8A8Unorm;
|
let mut fb_format = self.source.format;
|
||||||
if self.config.srgb_framebuffer {
|
if let Some(format) = self.config.get_format_override() {
|
||||||
fb_format = ImageFormat::R8G8B8A8Srgb;
|
format
|
||||||
} else if self.config.float_framebuffer {
|
} else if fb_format == ImageFormat::Unknown {
|
||||||
fb_format = ImageFormat::R16G16B16A16Sfloat;
|
ImageFormat::R8G8B8A8Unorm
|
||||||
}
|
} else {
|
||||||
fb_format
|
fb_format
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn draw(
|
pub(crate) fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
use crate::filter_chain::Vulkan;
|
use crate::filter_chain::Vulkan;
|
||||||
use crate::renderpass::VulkanRenderPass;
|
use crate::renderpass::VulkanRenderPass;
|
||||||
use crate::texture::OwnedTexture;
|
use crate::texture::{OwnedTexture, VulkanImage};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use ash::vk::{ImageAspectFlags, ImageViewType};
|
use ash::vk::{ImageAspectFlags, ImageViewType};
|
||||||
use librashader_common::Size;
|
use librashader_common::Size;
|
||||||
|
@ -16,7 +16,8 @@ pub(crate) struct OutputFramebuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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()
|
let image_subresource = vk::ImageSubresourceRange::builder()
|
||||||
.base_mip_level(0)
|
.base_mip_level(0)
|
||||||
.base_array_layer(0)
|
.base_array_layer(0)
|
||||||
|
@ -34,21 +35,22 @@ impl OutputFramebuffer {
|
||||||
|
|
||||||
let mut view_info = vk::ImageViewCreateInfo::builder()
|
let mut view_info = vk::ImageViewCreateInfo::builder()
|
||||||
.view_type(ImageViewType::TYPE_2D)
|
.view_type(ImageViewType::TYPE_2D)
|
||||||
.format(render_pass.format.into())
|
.format(image.format)
|
||||||
.image(image.clone())
|
.image(image.image.clone())
|
||||||
.subresource_range(image_subresource)
|
.subresource_range(image_subresource)
|
||||||
.components(swizzle_components)
|
.components(swizzle_components)
|
||||||
.build();
|
.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 {
|
let framebuffer = unsafe {
|
||||||
vulkan.device.create_framebuffer(
|
vulkan.device.create_framebuffer(
|
||||||
&vk::FramebufferCreateInfo::builder()
|
&vk::FramebufferCreateInfo::builder()
|
||||||
.render_pass(render_pass.handle)
|
.render_pass(render_pass.handle)
|
||||||
.attachments(&[image_view])
|
.attachments(&[image_view])
|
||||||
.width(size.width)
|
.width(image.size.width)
|
||||||
.height(size.height)
|
.height(image.size.height)
|
||||||
.layers(1)
|
.layers(1)
|
||||||
.build(),
|
.build(),
|
||||||
None,
|
None,
|
||||||
|
@ -57,8 +59,8 @@ impl OutputFramebuffer {
|
||||||
|
|
||||||
Ok(OutputFramebuffer {
|
Ok(OutputFramebuffer {
|
||||||
device: vulkan.device.clone(),
|
device: vulkan.device.clone(),
|
||||||
size,
|
size: image.size,
|
||||||
image,
|
image: image.image,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
image_view,
|
image_view,
|
||||||
})
|
})
|
||||||
|
|
|
@ -223,67 +223,67 @@ impl VulkanWindow {
|
||||||
}, cmd, None)
|
}, cmd, None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
eprintln!("{:x}", framebuffer_image.as_raw());
|
// eprintln!("{:x}", framebuffer_image.as_raw());
|
||||||
// todo: output image will remove need for ImageLayout::GENERAL
|
// // todo: output image will remove need for ImageLayout::GENERAL
|
||||||
// todo: make `frame` render into swapchain image rather than blit.
|
// // todo: make `frame` render into swapchain image rather than blit.
|
||||||
util::vulkan_image_layout_transition_levels(
|
// util::vulkan_image_layout_transition_levels(
|
||||||
&vulkan.base.device,
|
// &vulkan.base.device,
|
||||||
cmd,
|
// cmd,
|
||||||
framebuffer_image,
|
// framebuffer_image,
|
||||||
1,
|
// 1,
|
||||||
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
|
// vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
|
||||||
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
// vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
||||||
vk::AccessFlags::SHADER_READ,
|
// vk::AccessFlags::SHADER_READ,
|
||||||
vk::AccessFlags::TRANSFER_READ,
|
// vk::AccessFlags::TRANSFER_READ,
|
||||||
vk::PipelineStageFlags::VERTEX_SHADER,
|
// vk::PipelineStageFlags::VERTEX_SHADER,
|
||||||
vk::PipelineStageFlags::TRANSFER,
|
// vk::PipelineStageFlags::TRANSFER,
|
||||||
vk::QUEUE_FAMILY_IGNORED,
|
// vk::QUEUE_FAMILY_IGNORED,
|
||||||
vk::QUEUE_FAMILY_IGNORED,
|
// vk::QUEUE_FAMILY_IGNORED,
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
let blit_subresource = vk::ImageSubresourceLayers::builder()
|
// let blit_subresource = vk::ImageSubresourceLayers::builder()
|
||||||
.layer_count(1)
|
// .layer_count(1)
|
||||||
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
// .aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
.build();
|
// .build();
|
||||||
|
//
|
||||||
let src_offsets = [
|
// let src_offsets = [
|
||||||
vk::Offset3D { x: 0, y: 0, z: 0 },
|
// vk::Offset3D { x: 0, y: 0, z: 0 },
|
||||||
vk::Offset3D {
|
// vk::Offset3D {
|
||||||
x: vulkan.swapchain.extent.width as i32,
|
// x: vulkan.swapchain.extent.width as i32,
|
||||||
y: vulkan.swapchain.extent.height as i32,
|
// y: vulkan.swapchain.extent.height as i32,
|
||||||
z: 1,
|
// z: 1,
|
||||||
},
|
// },
|
||||||
];
|
// ];
|
||||||
|
//
|
||||||
let dst_offsets = [
|
// let dst_offsets = [
|
||||||
vk::Offset3D { x: 0, y: 0, z: 0 },
|
// vk::Offset3D { x: 0, y: 0, z: 0 },
|
||||||
vk::Offset3D {
|
// vk::Offset3D {
|
||||||
x: vulkan.swapchain.extent.width as i32,
|
// x: vulkan.swapchain.extent.width as i32,
|
||||||
y: vulkan.swapchain.extent.height as i32,
|
// y: vulkan.swapchain.extent.height as i32,
|
||||||
z: 1,
|
// z: 1,
|
||||||
},
|
// },
|
||||||
];
|
// ];
|
||||||
vulkan.base.device.cmd_blit_image(
|
// vulkan.base.device.cmd_blit_image(
|
||||||
cmd,
|
// cmd,
|
||||||
framebuffer_image,
|
// framebuffer_image,
|
||||||
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
// vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
||||||
swapchain_image,
|
// swapchain_image,
|
||||||
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
// vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
&[vk::ImageBlit {
|
// &[vk::ImageBlit {
|
||||||
src_subresource: blit_subresource,
|
// src_subresource: blit_subresource,
|
||||||
src_offsets,
|
// src_offsets,
|
||||||
dst_subresource: blit_subresource,
|
// dst_subresource: blit_subresource,
|
||||||
dst_offsets,
|
// dst_offsets,
|
||||||
}],
|
// }],
|
||||||
vk::Filter::LINEAR,
|
// vk::Filter::LINEAR,
|
||||||
);
|
// );
|
||||||
|
|
||||||
util::vulkan_image_layout_transition_levels(
|
util::vulkan_image_layout_transition_levels(
|
||||||
&vulkan.base.device,
|
&vulkan.base.device,
|
||||||
cmd,
|
cmd,
|
||||||
swapchain_image,
|
swapchain_image,
|
||||||
1,
|
1,
|
||||||
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
|
||||||
vk::ImageLayout::PRESENT_SRC_KHR,
|
vk::ImageLayout::PRESENT_SRC_KHR,
|
||||||
vk::AccessFlags::empty(),
|
vk::AccessFlags::empty(),
|
||||||
vk::AccessFlags::TRANSFER_READ,
|
vk::AccessFlags::TRANSFER_READ,
|
||||||
|
|
Loading…
Reference in a new issue