rt(vk): allow specifying the queue to use

This commit is contained in:
chyyran 2024-08-25 01:50:47 -04:00 committed by Ronny Chan
parent 16108838b1
commit aeb0a16cfb
6 changed files with 95 additions and 35 deletions

View file

@ -268,6 +268,9 @@ typedef struct libra_device_vk_t {
/// A raw `VkDevice` handle
/// for the device attached to the instance that will perform rendering.
VkDevice device;
/// The queue to use, if this is `NULL`, then
/// a suitable queue will be chosen.
VkQueue queue;
/// The entry loader for the Vulkan library.
PFN_vkGetInstanceProcAddr entry;
} libra_device_vk_t;

View file

@ -173,6 +173,7 @@ include = [
exclude = [
"Option_ID3D11DeviceContext",
"Option_PFN_vkGetInstanceProcAddr",
"PMTLCommandQueue",
"PMTLCommandBuffer",
"PMTLTexture"
@ -198,6 +199,7 @@ exclude = [
"CommandBuffer" = "VkCommandBuffer"
"Format" = "VkFormat"
"Image" = "VkImage"
"Queue" = "VkQueue"
# hack to get proper pointer indirection for COM pointers
# we don't need one for ID3D11DeviceContext.
@ -214,6 +216,9 @@ exclude = [
# hack to force cbindgen to not generate option type for nullable ID3D11DeviceContext.
"Option_ID3D11DeviceContext" = "ID3D11DeviceContext *"
# hack to force cbindgen to not generate option type for nullable PFN_vkGetInstanceProcAddr.
"Option_PFN_vkGetInstanceProcAddr" = "PFN_vkGetInstanceProcAddr"
# hack to get proper pointer indirection for COM pointers
"ID3D12Device" = "ID3D12Device *"
"ID3D12Resource" = "ID3D12Resource *"

View file

@ -15,9 +15,9 @@ use std::slice;
use librashader::runtime::FilterChainParameters;
use librashader::runtime::{Size, Viewport};
use ash::vk;
use crate::LIBRASHADER_API_VERSION;
use ash::vk;
use ash::vk::Handle;
pub use ash::vk::PFN_vkGetInstanceProcAddr;
/// A Vulkan instance function loader that the Vulkan filter chain needs to be initialized with.
@ -49,8 +49,11 @@ pub struct libra_device_vk_t {
/// A raw `VkDevice` handle
/// for the device attached to the instance that will perform rendering.
pub device: vk::Device,
/// The queue to use, if this is `NULL`, then
/// a suitable queue will be chosen. This must be a graphics queue.
pub queue: vk::Queue,
/// The entry loader for the Vulkan library.
pub entry: vk::PFN_vkGetInstanceProcAddr,
pub entry: Option<vk::PFN_vkGetInstanceProcAddr>,
}
impl From<libra_image_vk_t> for VulkanImage {
@ -65,11 +68,18 @@ impl From<libra_image_vk_t> for VulkanImage {
impl From<libra_device_vk_t> for VulkanInstance {
fn from(value: libra_device_vk_t) -> Self {
let queue = if value.queue.is_null() {
None
} else {
Some(value.queue)
};
VulkanInstance {
device: value.device,
instance: value.instance,
physical_device: value.physical_device,
get_instance_proc_addr: value.entry,
queue,
}
}
}

View file

@ -10,6 +10,8 @@ use thiserror::Error;
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum FilterChainError {
#[error("a vulkan handle that is required to be not null is null")]
HandleIsNull,
#[error("shader preset parse error")]
ShaderPresetError(#[from] ParsePresetError),
#[error("shader preprocess error")]

View file

@ -13,39 +13,38 @@ use crate::{error, memory, util};
use ash::vk;
use librashader_common::{ImageFormat, Size, Viewport};
use ash::vk::Handle;
use gpu_allocator::vulkan::Allocator;
use librashader_cache::CachedCompilation;
use librashader_common::map::FastHashMap;
use librashader_presets::context::VideoDriver;
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_reflect::back::targets::SPIRV;
use librashader_reflect::back::{CompileReflectShader, CompileShader};
use librashader_reflect::front::SpirvCompilation;
use librashader_reflect::reflect::cross::SpirvCross;
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_reflect::reflect::semantics::ShaderSemantics;
use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::binding::BindingUtil;
use librashader_runtime::framebuffer::FramebufferInit;
use librashader_runtime::image::{Image, ImageError, UVDirection, BGRA8};
use librashader_runtime::quad::QuadType;
use librashader_runtime::render_target::RenderTarget;
use librashader_runtime::scaling::ScaleFramebuffer;
use librashader_runtime::uniforms::UniformStorage;
use parking_lot::Mutex;
use rayon::prelude::*;
use std::collections::VecDeque;
use std::convert::Infallible;
use std::path::Path;
use std::sync::Arc;
use librashader_cache::CachedCompilation;
use librashader_presets::context::VideoDriver;
use librashader_reflect::reflect::cross::SpirvCross;
use librashader_runtime::framebuffer::FramebufferInit;
use librashader_runtime::render_target::RenderTarget;
use librashader_runtime::scaling::ScaleFramebuffer;
use rayon::prelude::*;
/// A Vulkan device and metadata that is required by the shader runtime.
pub struct VulkanObjects {
pub(crate) device: Arc<ash::Device>,
pub(crate) alloc: Arc<Mutex<Allocator>>,
queue: vk::Queue,
// pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties,
}
/// A collection of handles needed to access the Vulkan instance.
@ -58,27 +57,43 @@ pub struct VulkanInstance {
/// A `VkPhysicalDevice` handle.
pub physical_device: vk::PhysicalDevice,
/// A function pointer to the Vulkan library entry point.
pub get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr,
/// If this is `None`, [`FilterChainError::HandleIsNull`] will be returned.
pub get_instance_proc_addr: Option<vk::PFN_vkGetInstanceProcAddr>,
/// The graphics queue to use to submit commands. If this is `None`,
/// a queue will be chosen.
pub queue: Option<vk::Queue>,
}
impl TryFrom<VulkanInstance> for VulkanObjects {
type Error = FilterChainError;
fn try_from(vulkan: VulkanInstance) -> Result<Self, FilterChainError> {
if vulkan.queue.is_some_and(|q| q.is_null())
|| vulkan.device.is_null()
|| vulkan.instance.is_null()
{
return Err(FilterChainError::HandleIsNull);
};
let Some(get_instance_proc_addr) = vulkan.get_instance_proc_addr else {
return Err(FilterChainError::HandleIsNull);
};
unsafe {
let instance = ash::Instance::load(
&ash::StaticFn {
get_instance_proc_addr: vulkan.get_instance_proc_addr,
get_instance_proc_addr,
},
vulkan.instance,
);
let device = ash::Device::load(instance.fp_v1_0(), vulkan.device);
let queue = get_graphics_queue(&instance, &device, vulkan.physical_device);
// let memory_properties =
// instance.get_physical_device_memory_properties(vulkan.physical_device);
let queue = vulkan.queue.unwrap_or(get_graphics_queue(
&instance,
&device,
vulkan.physical_device,
));
let alloc = memory::create_allocator(device.clone(), instance, vulkan.physical_device)?;
@ -86,8 +101,6 @@ impl TryFrom<VulkanInstance> for VulkanObjects {
device: Arc::new(device),
alloc,
queue,
// memory_properties,
// debug,
})
}
}
@ -97,20 +110,47 @@ impl TryFrom<(vk::PhysicalDevice, ash::Instance, ash::Device)> for VulkanObjects
type Error = FilterChainError;
fn try_from(value: (vk::PhysicalDevice, ash::Instance, ash::Device)) -> error::Result<Self> {
if value.0.is_null() {
return Err(FilterChainError::HandleIsNull);
}
let device = value.2;
let queue = get_graphics_queue(&value.1, &device, value.0);
// let memory_properties = value.1.get_physical_device_memory_properties(value.0);
let alloc = memory::create_allocator(device.clone(), value.1, value.0)?;
Ok(VulkanObjects {
alloc,
device: Arc::new(device),
queue,
// memory_properties,
// debug: value.3,
})
}
}
impl TryFrom<(vk::PhysicalDevice, ash::Instance, ash::Device, vk::Queue)> for VulkanObjects {
type Error = FilterChainError;
fn try_from(
value: (vk::PhysicalDevice, ash::Instance, ash::Device, vk::Queue),
) -> error::Result<Self> {
if value.0.is_null() {
return Err(FilterChainError::HandleIsNull);
}
let device = value.2;
let queue = if value.3.is_null() {
get_graphics_queue(&value.1, &device, value.0)
} else {
value.3
};
let alloc = memory::create_allocator(device.clone(), value.1, value.0)?;
Ok(VulkanObjects {
alloc,
device: Arc::new(device),
queue,
})
}
}

View file

@ -237,6 +237,16 @@ impl VulkanWindow {
// vk::QUEUE_FAMILY_IGNORED
// );
let viewport = Viewport::new_render_target_sized_origin(
VulkanImage {
size: vulkan.swapchain.extent.into(),
image: swapchain_image,
format: vulkan.swapchain.format.format,
},
None,
)
.unwrap();
filter
.frame(
&VulkanImage {
@ -244,17 +254,7 @@ impl VulkanWindow {
image: framebuffer_image,
format: vulkan.swapchain.format.format,
},
&Viewport {
x: 0.0,
y: 0.0,
output: VulkanImage {
size: vulkan.swapchain.extent.into(),
image: swapchain_image,
format: vulkan.swapchain.format.format,
},
mvp: None,
size: vulkan.swapchain.extent.into(),
},
&viewport,
cmd,
frame,
Some(&FrameOptionsVulkan {