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 /// A raw `VkDevice` handle
/// for the device attached to the instance that will perform rendering. /// for the device attached to the instance that will perform rendering.
VkDevice device; 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. /// The entry loader for the Vulkan library.
PFN_vkGetInstanceProcAddr entry; PFN_vkGetInstanceProcAddr entry;
} libra_device_vk_t; } libra_device_vk_t;

View file

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

View file

@ -15,9 +15,9 @@ use std::slice;
use librashader::runtime::FilterChainParameters; use librashader::runtime::FilterChainParameters;
use librashader::runtime::{Size, Viewport}; use librashader::runtime::{Size, Viewport};
use ash::vk;
use crate::LIBRASHADER_API_VERSION; use crate::LIBRASHADER_API_VERSION;
use ash::vk;
use ash::vk::Handle;
pub use ash::vk::PFN_vkGetInstanceProcAddr; pub use ash::vk::PFN_vkGetInstanceProcAddr;
/// A Vulkan instance function loader that the Vulkan filter chain needs to be initialized with. /// 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 /// A raw `VkDevice` handle
/// for the device attached to the instance that will perform rendering. /// for the device attached to the instance that will perform rendering.
pub device: vk::Device, 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. /// 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 { 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 { impl From<libra_device_vk_t> for VulkanInstance {
fn from(value: libra_device_vk_t) -> Self { fn from(value: libra_device_vk_t) -> Self {
let queue = if value.queue.is_null() {
None
} else {
Some(value.queue)
};
VulkanInstance { VulkanInstance {
device: value.device, device: value.device,
instance: value.instance, instance: value.instance,
physical_device: value.physical_device, physical_device: value.physical_device,
get_instance_proc_addr: value.entry, get_instance_proc_addr: value.entry,
queue,
} }
} }
} }

View file

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

View file

@ -13,39 +13,38 @@ use crate::{error, memory, util};
use ash::vk; use ash::vk;
use librashader_common::{ImageFormat, Size, Viewport}; use librashader_common::{ImageFormat, Size, Viewport};
use ash::vk::Handle;
use gpu_allocator::vulkan::Allocator; use gpu_allocator::vulkan::Allocator;
use librashader_cache::CachedCompilation;
use librashader_common::map::FastHashMap; use librashader_common::map::FastHashMap;
use librashader_presets::context::VideoDriver;
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_reflect::back::targets::SPIRV; use librashader_reflect::back::targets::SPIRV;
use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::back::{CompileReflectShader, CompileShader};
use librashader_reflect::front::SpirvCompilation; use librashader_reflect::front::SpirvCompilation;
use librashader_reflect::reflect::cross::SpirvCross;
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_reflect::reflect::semantics::ShaderSemantics; use librashader_reflect::reflect::semantics::ShaderSemantics;
use librashader_reflect::reflect::ReflectShader; use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::binding::BindingUtil; use librashader_runtime::binding::BindingUtil;
use librashader_runtime::framebuffer::FramebufferInit;
use librashader_runtime::image::{Image, ImageError, UVDirection, BGRA8}; use librashader_runtime::image::{Image, ImageError, UVDirection, BGRA8};
use librashader_runtime::quad::QuadType; use librashader_runtime::quad::QuadType;
use librashader_runtime::render_target::RenderTarget;
use librashader_runtime::scaling::ScaleFramebuffer;
use librashader_runtime::uniforms::UniformStorage; use librashader_runtime::uniforms::UniformStorage;
use parking_lot::Mutex; use parking_lot::Mutex;
use rayon::prelude::*;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::convert::Infallible; use std::convert::Infallible;
use std::path::Path; use std::path::Path;
use std::sync::Arc; 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. /// A Vulkan device and metadata that is required by the shader runtime.
pub struct VulkanObjects { pub struct VulkanObjects {
pub(crate) device: Arc<ash::Device>, pub(crate) device: Arc<ash::Device>,
pub(crate) alloc: Arc<Mutex<Allocator>>, pub(crate) alloc: Arc<Mutex<Allocator>>,
queue: vk::Queue, queue: vk::Queue,
// pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties,
} }
/// A collection of handles needed to access the Vulkan instance. /// A collection of handles needed to access the Vulkan instance.
@ -58,27 +57,43 @@ pub struct VulkanInstance {
/// A `VkPhysicalDevice` handle. /// A `VkPhysicalDevice` handle.
pub physical_device: vk::PhysicalDevice, pub physical_device: vk::PhysicalDevice,
/// A function pointer to the Vulkan library entry point. /// 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 { impl TryFrom<VulkanInstance> for VulkanObjects {
type Error = FilterChainError; type Error = FilterChainError;
fn try_from(vulkan: VulkanInstance) -> Result<Self, 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 { unsafe {
let instance = ash::Instance::load( let instance = ash::Instance::load(
&ash::StaticFn { &ash::StaticFn {
get_instance_proc_addr: vulkan.get_instance_proc_addr, get_instance_proc_addr,
}, },
vulkan.instance, vulkan.instance,
); );
let device = ash::Device::load(instance.fp_v1_0(), vulkan.device); let device = ash::Device::load(instance.fp_v1_0(), vulkan.device);
let queue = get_graphics_queue(&instance, &device, vulkan.physical_device); let queue = vulkan.queue.unwrap_or(get_graphics_queue(
&instance,
// let memory_properties = &device,
// instance.get_physical_device_memory_properties(vulkan.physical_device); vulkan.physical_device,
));
let alloc = memory::create_allocator(device.clone(), instance, 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), device: Arc::new(device),
alloc, alloc,
queue, queue,
// memory_properties,
// debug,
}) })
} }
} }
@ -97,20 +110,47 @@ impl TryFrom<(vk::PhysicalDevice, ash::Instance, ash::Device)> for VulkanObjects
type Error = FilterChainError; type Error = FilterChainError;
fn try_from(value: (vk::PhysicalDevice, ash::Instance, ash::Device)) -> error::Result<Self> { 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 device = value.2;
let queue = get_graphics_queue(&value.1, &device, value.0); 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)?; let alloc = memory::create_allocator(device.clone(), value.1, value.0)?;
Ok(VulkanObjects { Ok(VulkanObjects {
alloc, alloc,
device: Arc::new(device), device: Arc::new(device),
queue, 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 // 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 filter
.frame( .frame(
&VulkanImage { &VulkanImage {
@ -244,17 +254,7 @@ impl VulkanWindow {
image: framebuffer_image, image: framebuffer_image,
format: vulkan.swapchain.format.format, format: vulkan.swapchain.format.format,
}, },
&Viewport { &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(),
},
cmd, cmd,
frame, frame,
Some(&FrameOptionsVulkan { Some(&FrameOptionsVulkan {