vk: do own queue selection and fix error type

This commit is contained in:
chyyran 2023-01-13 01:19:41 -05:00
parent 455b56ce8e
commit 40b9f08234
8 changed files with 123 additions and 79 deletions

View file

@ -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<T> = std::result::Result<T, Box<dyn Error>>;
#[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<T> = std::result::Result<T, FilterChainError>;

View file

@ -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<VulkanInfo<'_>> for Vulkan {
type Error = Box<dyn Error>;
impl TryFrom<VulkanInfo> for Vulkan {
type Error = FilterChainError;
fn try_from(vulkan: VulkanInfo) -> Result<Self, Box<dyn Error>> {
fn try_from(vulkan: VulkanInfo) -> Result<Self, FilterChainError> {
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<VulkanInfo<'_>> for Vulkan {
impl
TryFrom<(
vk::PhysicalDevice,
ash::Instance,
ash::Device,
vk::Queue,
vk::PhysicalDeviceMemoryProperties,
DebugUtils,
)> for Vulkan
{
type Error = Box<dyn Error>;
type Error = FilterChainError;
fn try_from(
value: (
Device,
Queue,
vk::PhysicalDeviceMemoryProperties,
DebugUtils,
vk::PhysicalDevice,
ash::Instance,
ash::Device,
),
) -> error::Result<Self> {
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, Error = Box<dyn Error>>,
vulkan: impl TryInto<Vulkan, Error = FilterChainError>,
path: impl AsRef<Path>,
options: Option<&FilterChainOptionsVulkan>,
) -> error::Result<FilterChainVulkan> {
@ -237,7 +214,7 @@ impl FilterChainVulkan {
}
pub fn load_from_preset(
vulkan: impl TryInto<Vulkan, Error = Box<dyn Error>>,
vulkan: impl TryInto<Vulkan, Error = FilterChainError>,
preset: ShaderPreset,
options: Option<&FilterChainOptionsVulkan>,
) -> error::Result<FilterChainVulkan> {
@ -325,7 +302,7 @@ impl FilterChainVulkan {
}),
);
}
Ok::<_, Box<dyn Error>>((shader, source, reflect))
Ok::<_, FilterChainError>((shader, source, reflect))
})
.into_iter()
.collect::<error::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>(
@ -431,11 +408,21 @@ impl FilterChainVulkan {
textures: &[TextureConfig],
) -> error::Result<FxHashMap<usize, LutTexture>> {
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)
}

View file

@ -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)
}

View file

@ -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<dyn Error>;
type Error = FilterChainError;
fn try_from(value: &VulkanBase) -> Result<Self, Self::Error> {
Vulkan::try_from((
value.physical_device,
value.instance.clone(),
value.device.clone(),
value.graphics_queue.clone(),
value.mem_props,
value.debug.loader.clone(),
))
}
}

View file

@ -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 {

View file

@ -16,7 +16,7 @@ pub struct LutTexture {
impl LutTexture {
pub fn new(
vulkan: &Vulkan,
cmd: &vk::CommandBuffer,
cmd: vk::CommandBuffer,
image: Image<BGRA8>,
config: &TextureConfig,
) -> error::Result<LutTexture> {
@ -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 {

View file

View file

@ -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) }
}