From 40b9f0823493c58d5cd4d708f4b35852c9b0962b Mon Sep 17 00:00:00 2001 From: chyyran Date: Fri, 13 Jan 2023 01:19:41 -0500 Subject: [PATCH] vk: do own queue selection and fix error type --- librashader-runtime-vk/src/error.rs | 26 +++- librashader-runtime-vk/src/filter_chain.rs | 117 ++++++++---------- .../src/hello_triangle/mod.rs | 3 +- .../src/hello_triangle/vulkan_base.rs | 8 +- librashader-runtime-vk/src/lib.rs | 10 +- librashader-runtime-vk/src/luts.rs | 14 +-- librashader-runtime-vk/src/options.rs | 0 librashader-runtime-vk/src/queue_selection.rs | 24 ++++ 8 files changed, 123 insertions(+), 79 deletions(-) create mode 100644 librashader-runtime-vk/src/options.rs create mode 100644 librashader-runtime-vk/src/queue_selection.rs diff --git a/librashader-runtime-vk/src/error.rs b/librashader-runtime-vk/src/error.rs index fa138cb..aac8dd5 100644 --- a/librashader-runtime-vk/src/error.rs +++ b/librashader-runtime-vk/src/error.rs @@ -1,3 +1,25 @@ -use std::error::Error; +use librashader_preprocess::PreprocessError; +use librashader_presets::ParsePresetError; +use librashader_reflect::error::{ShaderCompileError, ShaderReflectError}; +use librashader_runtime::image::ImageError; +use thiserror::Error; -pub type Result = std::result::Result>; +#[derive(Error, Debug)] +pub enum FilterChainError { + #[error("SPIRV reflection error")] + SpirvCrossReflectError(#[from] spirv_cross::ErrorCode), + #[error("shader preset parse error")] + ShaderPresetError(#[from] ParsePresetError), + #[error("shader preprocess error")] + ShaderPreprocessError(#[from] PreprocessError), + #[error("shader compile error")] + ShaderCompileError(#[from] ShaderCompileError), + #[error("shader reflect error")] + ShaderReflectError(#[from] ShaderReflectError), + #[error("lut loading error")] + LutLoadError(#[from] ImageError), + #[error("vulkan error")] + VulkanResult(#[from] ash::vk::Result), +} + +pub type Result = std::result::Result; diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index 68edc6f..779218f 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -4,18 +4,14 @@ use crate::framebuffer::OutputImage; use crate::luts::LutTexture; use crate::render_target::{RenderTarget, DEFAULT_MVP}; use crate::samplers::SamplerSet; -use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage}; +use crate::texture::{InputImage, OwnedImage, VulkanImage}; use crate::ubo_ring::VkUboRing; use crate::viewport::Viewport; use crate::vulkan_state::VulkanGraphicsPipeline; use crate::{error, util}; use ash::extensions::ext::DebugUtils; -use ash::vk::{ - CommandPoolCreateFlags, DebugUtilsObjectNameInfoEXT, Handle, PFN_vkGetInstanceProcAddr, Queue, - StaticFn, -}; -use ash::{vk, Device, Entry}; -use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; +use ash::vk; +use librashader_common::{ImageFormat, Size}; use librashader_preprocess::ShaderSource; use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; use librashader_reflect::back::targets::SpirV; @@ -29,16 +25,15 @@ use librashader_runtime::image::{Image, UVDirection}; use librashader_runtime::uniforms::UniformStorage; use rustc_hash::FxHashMap; use std::collections::VecDeque; -use std::error::Error; -use std::ffi::CStr; use std::path::Path; +use crate::error::FilterChainError; +use crate::queue_selection::get_graphics_queue; pub struct Vulkan { // physical_device: vk::PhysicalDevice, pub(crate) device: ash::Device, // instance: ash::Instance, queue: vk::Queue, - command_pool: vk::CommandPool, pipeline_cache: vk::PipelineCache, pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties, // debug: DebugUtils, @@ -51,57 +46,47 @@ type ShaderPassMeta = ( ); #[derive(Clone)] -pub struct VulkanInfo<'a> { - // physical_device: &'a vk::PhysicalDevice, - device: &'a vk::Device, - instance: &'a vk::Instance, - queue: &'a vk::Queue, - memory_properties: &'a vk::PhysicalDeviceMemoryProperties, - get_instance_proc_addr: PFN_vkGetInstanceProcAddr, +pub struct VulkanInfo { + device: vk::Device, + instance: vk::Instance, + physical_device: vk::PhysicalDevice, + get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr, } -impl TryFrom> for Vulkan { - type Error = Box; +impl TryFrom for Vulkan { + type Error = FilterChainError; - fn try_from(vulkan: VulkanInfo) -> Result> { + fn try_from(vulkan: VulkanInfo) -> Result { unsafe { let instance = ash::Instance::load( - &StaticFn { + &vk::StaticFn { get_instance_proc_addr: vulkan.get_instance_proc_addr, }, - vulkan.instance.clone(), + vulkan.instance, ); - let device = ash::Device::load(instance.fp_v1_0(), vulkan.device.clone()); + let device = ash::Device::load(instance.fp_v1_0(), vulkan.device); let pipeline_cache = unsafe { device.create_pipeline_cache(&vk::PipelineCacheCreateInfo::default(), None)? }; - // the queue is only used for lut loading.. we may want to select our own queue. - let command_pool = unsafe { - device.create_command_pool( - &vk::CommandPoolCreateInfo::builder() - .flags(CommandPoolCreateFlags::RESET_COMMAND_BUFFER) - .build(), - None, - )? - }; - let debug = DebugUtils::new( - &Entry::from_static_fn(StaticFn { + &ash::Entry::from_static_fn(vk::StaticFn { get_instance_proc_addr: vulkan.get_instance_proc_addr, }), &instance, ); + let queue = get_graphics_queue(&instance, &device, vulkan.physical_device); + let memory_properties = instance.get_physical_device_memory_properties(vulkan.physical_device); + Ok(Vulkan { device, // instance, - queue: vulkan.queue.clone(), - command_pool, + queue, pipeline_cache, - memory_properties: vulkan.memory_properties.clone(), + memory_properties, // debug, }) } @@ -110,44 +95,36 @@ impl TryFrom> for Vulkan { impl TryFrom<( + vk::PhysicalDevice, + ash::Instance, ash::Device, - vk::Queue, - vk::PhysicalDeviceMemoryProperties, - DebugUtils, )> for Vulkan { - type Error = Box; + type Error = FilterChainError; fn try_from( value: ( - Device, - Queue, - vk::PhysicalDeviceMemoryProperties, - DebugUtils, + vk::PhysicalDevice, + ash::Instance, + ash::Device, ), ) -> error::Result { unsafe { - let device = value.0; + let device = value.2; let pipeline_cache = unsafe { device.create_pipeline_cache(&vk::PipelineCacheCreateInfo::default(), None)? }; - let command_pool = unsafe { - device.create_command_pool( - &vk::CommandPoolCreateInfo::builder() - .flags(CommandPoolCreateFlags::RESET_COMMAND_BUFFER) - .build(), - None, - )? - }; + let queue = get_graphics_queue(&value.1, &device, value.0); + + let memory_properties = value.1.get_physical_device_memory_properties(value.0); Ok(Vulkan { device, - queue: value.1, - command_pool, + queue, pipeline_cache, - memory_properties: value.2, + memory_properties, // debug: value.3, }) } @@ -227,7 +204,7 @@ pub type FilterChainOptionsVulkan = (); impl FilterChainVulkan { /// Load the shader preset at the given path into a filter chain. pub fn load_from_path( - vulkan: impl TryInto>, + vulkan: impl TryInto, path: impl AsRef, options: Option<&FilterChainOptionsVulkan>, ) -> error::Result { @@ -237,7 +214,7 @@ impl FilterChainVulkan { } pub fn load_from_preset( - vulkan: impl TryInto>, + vulkan: impl TryInto, preset: ShaderPreset, options: Option<&FilterChainOptionsVulkan>, ) -> error::Result { @@ -325,7 +302,7 @@ impl FilterChainVulkan { }), ); } - Ok::<_, Box>((shader, source, reflect)) + Ok::<_, FilterChainError>((shader, source, reflect)) }) .into_iter() .collect::)>>>( @@ -431,11 +408,21 @@ impl FilterChainVulkan { textures: &[TextureConfig], ) -> error::Result> { let mut luts = FxHashMap::default(); + + let command_pool = unsafe { + vulkan.device.create_command_pool( + &vk::CommandPoolCreateInfo::builder() + .flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER) + .build(), + None, + )? + }; + let command_buffer = unsafe { // panic safety: command buffer count = 1 vulkan.device.allocate_command_buffers( &vk::CommandBufferAllocateInfo::builder() - .command_pool(vulkan.command_pool) + .command_pool(command_pool) .level(vk::CommandBufferLevel::PRIMARY) .command_buffer_count(1) .build(), @@ -454,7 +441,7 @@ impl FilterChainVulkan { for (index, texture) in textures.iter().enumerate() { let image = Image::load(&texture.path, UVDirection::TopLeft)?; - let texture = LutTexture::new(vulkan, &command_buffer, image, texture)?; + let texture = LutTexture::new(vulkan, command_buffer, image, texture)?; luts.insert(index, texture); } @@ -468,9 +455,13 @@ impl FilterChainVulkan { .device .queue_submit(vulkan.queue, &submits, vk::Fence::null())?; vulkan.device.queue_wait_idle(vulkan.queue)?; + vulkan .device - .free_command_buffers(vulkan.command_pool, &buffers); + .free_command_buffers(command_pool, &buffers); + + vulkan.device + .destroy_command_pool(command_pool, None); } Ok(luts) } diff --git a/librashader-runtime-vk/src/hello_triangle/mod.rs b/librashader-runtime-vk/src/hello_triangle/mod.rs index dcb8b9b..4e17453 100644 --- a/librashader-runtime-vk/src/hello_triangle/mod.rs +++ b/librashader-runtime-vk/src/hello_triangle/mod.rs @@ -347,8 +347,7 @@ impl VulkanWindow { .queue_present(vulkan.base.graphics_queue, &present_info) .unwrap(); - //oops i pooped my pants - // std::mem::forget(intermediates); + vulkan.base.device.device_wait_idle().unwrap(); drop(intermediates) } diff --git a/librashader-runtime-vk/src/hello_triangle/vulkan_base.rs b/librashader-runtime-vk/src/hello_triangle/vulkan_base.rs index 04d5331..9434783 100644 --- a/librashader-runtime-vk/src/hello_triangle/vulkan_base.rs +++ b/librashader-runtime-vk/src/hello_triangle/vulkan_base.rs @@ -8,6 +8,7 @@ use crate::hello_triangle::physicaldevice::{find_queue_family, pick_physical_dev use crate::hello_triangle::surface::VulkanSurface; use ash::prelude::VkResult; use std::ffi::{CStr, CString}; +use crate::error::FilterChainError; const WINDOW_TITLE: &'static [u8] = b"librashader Vulkan\0"; const KHRONOS_VALIDATION: &'static [u8] = b"VK_LAYER_KHRONOS_validation\0"; @@ -162,14 +163,13 @@ impl Drop for VulkanBase { } impl TryFrom<&VulkanBase> for Vulkan { - type Error = Box; + type Error = FilterChainError; fn try_from(value: &VulkanBase) -> Result { Vulkan::try_from(( + value.physical_device, + value.instance.clone(), value.device.clone(), - value.graphics_queue.clone(), - value.mem_props, - value.debug.loader.clone(), )) } } diff --git a/librashader-runtime-vk/src/lib.rs b/librashader-runtime-vk/src/lib.rs index 1b3b0ed..87cb25c 100644 --- a/librashader-runtime-vk/src/lib.rs +++ b/librashader-runtime-vk/src/lib.rs @@ -3,10 +3,10 @@ #![feature(strict_provenance)] mod draw_quad; -mod error; mod filter_chain; mod filter_pass; mod framebuffer; +#[cfg(test)] mod hello_triangle; mod luts; mod render_target; @@ -17,6 +17,14 @@ mod util; mod viewport; mod vulkan_primitives; mod vulkan_state; +mod queue_selection; + +pub use filter_chain::FilterChainFrameIntermediates; +pub use filter_chain::FilterChainVulkan; +pub use viewport::Viewport; + +pub mod error; +pub mod options; #[cfg(test)] mod tests { diff --git a/librashader-runtime-vk/src/luts.rs b/librashader-runtime-vk/src/luts.rs index c65c94b..48552d0 100644 --- a/librashader-runtime-vk/src/luts.rs +++ b/librashader-runtime-vk/src/luts.rs @@ -16,7 +16,7 @@ pub struct LutTexture { impl LutTexture { pub fn new( vulkan: &Vulkan, - cmd: &vk::CommandBuffer, + cmd: vk::CommandBuffer, image: Image, config: &TextureConfig, ) -> error::Result { @@ -97,7 +97,7 @@ impl LutTexture { unsafe { util::vulkan_image_layout_transition_levels( &vulkan.device, - *cmd, + cmd, texture, vk::REMAINING_MIP_LEVELS, vk::ImageLayout::UNDEFINED, @@ -115,7 +115,7 @@ impl LutTexture { ); vulkan.device.cmd_copy_buffer_to_image( - *cmd, + cmd, staging.handle, texture, if config.mipmap { @@ -183,7 +183,7 @@ impl LutTexture { unsafe { util::vulkan_image_layout_transition_levels( &vulkan.device, - *cmd, + cmd, texture, vk::REMAINING_MIP_LEVELS, vk::ImageLayout::GENERAL, @@ -198,13 +198,13 @@ impl LutTexture { // todo: respect mipmap filter? vulkan.device.cmd_blit_image( - *cmd, + cmd, texture, vk::ImageLayout::GENERAL, texture, vk::ImageLayout::GENERAL, &image_blit, - vk::Filter::LINEAR, + config.filter_mode.into(), ); } } @@ -212,7 +212,7 @@ impl LutTexture { unsafe { util::vulkan_image_layout_transition_levels( &vulkan.device, - *cmd, + cmd, texture, vk::REMAINING_MIP_LEVELS, if config.mipmap { diff --git a/librashader-runtime-vk/src/options.rs b/librashader-runtime-vk/src/options.rs new file mode 100644 index 0000000..e69de29 diff --git a/librashader-runtime-vk/src/queue_selection.rs b/librashader-runtime-vk/src/queue_selection.rs new file mode 100644 index 0000000..37fa105 --- /dev/null +++ b/librashader-runtime-vk/src/queue_selection.rs @@ -0,0 +1,24 @@ +use ash::vk; + +fn find_graphics_queue_family( + instance: &ash::Instance, + physical_device: vk::PhysicalDevice, +) -> u32 { + let queue_families = + unsafe { instance.get_physical_device_queue_family_properties(physical_device) }; + // find the most specialized transfer queue. + for (index, queue_family) in queue_families.iter().enumerate() { + if queue_family.queue_count > 0 + && queue_family.queue_flags.contains(vk::QueueFlags::GRAPHICS) + { + return index as u32 + } + } + + return 0 +} + +pub fn get_graphics_queue(instance: &ash::Instance, device: &ash::Device, physical_device: vk::PhysicalDevice) -> vk::Queue { + let queue_family = find_graphics_queue_family(instance, physical_device); + unsafe { device.get_device_queue(queue_family, 0) } +} \ No newline at end of file