capi: finish capi for vulkan

This commit is contained in:
chyyran 2023-01-13 17:59:22 -05:00
parent 45d03fbfb8
commit 3e628093ae
27 changed files with 444 additions and 80 deletions

5
Cargo.lock generated
View file

@ -22,9 +22,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "ash"
version = "0.37.1+1.3.235"
version = "0.37.2+1.3.238"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "911015c962d56e2e4052f40182ca5462ba60a3d2ff04e827c365a0ab3d65726d"
checksum = "28bf19c1f0a470be5fbf7522a308a05df06610252c5bcf5143e1b23f629a9a03"
dependencies = [
"libloading",
]
@ -787,6 +787,7 @@ dependencies = [
name = "librashader-capi"
version = "0.1.0-alpha.5"
dependencies = [
"ash",
"gl",
"librashader",
"paste",

View file

@ -6,7 +6,8 @@
librashader (*/ˈli:brəʃeɪdɚ/*) is a preprocessor, compiler, and runtime for RetroArch 'slang' shaders, rewritten in pure Rust.
Heavily WIP.
[![Latest Version](https://img.shields.io/crates/v/librashader.svg)](https://crates.io/crates/librashader) [![Docs](https://docs.rs/librashader/badge.svg)](https://docs.rs/librashader) ![License](https://img.shields.io/crates/l/librashader)
![Nightly rust](https://img.shields.io/badge/rust-nightly-orange.svg)
## Supported Render APIs
librashader supports OpenGL 3, OpenGL 4.6, Vulkan, DirectX 11, and DirectX 12. Older versions

View file

@ -15,9 +15,10 @@ description = "RetroArch shaders for all."
crate-type = [ "cdylib", "staticlib" ]
[features]
default = ["runtime-opengl", "runtime-d3d11"]
default = ["runtime-opengl", "runtime-d3d11", "runtime-vulkan"]
runtime-opengl = ["gl", "librashader/gl"]
runtime-d3d11 = ["windows", "librashader/d3d11"]
runtime-vulkan = ["ash", "librashader/vk"]
[dependencies]
librashader = { path = "../librashader", version = "0.1.0-alpha.5" }
@ -25,6 +26,7 @@ thiserror = "1.0.37"
paste = "1.0.9"
gl = { version = "0.14.0", optional = true }
rustc-hash = "1.1.0"
ash = { version = "0.37.2+1.3.238", optional = true }
[dependencies.windows]
version = "0.43.0"

View file

@ -4,13 +4,14 @@ include_guard = "__LIBRASHADER_H__"
pragma_once = true
usize_is_size_t = true
documentation_style = "c++"
after_includes = "#ifdef _WIN32 && RUNTIME_D3D11 \n#include <d3d11.h>\n#else\ntypedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;\n#endif"
after_includes = "#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D11)\n#include <d3d11.h>\n#else\ntypedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;\n#endif\n#if defined(LIBRA_RUNTIME_VULKAN)\n#include <vulkan\\vulkan.h>\n#endif"
[defines]
"feature = runtime-opengl" = "LIBRA_RUNTIME_OPENGL"
"feature = runtime-d3d11" = "LIBRA_RUNTIME_D3D11"
"feature = runtime-vulkan" = "LIBRA_RUNTIME_VULKAN"
[parse]
parse_deps = true
@ -19,7 +20,8 @@ include = ["librashader",
"librashader-preprocess",
"librashader-reflect",
"librashader-runtime-gl",
"librashader-runtime-d3d11"
"librashader-runtime-d3d11",
"librashader-runtime-vk",
]
expand = ["librashader-capi"]
@ -66,4 +68,15 @@ include = [
"FrameOptionsGL" = "frame_gl_opt_t"
"FilterChainD3D11" = "_filter_chain_d3d11"
"FilterChainOptionsD3D11" = "filter_chain_d3d11_opt_t"
"FrameOptionsD3D11" = "frame_d3d11_opt_t"
"FrameOptionsD3D11" = "frame_vk_opt_t"
"FilterChainVulkan" = "_filter_chain_vk"
"FilterChainOptionsVulkan" = "filter_chain_vk_opt_t"
"FrameOptionsVullam" = "frame_vk_opt_t"
# vulkan renames
"PhysicalDevice" = "VkPhysicalDevice"
"Instance" = "VkInstance"
"Device" = "VkDevice"
"CommandBuffer" = "VkCommandBuffer"
"Format" = "VkFormat"
"Image" = "VkImage"

View file

@ -8,11 +8,14 @@
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef _WIN32 && RUNTIME_D3D11
#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D11)
#include <d3d11.h>
#else
typedef void ID3D11Device; typedef void ID3D11RenderTargetView; typedef void ID3D1ShaderResourceView;
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
#include <vulkan\vulkan.h>
#endif
/// Error codes for librashader error types.
enum LIBRA_ERRNO
@ -32,7 +35,13 @@ typedef int32_t LIBRA_ERRNO;
#endif // __cplusplus
/// A Direct3D 11 filter chain.
typedef struct FilterChain FilterChain;
typedef struct _filter_chain_d3d11 _filter_chain_d3d11;
/// An OpenGL filter chain.
typedef struct _filter_chain_gl _filter_chain_gl;
/// A Vulkan filter chain.
typedef struct _filter_chain_vk _filter_chain_vk;
/// The error type for librashader.
typedef struct _libra_error _libra_error;
@ -49,23 +58,21 @@ typedef struct _shader_preset* libra_shader_preset_t;
#if defined(LIBRA_RUNTIME_OPENGL)
/// A GL function loader that librashader needs to be initialized with.
typedef const void* (*gl_loader_t)(const char*);
typedef const void* (*libra_gl_loader_t)(const char*);
#endif
/// Options for Direct3D11 filter chain creation.
typedef struct FilterChainOptions {
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
bool use_deferred_context;
/// Whether or not to explicitly disable mipmap
/// generation regardless of shader preset settings.
/// Options for filter chain creation.
typedef struct filter_chain_gl_opt_t {
/// The GLSL version. Should be at least `330`.
uint16_t gl_version;
/// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+.
bool use_dsa;
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings.
bool force_no_mipmaps;
} FilterChainOptions;
} filter_chain_gl_opt_t;
#if defined(LIBRA_RUNTIME_OPENGL)
typedef struct FilterChain* libra_gl_filter_chain_t;
typedef struct _filter_chain_gl* libra_gl_filter_chain_t;
#endif
#if defined(LIBRA_RUNTIME_OPENGL)
@ -102,16 +109,28 @@ typedef struct libra_draw_framebuffer_gl_t {
} libra_draw_framebuffer_gl_t;
#endif
/// Options for each Direct3D11 shader frame.
typedef struct FrameOptions {
/// Options for each OpenGL shader frame.
typedef struct frame_gl_opt_t {
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of the frame. 1 should be vertical.
int32_t frame_direction;
} FrameOptions;
} frame_gl_opt_t;
/// Options for Direct3D11 filter chain creation.
typedef struct filter_chain_d3d11_opt_t {
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
bool use_deferred_context;
/// Whether or not to explicitly disable mipmap
/// generation regardless of shader preset settings.
bool force_no_mipmaps;
} filter_chain_d3d11_opt_t;
#if defined(LIBRA_RUNTIME_D3D11)
typedef struct FilterChain* libra_d3d11_filter_chain_t;
typedef struct _filter_chain_d3d11* libra_d3d11_filter_chain_t;
#endif
#if defined(LIBRA_RUNTIME_D3D11)
@ -126,6 +145,65 @@ typedef struct libra_source_image_d3d11_t {
} libra_source_image_d3d11_t;
#endif
/// Options for each Direct3D11 shader frame.
typedef struct frame_vk_opt_t {
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of the frame. 1 should be vertical.
int32_t frame_direction;
} frame_vk_opt_t;
#if defined(LIBRA_RUNTIME_VULKAN)
/// Handles required to instantiate vulkan
typedef struct libra_device_vk_t {
/// A raw `VkPhysicalDevice` handle
/// for the physical device that will perform rendering.
VkPhysicalDevice physical_device;
/// A raw `VkInstance` handle
/// for the Vulkan instance that will perform rendering.
VkInstance instance;
/// A raw `VkDevice` handle
/// for the device attached to the instance that will perform rendering.
VkDevice device;
/// The entry loader for the Vulkan library.
PFN_vkGetInstanceProcAddr entry;
} libra_device_vk_t;
#endif
/// Options for filter chain creation.
typedef struct filter_chain_vk_opt_t {
/// The number of frames in flight to keep. If zero, defaults to three.
uint32_t frames_in_flight;
/// Whether or not to explicitly disable mipmap generation regardless of shader preset settings.
bool force_no_mipmaps;
} filter_chain_vk_opt_t;
#if defined(LIBRA_RUNTIME_VULKAN)
typedef struct _filter_chain_vk* libra_vk_filter_chain_t;
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Vulkan parameters for the source image.
typedef struct libra_image_vk_t {
/// A raw `VkImage` handle to the source image.
VkImage handle;
/// The `VkFormat` of the source image.
VkFormat format;
/// The width of the source image.
uint32_t width;
/// The height of the source image.
uint32_t height;
} libra_image_vk_t;
#endif
/// Options for each Vulkan shader frame.
typedef struct FrameOptionsVulkan {
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of the frame. 1 should be vertical.
int32_t frame_direction;
} FrameOptionsVulkan;
typedef libra_error_t(*PFN_libra_preset_free)(libra_shader_preset_t* preset);
typedef libra_error_t(*PFN_libra_preset_set_param)(libra_shader_preset_t* preset,
@ -152,12 +230,12 @@ typedef int32_t(*PFN_libra_error_write)(libra_error_t error, char** out);
typedef int32_t(*PFN_libra_error_free_string)(char** out);
#if defined(LIBRA_RUNTIME_OPENGL)
typedef libra_error_t(*PFN_libra_gl_init_context)(gl_loader_t loader);
typedef libra_error_t(*PFN_libra_gl_init_context)(libra_gl_loader_t loader);
#endif
#if defined(LIBRA_RUNTIME_OPENGL)
typedef libra_error_t(*PFN_libra_gl_filter_chain_create)(libra_shader_preset_t* preset,
const struct FilterChainOptions* options,
const struct filter_chain_gl_opt_t* options,
libra_gl_filter_chain_t* out);
#endif
@ -168,7 +246,7 @@ typedef libra_error_t(*PFN_libra_gl_filter_chain_frame)(libra_gl_filter_chain_t*
struct libra_viewport_t viewport,
struct libra_draw_framebuffer_gl_t out,
const float* mvp,
const struct FrameOptions* opt);
const struct frame_gl_opt_t* opt);
#endif
#if defined(LIBRA_RUNTIME_OPENGL)
@ -177,7 +255,7 @@ typedef libra_error_t(*PFN_libra_gl_filter_chain_free)(libra_gl_filter_chain_t*
#if defined(LIBRA_RUNTIME_D3D11)
typedef libra_error_t(*PFN_libra_d3d11_filter_chain_create)(libra_shader_preset_t* preset,
const struct FilterChainOptions* options,
const struct filter_chain_d3d11_opt_t* options,
const ID3D11Device* device,
libra_d3d11_filter_chain_t* out);
#endif
@ -189,7 +267,7 @@ typedef libra_error_t(*PFN_libra_d3d11_filter_chain_frame)(libra_d3d11_filter_ch
struct libra_viewport_t viewport,
const ID3D11RenderTargetView* out,
const float* mvp,
const struct FrameOptions* opt);
const struct frame_vk_opt_t* opt);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
@ -294,7 +372,7 @@ extern "C" {
///
/// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter
/// chain objects, and drawing with them causes immediate undefined behaviour.
libra_error_t libra_gl_init_context(gl_loader_t loader);
libra_error_t libra_gl_init_context(libra_gl_loader_t loader);
#endif
#if defined(LIBRA_RUNTIME_OPENGL)
@ -308,7 +386,7 @@ extern "C" {
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t* preset,
const struct FilterChainOptions* options,
const struct filter_chain_gl_opt_t* options,
libra_gl_filter_chain_t* out);
#endif
@ -328,7 +406,7 @@ extern "C" {
struct libra_viewport_t viewport,
struct libra_draw_framebuffer_gl_t out,
const float* mvp,
const struct FrameOptions* opt);
const struct frame_gl_opt_t* opt);
#endif
#if defined(LIBRA_RUNTIME_OPENGL)
@ -351,7 +429,7 @@ extern "C" {
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t* preset,
const struct FilterChainOptions* options,
const struct filter_chain_d3d11_opt_t* options,
const ID3D11Device* device,
libra_d3d11_filter_chain_t* out);
#endif
@ -372,7 +450,7 @@ extern "C" {
struct libra_viewport_t viewport,
const ID3D11RenderTargetView* out,
const float* mvp,
const struct FrameOptions* opt);
const struct frame_vk_opt_t* opt);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
@ -384,6 +462,59 @@ extern "C" {
libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t* chain);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - The handles provided in `vulkan` must be valid for the command buffers that
/// `libra_vk_filter_chain_frame` will write to. Namely, the VkDevice must have been
/// created with the `VK_KHR_dynamic_rendering` extension.
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
libra_error_t libra_vk_filter_chain_create(struct libra_device_vk_t vulkan,
libra_shader_preset_t* preset,
const struct filter_chain_vk_opt_t* options,
libra_vk_filter_chain_t* out);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command buffer.
///
/// librashader will not do any queue submissions.
///
/// ## Safety
/// - `libra_vk_filter_chain_frame` **must not be called within a RenderPass**.
/// - `command_buffer` must be a valid handle to a `VkCommandBuffer` that is ready for recording.
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
libra_error_t libra_vk_filter_chain_frame(libra_vk_filter_chain_t* chain,
VkCommandBuffer command_buffer,
size_t frame_count,
struct libra_image_vk_t image,
struct libra_viewport_t viewport,
struct libra_image_vk_t out,
const float* mvp,
const struct FrameOptionsVulkan* opt);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
/// Free a GL filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
libra_error_t libra_vk_filter_chain_free(libra_vk_filter_chain_t* chain);
#endif
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View file

@ -13,6 +13,10 @@ pub type libra_gl_filter_chain_t = Option<NonNull<librashader::runtime::gl::capi
pub type libra_d3d11_filter_chain_t =
Option<NonNull<librashader::runtime::d3d11::capi::FilterChainD3D11>>;
#[cfg(feature = "runtime-vulkan")]
pub type libra_vk_filter_chain_t =
Option<NonNull<librashader::runtime::vk::capi::FilterChainVulkan>>;
/// Parameters for the output viewport.
#[repr(C)]
pub struct libra_viewport_t {

View file

@ -29,6 +29,9 @@ pub enum LibrashaderError {
#[cfg(feature = "runtime-d3d11")]
#[error("There was an error in the D3D11 filter chain.")]
D3D11FilterError(#[from] librashader::runtime::d3d11::error::FilterChainError),
#[cfg(feature = "runtime-vulkan")]
#[error("There was an error in the Vulkan filter chain.")]
VulkanFilterError(#[from] librashader::runtime::vk::error::FilterChainError),
}
/// Error codes for librashader error types.
@ -167,6 +170,8 @@ impl LibrashaderError {
LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
#[cfg(feature = "runtime-d3d11")]
LibrashaderError::D3D11FilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
#[cfg(feature = "runtime-vulkan")]
LibrashaderError::VulkanFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
}
}
pub(crate) const fn ok() -> libra_error_t {

View file

@ -4,9 +4,9 @@
//! possible by linking against `librashader.h` as well as any static libraries used by `librashader`.
//!
//! ## Usage
//! ⚠ Rust consumers should take a look at [librashader](https://docs.rs/librashader/)
//! ⚠ Rust consumers use [librashader](https://docs.rs/librashader/) directly instead.
//!
//! The C API is designed to be easy to use and safe. Most objects are only accessible behind an opaque pointer.
//! The librashader C API is designed to be easy to use and safe. Most objects are only accessible behind an opaque pointer.
//! Every allocated object can be freed with a corresponding `free` function **for that specific object type**.
//!
//! Once an object is freed, the input pointer is always set to null. Attempting to free an object that was not
@ -44,6 +44,7 @@ mod ffi;
pub mod presets;
#[cfg(feature = "reflect")]
#[doc(hidden)]
pub mod reflect;
pub mod runtime;

View file

@ -7,11 +7,6 @@ use std::ffi::{c_char, CStr, CString};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
pub type PFN_lbr_preset_create = unsafe extern "C" fn(
filename: *const c_char,
out: *mut MaybeUninit<libra_shader_preset_t>,
) -> libra_error_t;
extern_fn! {
/// Load a preset.
///

View file

@ -14,7 +14,7 @@ pub use librashader::runtime::gl::capi::options::FrameOptionsGL;
use librashader::runtime::{Size, Viewport};
/// A GL function loader that librashader needs to be initialized with.
pub type gl_loader_t = unsafe extern "C" fn(*const c_char) -> *const c_void;
pub type libra_gl_loader_t = unsafe extern "system" fn(*const c_char) -> *const c_void;
/// OpenGL parameters for the source image.
#[repr(C)]
@ -59,7 +59,7 @@ extern_fn! {
///
/// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter
/// chain objects, and drawing with them causes immediate undefined behaviour.
raw fn libra_gl_init_context(loader: gl_loader_t) {
raw fn libra_gl_init_context(loader: libra_gl_loader_t) {
gl::load_with(|s| unsafe {
let proc_name = CString::new(s).unwrap_unchecked();
loader(proc_name.as_ptr())

View file

@ -4,3 +4,6 @@ pub mod gl;
#[cfg(feature = "runtime-d3d11")]
pub mod d3d11;
#[cfg(feature = "runtime-vulkan")]
pub mod vk;

View file

@ -0,0 +1,183 @@
use std::ffi::{c_char, c_void};
use crate::ctypes::{
libra_vk_filter_chain_t, libra_shader_preset_t, libra_viewport_t,
};
use crate::error::{assert_non_null, assert_some_ptr};
use crate::ffi::extern_fn;
use librashader::runtime::vk::{VulkanImage, VulkanInstance};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
use std::slice;
pub use librashader::runtime::vk::capi::options::FilterChainOptionsVulkan;
pub use librashader::runtime::vk::capi::options::FrameOptionsVulkan;
use librashader::runtime::{Size, Viewport};
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.
pub type libra_PFN_vkGetInstanceProcAddr = unsafe extern "system" fn(instance: *mut c_void, p_name: *const c_char);
/// Vulkan parameters for the source image.
#[repr(C)]
pub struct libra_image_vk_t {
/// A raw `VkImage` handle to the source image.
pub handle: vk::Image,
/// The `VkFormat` of the source image.
pub format: vk::Format,
/// The width of the source image.
pub width: u32,
/// The height of the source image.
pub height: u32,
}
/// Handles required to instantiate vulkan
#[repr(C)]
pub struct libra_device_vk_t {
/// A raw `VkPhysicalDevice` handle
/// for the physical device that will perform rendering.
pub physical_device: vk::PhysicalDevice,
/// A raw `VkInstance` handle
/// for the Vulkan instance that will perform rendering.
pub instance: vk::Instance,
/// A raw `VkDevice` handle
/// for the device attached to the instance that will perform rendering.
pub device: vk::Device,
/// The entry loader for the Vulkan library.
pub entry: vk::PFN_vkGetInstanceProcAddr
}
impl From<libra_image_vk_t> for VulkanImage {
fn from(value: libra_image_vk_t) -> Self {
VulkanImage {
size: Size::new(value.width, value.height),
image: value.handle,
format: value.format,
}
}
}
impl From<libra_device_vk_t> for VulkanInstance {
fn from(value: libra_device_vk_t) -> Self {
VulkanInstance {
device: value.device,
instance: value.instance,
physical_device: value.physical_device,
get_instance_proc_addr: value.entry,
}
}
}
extern_fn! {
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - The handles provided in `vulkan` must be valid for the command buffers that
/// `libra_vk_filter_chain_frame` will write to. Namely, the VkDevice must have been
/// created with the `VK_KHR_dynamic_rendering` extension.
/// - `preset` must be either null, or valid and aligned.
/// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_vk_filter_chain_create(
vulkan: libra_device_vk_t,
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsVulkan,
out: *mut MaybeUninit<libra_vk_filter_chain_t>
) {
assert_non_null!(preset);
let preset = unsafe {
let preset_ptr = &mut *preset;
let preset = preset_ptr.take();
Box::from_raw(preset.unwrap().as_ptr())
};
let options = if options.is_null() {
None
} else {
Some(unsafe { &*options })
};
let vulkan: VulkanInstance = vulkan.into();
let chain = librashader::runtime::vk::capi::FilterChainVulkan::load_from_preset(vulkan, *preset, options)?;
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain,
)))))
}
}
}
extern_fn! {
/// Records rendering commands for a frame with the given parameters for the given filter chain
/// to the input command buffer.
///
/// librashader will not do any queue submissions.
///
/// ## Safety
/// - `libra_vk_filter_chain_frame` **must not be called within a RenderPass**.
/// - `command_buffer` must be a valid handle to a `VkCommandBuffer` that is ready for recording.
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
fn libra_vk_filter_chain_frame(
chain: *mut libra_vk_filter_chain_t,
command_buffer: vk::CommandBuffer,
frame_count: usize,
image: libra_image_vk_t,
viewport: libra_viewport_t,
out: libra_image_vk_t,
mvp: *const f32,
opt: *const FrameOptionsVulkan
) mut |chain| {
assert_some_ptr!(mut chain);
let image: VulkanImage = image.into();
let output = out.into();
let mvp = if mvp.is_null() {
None
} else {
Some(<&[f32; 16]>::try_from(unsafe { slice::from_raw_parts(mvp, 16) }).unwrap())
};
let opt = if opt.is_null() {
None
} else {
Some(unsafe { opt.read() })
};
let viewport = Viewport {
x: viewport.x,
y: viewport.y,
output,
mvp,
};
chain.frame(&image, &viewport, command_buffer, frame_count, opt.as_ref())?;
}
}
extern_fn! {
/// Free a GL filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
fn libra_vk_filter_chain_free(
chain: *mut libra_vk_filter_chain_t
) {
assert_non_null!(chain);
unsafe {
let chain_ptr = &mut *chain;
let chain = chain_ptr.take();
drop(Box::from_raw(chain.unwrap().as_ptr()))
};
}
}

View file

@ -0,0 +1,4 @@
//! C API for the librashader OpenGL Runtime (`libra_gl_*`)
mod filter_chain;
pub use filter_chain::*;

View file

@ -53,7 +53,7 @@ const NULL_TEXTURES: &[Option<ID3D11ShaderResourceView>; 16] = &[
// slang_process.cpp 229
impl FilterPass {
pub fn get_format(&self) -> ImageFormat {
let mut fb_format = self.source.format;
let fb_format = self.source.format;
if let Some(format) = self.config.get_format_override() {
format
} else if fb_format == ImageFormat::Unknown {

View file

@ -104,7 +104,7 @@ impl<T: GLInterface> FilterPass<T> {
impl<T: GLInterface> FilterPass<T> {
pub fn get_format(&self) -> ImageFormat {
let mut fb_format = self.source.format;
let fb_format = self.source.format;
if let Some(format) = self.config.get_format_override() {
format
} else if fb_format == ImageFormat::Unknown {

View file

@ -3,7 +3,7 @@ use crate::framebuffer::GLImage;
use crate::gl::framebuffer::Framebuffer;
use crate::gl::FramebufferInterface;
use crate::texture::Texture;
use gl::types::{GLenum, GLint, GLsizei, GLuint};
use gl::types::{GLenum, GLint, GLsizei};
use librashader_common::{ImageFormat, Size, Viewport};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ViewportSize};

View file

@ -3,7 +3,7 @@ use crate::framebuffer::GLImage;
use crate::gl::framebuffer::Framebuffer;
use crate::gl::FramebufferInterface;
use crate::texture::Texture;
use gl::types::{GLenum, GLint, GLsizei, GLuint};
use gl::types::{GLenum, GLint, GLsizei};
use librashader_common::{ImageFormat, Size, Viewport};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ViewportSize};

View file

@ -29,7 +29,7 @@ use std::path::Path;
use crate::options::{FilterChainOptionsVulkan, FrameOptionsVulkan};
/// A Vulkan device and metadata that is required by the shader runtime.
pub struct VulkanDevice {
pub struct VulkanObjects {
pub(crate) device: ash::Device,
pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties,
queue: vk::Queue,
@ -55,7 +55,7 @@ pub struct VulkanInstance {
pub get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr,
}
impl TryFrom<VulkanInstance> for VulkanDevice {
impl TryFrom<VulkanInstance> for VulkanObjects {
type Error = FilterChainError;
fn try_from(vulkan: VulkanInstance) -> Result<Self, FilterChainError> {
@ -76,7 +76,7 @@ impl TryFrom<VulkanInstance> for VulkanDevice {
let memory_properties =
instance.get_physical_device_memory_properties(vulkan.physical_device);
Ok(VulkanDevice {
Ok(VulkanObjects {
device,
queue,
pipeline_cache,
@ -87,7 +87,7 @@ impl TryFrom<VulkanInstance> for VulkanDevice {
}
}
impl TryFrom<(vk::PhysicalDevice, ash::Instance, ash::Device)> for VulkanDevice {
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> {
@ -100,7 +100,7 @@ impl TryFrom<(vk::PhysicalDevice, ash::Instance, ash::Device)> for VulkanDevice
let memory_properties = value.1.get_physical_device_memory_properties(value.0);
Ok(VulkanDevice {
Ok(VulkanObjects {
device,
queue,
pipeline_cache,
@ -115,7 +115,7 @@ impl TryFrom<(vk::PhysicalDevice, ash::Instance, ash::Device)> for VulkanDevice
pub struct FilterChainVulkan {
pub(crate) common: FilterCommon,
passes: Box<[FilterPass]>,
vulkan: VulkanDevice,
vulkan: VulkanObjects,
output_framebuffers: Box<[OwnedImage]>,
feedback_framebuffers: Box<[OwnedImage]>,
history_framebuffers: VecDeque<OwnedImage>,
@ -191,7 +191,7 @@ impl Drop for FrameResiduals {
impl FilterChainVulkan {
/// Load the shader preset at the given path into a filter chain.
pub fn load_from_path(
vulkan: impl TryInto<VulkanDevice, Error = FilterChainError>,
vulkan: impl TryInto<VulkanObjects, Error = FilterChainError>,
path: impl AsRef<Path>,
options: Option<&FilterChainOptionsVulkan>,
) -> error::Result<FilterChainVulkan> {
@ -202,7 +202,7 @@ impl FilterChainVulkan {
/// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset(
vulkan: impl TryInto<VulkanDevice, Error = FilterChainError>,
vulkan: impl TryInto<VulkanObjects, Error = FilterChainError>,
preset: ShaderPreset,
options: Option<&FilterChainOptionsVulkan>,
) -> error::Result<FilterChainVulkan> {
@ -328,7 +328,7 @@ impl FilterChainVulkan {
}
fn init_passes(
vulkan: &VulkanDevice,
vulkan: &VulkanObjects,
passes: Vec<ShaderPassMeta>,
semantics: &ShaderSemantics,
frames_in_flight: u32,
@ -402,7 +402,7 @@ impl FilterChainVulkan {
}
fn load_luts(
vulkan: &VulkanDevice,
vulkan: &VulkanObjects,
textures: &[TextureConfig],
) -> error::Result<FxHashMap<usize, LutTexture>> {
let mut luts = FxHashMap::default();
@ -462,7 +462,7 @@ impl FilterChainVulkan {
}
fn init_history(
vulkan: &VulkanDevice,
vulkan: &VulkanObjects,
filters: &[FilterPass],
) -> error::Result<(VecDeque<OwnedImage>, Box<[Option<InputImage>]>)> {
let mut required_images = 0;
@ -580,11 +580,11 @@ impl FilterChainVulkan {
/// the output image to the final layout.
pub fn frame(
&mut self,
count: usize,
viewport: &Viewport<VulkanImage>,
input: &VulkanImage,
viewport: &Viewport<VulkanImage>,
cmd: vk::CommandBuffer,
options: Option<FrameOptionsVulkan>,
count: usize,
options: Option<&FrameOptionsVulkan>,
) -> error::Result<()> {
let intermediates = &mut self.residuals[count % self.residuals.len()];
intermediates.dispose();

View file

@ -1,4 +1,4 @@
use crate::filter_chain::VulkanDevice;
use crate::filter_chain::VulkanObjects;
use crate::texture::VulkanImage;
use crate::{error, util};
use ash::vk;
@ -13,7 +13,7 @@ pub(crate) struct OutputImage {
}
impl OutputImage {
pub fn new(vulkan: &VulkanDevice, image: VulkanImage) -> error::Result<OutputImage> {
pub fn new(vulkan: &VulkanObjects, image: VulkanImage) -> error::Result<OutputImage> {
let image_subresource = vk::ImageSubresourceRange::builder()
.base_mip_level(0)
.base_array_layer(0)

View file

@ -8,7 +8,7 @@ mod swapchain;
mod syncobjects;
pub mod vulkan_base;
use crate::filter_chain::{FilterChainVulkan, VulkanDevice};
use crate::filter_chain::{FilterChainVulkan, VulkanObjects};
use crate::hello_triangle::command::VulkanCommandPool;
use crate::hello_triangle::framebuffer::VulkanFramebuffer;
use crate::hello_triangle::pipeline::VulkanPipeline;
@ -212,7 +212,11 @@ impl VulkanWindow {
filter
.frame(
frame,
&VulkanImage {
size: vulkan.swapchain.extent.into(),
image: framebuffer_image,
format: vulkan.swapchain.format.format,
},
&Viewport {
x: 0.0,
y: 0.0,
@ -223,12 +227,8 @@ impl VulkanWindow {
},
mvp: None,
},
&VulkanImage {
size: vulkan.swapchain.extent.into(),
image: framebuffer_image,
format: vulkan.swapchain.format.format,
},
cmd,
frame,
None,
)
.unwrap();

View file

@ -3,7 +3,7 @@ use std::borrow::Cow;
use std::error::Error;
use crate::error::FilterChainError;
use crate::filter_chain::VulkanDevice;
use crate::filter_chain::VulkanObjects;
use crate::hello_triangle::debug::VulkanDebug;
use crate::hello_triangle::physicaldevice::{find_queue_family, pick_physical_device};
use crate::hello_triangle::surface::VulkanSurface;
@ -158,11 +158,11 @@ impl Drop for VulkanBase {
}
}
impl TryFrom<&VulkanBase> for VulkanDevice {
impl TryFrom<&VulkanBase> for VulkanObjects {
type Error = FilterChainError;
fn try_from(value: &VulkanBase) -> Result<Self, Self::Error> {
VulkanDevice::try_from((
VulkanObjects::try_from((
value.physical_device,
value.instance.clone(),
value.device.clone(),

View file

@ -20,7 +20,7 @@ mod vulkan_primitives;
mod vulkan_state;
pub use filter_chain::FilterChainVulkan;
pub use filter_chain::VulkanDevice;
pub use filter_chain::VulkanObjects;
pub use filter_chain::VulkanInstance;
pub use texture::VulkanImage;

View file

@ -1,4 +1,4 @@
use crate::filter_chain::VulkanDevice;
use crate::filter_chain::VulkanObjects;
use crate::texture::{InputImage, VulkanImage};
use crate::vulkan_primitives::{VulkanBuffer, VulkanImageMemory};
use crate::{error, util};
@ -15,7 +15,7 @@ pub struct LutTexture {
impl LutTexture {
pub fn new(
vulkan: &VulkanDevice,
vulkan: &VulkanObjects,
cmd: vk::CommandBuffer,
image: Image<BGRA8>,
config: &TextureConfig,

View file

@ -1,4 +1,4 @@
use crate::filter_chain::VulkanDevice;
use crate::filter_chain::VulkanObjects;
use crate::util::find_vulkan_memory_type;
use crate::vulkan_primitives::VulkanImageMemory;
use crate::{error, util};
@ -114,7 +114,7 @@ impl OwnedImage {
}
pub fn new(
vulkan: &VulkanDevice,
vulkan: &VulkanObjects,
size: Size<u32>,
format: ImageFormat,
max_miplevels: u32,

View file

@ -28,6 +28,9 @@
//! | DirectX 9 | ❌ | |
//! | Metal | ❌ | |
//!
//! ## C API
//! For documentation on the librashader C API, see [librashader_capi](https://docs.rs/librashader-capi/latest/librashader_capi/),
//! or [`librashader.h`](https://github.com/SnowflakePowered/librashader/blob/master/librashader-capi/librashader.h).
#[cfg(feature = "presets")]
/// Parsing and usage of shader presets.
@ -150,7 +153,7 @@ pub mod runtime {
FrameOptionsVulkan as FrameOptions,
},
FilterChainVulkan as FilterChain,
VulkanImage, VulkanDevice, VulkanInstance,
VulkanImage, VulkanObjects, VulkanInstance,
error
};

View file

@ -4,7 +4,15 @@
#include <iostream>
#include <filesystem>
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
VK_DEFINE_HANDLE(VkInstance)
typedef void (*PFN_vkVoidFunction)(void);
typedef PFN_vkVoidFunction(*PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName);
#define LIBRA_RUNTIME_OPENGL
#define LIBRA_RUNTIME_VULKAN
#include "../../../../librashader-capi/librashader.h"
int main()
{
@ -16,8 +24,12 @@ int main()
std::cout << "error happened\n";
}
libra_preset_print(&preset);
libra_gl_filter_chain_t chain;
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
libra_PFN_vkGetInstanceProcAddr entry = reinterpret_cast<libra_PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr);
error = libra_gl_filter_chain_create(NULL, NULL, &chain);
if (error != NULL) {
libra_error_print(error);

View file

@ -110,10 +110,13 @@
<TreatAngleIncludeAsExternal>false</TreatAngleIncludeAsExternal>
<LanguageStandard>stdcpplatest</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<AdditionalIncludeDirectories>D:\Runtime\Vulkan\1.3.224.1\Include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>D:\Runtime\Vulkan\1.3.224.1\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>vulkan-1.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -124,12 +127,15 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>D:\Runtime\Vulkan\1.3.224.1\Include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>D:\Runtime\Vulkan\1.3.224.1\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>vulkan-1.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>