vk: accept output viewport

This commit is contained in:
chyyran 2023-01-11 02:36:37 -05:00
parent 9dd656d49f
commit ace6774a15
7 changed files with 86 additions and 57 deletions

View file

@ -25,6 +25,7 @@ use std::path::Path;
use crate::draw_quad::{DrawQuad, VBO_DEFAULT_FINAL, VBO_OFFSCREEN}; use crate::draw_quad::{DrawQuad, VBO_DEFAULT_FINAL, VBO_OFFSCREEN};
use crate::framebuffer::OutputFramebuffer; use crate::framebuffer::OutputFramebuffer;
use crate::render_target::{DEFAULT_MVP, RenderTarget}; use crate::render_target::{DEFAULT_MVP, RenderTarget};
use crate::viewport::Viewport;
pub struct Vulkan { pub struct Vulkan {
// physical_device: vk::PhysicalDevice, // physical_device: vk::PhysicalDevice,
@ -453,7 +454,7 @@ impl FilterChainVulkan {
pub fn frame( pub fn frame(
&mut self, &mut self,
count: usize, count: usize,
viewport: &vk::Viewport, viewport: &Viewport,
input: &VulkanImage, input: &VulkanImage,
cmd: vk::CommandBuffer, cmd: vk::CommandBuffer,
options: Option<()>, options: Option<()>,
@ -502,7 +503,7 @@ impl FilterChainVulkan {
self.output_framebuffers[index].scale( self.output_framebuffers[index].scale(
pass.config.scaling.clone(), pass.config.scaling.clone(),
pass.get_format(), pass.get_format(),
&viewport.into(), &viewport.output.size,
&original, &original,
&source, &source,
)?; )?;
@ -515,6 +516,8 @@ impl FilterChainVulkan {
// todo: the output framebuffers can only be dropped after command queue submission. // todo: the output framebuffers can only be dropped after command queue submission.
let out = RenderTarget { let out = RenderTarget {
x: 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.image, target.image.size)?,
}; };

View file

@ -15,6 +15,7 @@ use librashader_reflect::reflect::ShaderReflection;
use librashader_runtime::uniforms::{UniformStorage, UniformStorageAccess}; use librashader_runtime::uniforms::{UniformStorage, UniformStorageAccess};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::draw_quad::VboType; use crate::draw_quad::VboType;
use crate::viewport::Viewport;
pub struct FilterPass { pub struct FilterPass {
pub device: ash::Device, pub device: ash::Device,
@ -73,7 +74,7 @@ impl FilterPass {
parent: &FilterCommon, parent: &FilterCommon,
frame_count: u32, frame_count: u32,
frame_direction: i32, frame_direction: i32,
viewport: &vk::Viewport, viewport: &Viewport,
original: &InputTexture, original: &InputTexture,
source: &InputTexture, source: &InputTexture,
output: &RenderTarget, output: &RenderTarget,
@ -87,7 +88,7 @@ impl FilterPass {
frame_count, frame_count,
frame_direction, frame_direction,
output.output.size, output.output.size,
viewport.into(), viewport.output.size,
&descriptor, &descriptor,
original, original,
source, source,
@ -110,8 +111,12 @@ impl FilterPass {
float32: [0.0, 0.0, 0.0, 0.0] float32: [0.0, 0.0, 0.0, 0.0]
} }
}]) }])
// always render into the full output, regardless of viewport settings.
.render_area(vk::Rect2D { .render_area(vk::Rect2D {
offset: Default::default(), offset: vk::Offset2D {
x: 0,
y: 0,
},
extent: output.output.size.into(), extent: output.output.size.into(),
}).build(); }).build();
@ -139,7 +144,10 @@ impl FilterPass {
parent.device.cmd_set_scissor(cmd, 0, &[ parent.device.cmd_set_scissor(cmd, 0, &[
vk::Rect2D { vk::Rect2D {
offset: Default::default(), offset: vk::Offset2D {
x: output.x as i32,
y: output.y as i32,
},
extent: output.output.size.into() extent: output.output.size.into()
}]); }]);

View file

@ -24,6 +24,7 @@ use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEve
use winit::event_loop::{ControlFlow, EventLoop, EventLoopBuilder}; use winit::event_loop::{ControlFlow, EventLoop, EventLoopBuilder};
use winit::platform::windows::EventLoopBuilderExtWindows; use winit::platform::windows::EventLoopBuilderExtWindows;
use crate::texture::VulkanImage; use crate::texture::VulkanImage;
use crate::viewport::Viewport;
// Constants // Constants
const WINDOW_TITLE: &'static str = "librashader Vulkan"; const WINDOW_TITLE: &'static str = "librashader Vulkan";
@ -206,13 +207,15 @@ impl VulkanWindow {
// vk::QUEUE_FAMILY_IGNORED // vk::QUEUE_FAMILY_IGNORED
// ); // );
let intermediates = filter.frame(0, &vk::Viewport { let intermediates = filter.frame(0, &Viewport {
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
width: vulkan.swapchain.extent.width as f32, output: VulkanImage {
height: vulkan.swapchain.extent.height as f32, size: vulkan.swapchain.extent.into(),
min_depth: 0.0, image: swapchain_image,
max_depth: 1.0, format: vulkan.swapchain.format.format,
},
mvp: None,
}, &VulkanImage { }, &VulkanImage {
size: vulkan.swapchain.extent.into(), size: vulkan.swapchain.extent.into(),
image: framebuffer_image, image: framebuffer_image,
@ -222,6 +225,7 @@ impl VulkanWindow {
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.
util::vulkan_image_layout_transition_levels( util::vulkan_image_layout_transition_levels(
&vulkan.base.device, &vulkan.base.device,
cmd, cmd,

View file

@ -14,8 +14,9 @@ pub struct VulkanSwapchain {
pub extent: vk::Extent2D, pub extent: vk::Extent2D,
mode: vk::PresentModeKHR, mode: vk::PresentModeKHR,
pub swapchain_images: Vec<vk::Image>, pub swapchain_images: Vec<vk::Image>,
pub render_images: Vec<(vk::Image, VulkanImageMemory)>, pub swapchain_image_views: Vec<vk::ImageView>,
pub render_images: Vec<(vk::Image, VulkanImageMemory)>,
pub render_image_views: Vec<vk::ImageView>, pub render_image_views: Vec<vk::ImageView>,
device: ash::Device, device: ash::Device,
} }
@ -56,7 +57,7 @@ impl VulkanSwapchain {
.clipped(true) .clipped(true)
.image_array_layers(1) .image_array_layers(1)
// todo: switch to IMAGE_USAGE_TRANSFER_DST // todo: switch to IMAGE_USAGE_TRANSFER_DST
.image_usage(vk::ImageUsageFlags::TRANSFER_DST) .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
.build(); .build();
let loader = ash::extensions::khr::Swapchain::new(&base.instance, &base.device); let loader = ash::extensions::khr::Swapchain::new(&base.instance, &base.device);
@ -114,48 +115,48 @@ impl VulkanSwapchain {
} }
} }
// let image_views: VkResult<Vec<vk::ImageView>> = swapchain_images let swapchain_image_views: VkResult<Vec<vk::ImageView>> = swapchain_images
// .iter() .iter()
// .map(|image| { .map(|image| {
// let create_info = vk::ImageViewCreateInfo::builder() let create_info = vk::ImageViewCreateInfo::builder()
// .view_type(vk::ImageViewType::TYPE_2D) .view_type(vk::ImageViewType::TYPE_2D)
// .format(format.format) .format(format.format)
// .components(vk::ComponentMapping { .components(vk::ComponentMapping {
// r: vk::ComponentSwizzle::IDENTITY, r: vk::ComponentSwizzle::IDENTITY,
// g: vk::ComponentSwizzle::IDENTITY, g: vk::ComponentSwizzle::IDENTITY,
// b: vk::ComponentSwizzle::IDENTITY, b: vk::ComponentSwizzle::IDENTITY,
// a: vk::ComponentSwizzle::IDENTITY, a: vk::ComponentSwizzle::IDENTITY,
// }) })
// .subresource_range(vk::ImageSubresourceRange { .subresource_range(vk::ImageSubresourceRange {
// aspect_mask: vk::ImageAspectFlags::COLOR, aspect_mask: vk::ImageAspectFlags::COLOR,
// base_mip_level: 0, base_mip_level: 0,
// level_count: 1, level_count: 1,
// base_array_layer: 0, base_array_layer: 0,
// layer_count: 1, layer_count: 1,
// }) })
// .image(*image) .image(*image)
// .build(); .build();
//
// let view = unsafe { base.device.create_image_view(&create_info, None)? }; let view = unsafe { base.device.create_image_view(&create_info, None)? };
// unsafe { unsafe {
// base.debug.loader.set_debug_utils_object_name(base.device.handle(), base.debug.loader.set_debug_utils_object_name(base.device.handle(),
// &vk::DebugUtilsObjectNameInfoEXT::builder() &vk::DebugUtilsObjectNameInfoEXT::builder()
// .object_handle(image.as_raw()) .object_handle(image.as_raw())
// .object_name(CStr::from_bytes_with_nul_unchecked(b"SwapchainImage\0")) .object_name(CStr::from_bytes_with_nul_unchecked(b"SwapchainImage\0"))
// .object_type(vk::ObjectType::IMAGE) .object_type(vk::ObjectType::IMAGE)
// .build()) .build())
// .expect("could not set object name"); .expect("could not set object name");
// base.debug.loader.set_debug_utils_object_name(base.device.handle(), base.debug.loader.set_debug_utils_object_name(base.device.handle(),
// &vk::DebugUtilsObjectNameInfoEXT::builder() &vk::DebugUtilsObjectNameInfoEXT::builder()
// .object_handle(view.as_raw()) .object_handle(view.as_raw())
// .object_name(CStr::from_bytes_with_nul_unchecked(b"SwapchainImageView\0")) .object_name(CStr::from_bytes_with_nul_unchecked(b"SwapchainImageView\0"))
// .object_type(vk::ObjectType::IMAGE_VIEW) .object_type(vk::ObjectType::IMAGE_VIEW)
// .build()) .build())
// .expect("could not set object name"); .expect("could not set object name");
// } }
// Ok(view) Ok(view)
// }) })
// .collect(); .collect();
let render_image_views: VkResult<Vec<vk::ImageView>> = render_images let render_image_views: VkResult<Vec<vk::ImageView>> = render_images
.iter() .iter()
@ -200,7 +201,7 @@ impl VulkanSwapchain {
mode, mode,
swapchain_images, swapchain_images,
render_images, render_images,
// swapchain_image_views: image_views?, swapchain_image_views: swapchain_image_views?,
render_image_views: render_image_views?, render_image_views: render_image_views?,
device: base.device.clone(), device: base.device.clone(),
}) })
@ -213,7 +214,7 @@ impl Drop for VulkanSwapchain {
for view in &self.render_image_views { for view in &self.render_image_views {
self.device.destroy_image_view(*view, None) self.device.destroy_image_view(*view, None)
} }
for (view, memory) in &self.render_images { for (view, _memory) in &self.render_images {
self.device.destroy_image(*view, None); self.device.destroy_image(*view, None);
} }
self.loader.destroy_swapchain(self.swapchain, None) self.loader.destroy_swapchain(self.swapchain, None)

View file

@ -17,6 +17,7 @@ mod ubo_ring;
mod util; mod util;
mod vulkan_primitives; mod vulkan_primitives;
mod vulkan_state; mod vulkan_state;
mod viewport;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -11,6 +11,8 @@ pub(crate) static DEFAULT_MVP: &[f32; 16] = &[
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct RenderTarget<'a> { pub(crate) struct RenderTarget<'a> {
pub x: f32,
pub y: f32,
pub mvp: &'a [f32; 16], pub mvp: &'a [f32; 16],
pub output: OutputFramebuffer, pub output: OutputFramebuffer,
} }

View file

@ -0,0 +1,10 @@
use crate::texture::VulkanImage;
#[derive(Clone)]
pub struct Viewport<'a> {
pub x: f32,
pub y: f32,
pub output: VulkanImage,
pub mvp: Option<&'a [f32; 16]>,
}