ld: expose runtime params api to loader

This commit is contained in:
chyyran 2023-01-14 17:14:37 -05:00
parent 3592b453e8
commit c1669916d4
6 changed files with 174 additions and 153 deletions

View file

@ -102,15 +102,15 @@ typedef struct libra_preset_param_t {
} libra_preset_param_t;
/// A list of preset parameters.
typedef struct libra_preset_parameter_list_t {
typedef struct libra_preset_param_list_t {
/// A pointer to the parameter
const struct libra_preset_param_t *parameters;
/// The number of parameters in the list
/// The number of parameters in the list.
uint64_t length;
/// For internal use only.
/// Changing this causes immediate undefined behaviour on freeing this parameter list.
uint64_t _internal_alloc;
} libra_preset_parameter_list_t;
} libra_preset_param_list_t;
#if defined(LIBRA_RUNTIME_OPENGL)
/// A GL function loader that librashader needs to be initialized with.
@ -291,6 +291,15 @@ typedef libra_error_t (*PFN_libra_preset_get_param)(libra_shader_preset_t *prese
///libra_preset_print
typedef libra_error_t (*PFN_libra_preset_print)(libra_shader_preset_t *preset);
/// Function pointer definition for
///libra_preset_get_runtime_params
typedef libra_error_t (*PFN_libra_preset_get_runtime_params)(libra_shader_preset_t *preset,
struct libra_preset_param_list_t *out);
/// Function pointer definition for
///libra_preset_free_runtime_params
typedef libra_error_t (*PFN_libra_preset_free_runtime_params)(struct libra_preset_param_list_t preset);
/// Function pointer definition for libra_error_errno
typedef LIBRA_ERRNO (*PFN_libra_error_errno)(libra_error_t error);
@ -571,8 +580,34 @@ libra_error_t libra_preset_print(libra_shader_preset_t *preset);
/// ## Safety
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
/// - `out` must be an aligned pointer to a `libra_preset_parameter_list_t`.
libra_error_t libra_preset_get_runtime_parameters(libra_shader_preset_t *preset,
struct libra_preset_parameter_list_t *out);
/// - The output struct should be treated as immutable. Mutating any struct fields
/// in the returned struct may at best cause memory leaks, and at worse
/// cause undefined behaviour when later freed.
/// - It is safe to call `libra_preset_get_runtime_params` multiple times, however
/// the output struct must only be freed once per call.
libra_error_t libra_preset_get_runtime_params(libra_shader_preset_t *preset,
struct libra_preset_param_list_t *out);
/// Free the runtime parameters.
///
/// Unlike the other `free` functions provided by librashader,
/// `libra_preset_free_runtime_params` takes the struct directly.
/// The caller must take care to maintain the lifetime of any pointers
/// contained within the input `libra_preset_param_list_t`.
///
/// ## Safety
/// - Any pointers rooted at `parameters` becomes invalid after this function returns,
/// including any strings accessible via the input `libra_preset_param_list_t`.
/// The caller must ensure that there are no live pointers, aliased or unaliased,
/// to data accessible via the input `libra_preset_param_list_t`.
///
/// - Accessing any data pointed to via the input `libra_preset_param_list_t` after it
/// has been freed is a use-after-free and is immediate undefined behaviour.
///
/// - If any struct fields of the input `libra_preset_param_list_t` was modified from
/// their values given after `libra_preset_get_runtime_params`, this may result
/// in undefined behaviour.
libra_error_t libra_preset_free_runtime_params(struct libra_preset_param_list_t preset);
#if defined(LIBRA_RUNTIME_OPENGL)
/// Initialize the OpenGL Context for librashader.

View file

@ -32,8 +32,27 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#if defined(_WIN32)
#include <windows.h>
#define _LIBRASHADER_ASSIGN(HMOD, INSTANCE, NAME) \
{ \
FARPROC address = GetProcAddress(HMOD, "libra_" #NAME); \
if (address != NULL) { \
(INSTANCE).NAME = (PFN_libra_##NAME)address; \
} \
}
typedef HMODULE _LIBRASHADER_IMPL_HANDLE;
#define _LIBRASHADER_LOAD LoadLibraryW(L"librashader.dll")
#elif defined(__linux__)
#include <dlfcn.h>
#define _LIBRASHADER_ASSIGN(HMOD, INSTANCE, NAME) \
{ \
void *address = dlsym(HMOD, "libra_" #NAME); \
if (address != NULL) { \
(INSTANCE).NAME = (PFN_libra_##NAME)address; \
} \
}
typedef void* _LIBRASHADER_IMPL_HANDLE;
#define _LIBRASHADER_LOAD dlopen(L"librashader.so", RTLD_LAZY)
#endif
#include "librashader.h"
@ -74,7 +93,13 @@ libra_error_t __librashader__noop_preset_get_param(
libra_error_t __librashader__noop_preset_print(libra_shader_preset_t *preset) {
return NULL;
}
libra_error_t __librashader__noop_preset_get_runtime_params(
libra_shader_preset_t *preset, struct libra_preset_param_list_t *out) {
return NULL;
}
libra_error_t __librashader__noop_preset_free_runtime_params(struct libra_preset_param_list_t out) {
return NULL;
}
#if defined(LIBRA_RUNTIME_OPENGL)
libra_error_t __librashader__noop_gl_init_context(libra_gl_loader_t loader) {
return NULL;
@ -211,6 +236,8 @@ typedef struct libra_instance_t {
PFN_libra_preset_set_param preset_set_param;
PFN_libra_preset_get_param preset_get_param;
PFN_libra_preset_print preset_print;
PFN_libra_preset_get_runtime_params preset_get_runtime_params;
PFN_libra_preset_free_runtime_params preset_free_runtime_params;
PFN_libra_error_errno error_errno;
PFN_libra_error_print error_print;
@ -263,7 +290,10 @@ libra_instance_t __librashader_make_null_instance() {
.preset_set_param = __librashader__noop_preset_set_param,
.preset_get_param = __librashader__noop_preset_get_param,
.preset_print = __librashader__noop_preset_print,
.preset_get_runtime_params =
__librashader__noop_preset_get_runtime_params,
.preset_free_runtime_params =
__librashader__noop_preset_free_runtime_params,
.error_errno = __librashader__noop_error_errno,
.error_print = __librashader__noop_error_print,
.error_free = __librashader__noop_error_free,
@ -331,152 +361,78 @@ libra_instance_t __librashader_make_null_instance() {
/// \return An `libra_instance_t` struct with loaded function pointers.
libra_instance_t librashader_load_instance();
#if defined(_WIN32)
#define _LIBRASHADER_ASSIGN_FARPROC(HMOD, INSTANCE, NAME) \
{ \
FARPROC address = GetProcAddress(HMOD, "libra_" #NAME); \
if (address != NULL) { \
(INSTANCE).NAME = (PFN_libra_##NAME)address; \
} \
}
#if defined(_WIN32) || defined(__linux__)
libra_instance_t librashader_load_instance() {
HMODULE librashader = LoadLibraryW(L"librashader.dll");
_LIBRASHADER_IMPL_HANDLE librashader = _LIBRASHADER_LOAD;
libra_instance_t instance = __librashader_make_null_instance();
if (librashader == 0) {
return instance;
}
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, preset_create);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, preset_free);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, preset_set_param);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, preset_get_param);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, preset_print);
_LIBRASHADER_ASSIGN(librashader, instance, preset_create);
_LIBRASHADER_ASSIGN(librashader, instance, preset_free);
_LIBRASHADER_ASSIGN(librashader, instance, preset_set_param);
_LIBRASHADER_ASSIGN(librashader, instance, preset_get_param);
_LIBRASHADER_ASSIGN(librashader, instance, preset_print);
_LIBRASHADER_ASSIGN(librashader, instance,
preset_get_runtime_params);
_LIBRASHADER_ASSIGN(librashader, instance,
preset_free_runtime_params);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, error_errno);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, error_print);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, error_free);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, error_write);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, error_free_string);
_LIBRASHADER_ASSIGN(librashader, instance, error_errno);
_LIBRASHADER_ASSIGN(librashader, instance, error_print);
_LIBRASHADER_ASSIGN(librashader, instance, error_free);
_LIBRASHADER_ASSIGN(librashader, instance, error_write);
_LIBRASHADER_ASSIGN(librashader, instance, error_free_string);
#if defined(LIBRA_RUNTIME_OPENGL)
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, gl_init_context);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, gl_filter_chain_create);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, gl_filter_chain_frame);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, gl_filter_chain_free);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance, gl_init_context);
_LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_create);
_LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_frame);
_LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_free);
_LIBRASHADER_ASSIGN(librashader, instance,
gl_filter_chain_get_param);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
gl_filter_chain_set_param);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
gl_filter_chain_get_active_pass_count);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
gl_filter_chain_set_active_pass_count);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
d3d11_filter_chain_create);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
d3d11_filter_chain_frame);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, d3d11_filter_chain_free);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_free);
_LIBRASHADER_ASSIGN(librashader, instance,
d3d11_filter_chain_get_param);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
d3d11_filter_chain_set_param);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
d3d11_filter_chain_get_active_pass_count);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
d3d11_filter_chain_set_active_pass_count);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, vk_filter_chain_create);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, vk_filter_chain_frame);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, vk_filter_chain_free);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_create);
_LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_frame);
_LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_free);
_LIBRASHADER_ASSIGN(librashader, instance,
vk_filter_chain_get_param);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
vk_filter_chain_set_param);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
vk_filter_chain_get_active_pass_count);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance,
_LIBRASHADER_ASSIGN(librashader, instance,
vk_filter_chain_set_active_pass_count);
#endif
return instance;
}
#elif defined(__linux__)
#define _LIBRASHADER_ASSIGN_DLSYM(HMOD, INSTANCE, NAME) \
{ \
void *address = dlsym(HMOD, "libra_" #NAME); \
if (address != NULL) { \
(INSTANCE).NAME = (PFN_libra_##NAME)address; \
} \
}
libra_instance_t librashader_load_instance() {
void *librashader = dlopen(L"librashader.so", RTLD_LAZY);
libra_instance_t instance = __librashader_make_null_instance();
if (librashader == NULL) {
return instance;
}
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, preset_create);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, preset_free);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, preset_set_param);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, preset_get_param);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, preset_print);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, error_errno);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, error_print);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, error_free);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, error_write);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, error_free_string);
#if defined(LIBRA_RUNTIME_OPENGL)
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, gl_init_context);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, gl_filter_chain_create);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, gl_filter_chain_frame);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, gl_filter_chain_free);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, gl_filter_chain_get_param);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, gl_filter_chain_set_param);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance,
gl_filter_chain_get_active_pass_count);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance,
gl_filter_chain_set_active_pass_count);
#endif
// Not sure why you would want this
#if defined(LIBRA_RUNTIME_D3D11)
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, d3d11_filter_chain_create);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, d3d11_filter_chain_frame);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, d3d11_filter_chain_free);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance,
d3d11_filter_chain_get_param);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance,
d3d11_filter_chain_set_param);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance,
d3d11_filter_chain_get_active_pass_count);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance,
d3d11_filter_chain_set_active_pass_count);
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, vk_filter_chain_create);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, vk_filter_chain_frame);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, vk_filter_chain_free);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, vk_filter_chain_get_param);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance, vk_filter_chain_set_param);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance,
vk_filter_chain_get_active_pass_count);
_LIBRASHADER_ASSIGN_DLSYM(librashader, instance,
vk_filter_chain_set_active_pass_count);
#endif
return instance;
}
#else
libra_instance_t librashader_load_instance() {
return __librashader_make_null_instance();

View file

@ -37,7 +37,8 @@ include = [
"PFN_libra_preset_set_param",
"PFN_libra_preset_get_param",
"PFN_libra_preset_print",
"PFN_libra_preset_get_runtime_param_names",
"PFN_libra_preset_get_runtime_params",
"PFN_libra_preset_free_runtime_params",
# error
"PFN_libra_error_errno",

View file

@ -9,10 +9,10 @@ use std::ptr::NonNull;
/// A list of preset parameters.
#[repr(C)]
pub struct libra_preset_parameter_list_t {
pub struct libra_preset_param_list_t {
/// A pointer to the parameter
pub parameters: *const libra_preset_param_t,
/// The number of parameters in the list
/// The number of parameters in the list.
pub length: u64,
/// For internal use only.
/// Changing this causes immediate undefined behaviour on freeing this parameter list.
@ -146,9 +146,14 @@ extern_fn! {
/// ## Safety
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
/// - `out` must be an aligned pointer to a `libra_preset_parameter_list_t`.
fn libra_preset_get_runtime_parameters(
/// - The output struct should be treated as immutable. Mutating any struct fields
/// in the returned struct may at best cause memory leaks, and at worse
/// cause undefined behaviour when later freed.
/// - It is safe to call `libra_preset_get_runtime_params` multiple times, however
/// the output struct must only be freed once per call.
fn libra_preset_get_runtime_params(
preset: *mut libra_shader_preset_t,
out: *mut MaybeUninit<libra_preset_parameter_list_t>
out: *mut MaybeUninit<libra_preset_param_list_t>
) |preset| {
assert_some_ptr!(preset);
assert_non_null!(out);
@ -171,7 +176,7 @@ extern_fn! {
}
let (parts, len, cap) = values.into_raw_parts();
unsafe {
out.write(MaybeUninit::new(libra_preset_parameter_list_t {
out.write(MaybeUninit::new(libra_preset_param_list_t {
parameters: parts,
length: len as u64,
_internal_alloc: cap as u64,
@ -180,28 +185,39 @@ extern_fn! {
}
}
// /// Get a list of runtime parameter names.
// ///
// /// The caller must provide a sufficiently sized buffer.
// /// If `value` is null, then size will be written to with the size of the buffer required
// /// to get the parameter names.
// /// ## Safety
// /// - `preset` must be null or a valid and aligned pointer to a shader preset.
// #[no_mangle]
// pub unsafe extern "C" fn libra_preset_free_runtime_param_names(
// value: MaybeUninit<*mut *const c_char>,
// ) -> libra_error_t {
// ffi_body!(|value| {
// let iter = librashader::presets::get_parameter_meta(preset)?;
// let mut c_strings = Vec::new();
// for param in iter {
// let c_string = CString::new(param.id)
// .map_err(|err| LibrashaderError::UnknownError(Box::new(err)))?;
// c_strings.push(c_string.into_raw().cast_const());
// }
//
// let (parts, _len, _cap) = c_strings.into_raw_parts();
//
// value.write(parts);
// })
// }
extern_fn! {
/// Free the runtime parameters.
///
/// Unlike the other `free` functions provided by librashader,
/// `libra_preset_free_runtime_params` takes the struct directly.
/// The caller must take care to maintain the lifetime of any pointers
/// contained within the input `libra_preset_param_list_t`.
///
/// ## Safety
/// - Any pointers rooted at `parameters` becomes invalid after this function returns,
/// including any strings accessible via the input `libra_preset_param_list_t`.
/// The caller must ensure that there are no live pointers, aliased or unaliased,
/// to data accessible via the input `libra_preset_param_list_t`.
///
/// - Accessing any data pointed to via the input `libra_preset_param_list_t` after it
/// has been freed is a use-after-free and is immediate undefined behaviour.
///
/// - If any struct fields of the input `libra_preset_param_list_t` was modified from
/// their values given after `libra_preset_get_runtime_params`, this may result
/// in undefined behaviour.
fn libra_preset_free_runtime_params(preset: libra_preset_param_list_t) {
unsafe {
let values = Vec::from_raw_parts(preset.parameters.cast_mut(),
preset.length as usize,
preset._internal_alloc as usize);
for value in values {
let name = CString::from_raw(value.name.cast_mut());
let description = CString::from_raw(value.description.cast_mut());
drop(name);
drop(description)
}
}
}
}

View file

@ -8,8 +8,10 @@ use librashader_runtime::image::{Image, BGRA8};
use librashader_runtime::scaling::MipmapSize;
pub(crate) struct LutTexture {
pub memory: VulkanImageMemory,
pub staging: VulkanBuffer,
#[allow(dead_code)]
memory: VulkanImageMemory,
#[allow(dead_code)]
staging: VulkanBuffer,
pub image: InputImage,
}

View file

@ -10,6 +10,18 @@ int main()
std::cout << "Hello World!\n";
std::cout << std::filesystem::current_path() << std::endl;
auto instance = librashader_load_instance();
libra_shader_preset_t preset;
auto error = instance.preset_create(
"../../../slang-shaders/border/gameboy-player/"
"gameboy-player-crt-royale.slangp",
&preset);
libra_preset_param_list_t parameters;
error = instance.preset_get_runtime_params(&preset, &parameters);
libra_preset_param_t next = parameters.parameters[471];
instance.preset_free_runtime_params(parameters);
/*libra_shader_preset_t preset;
auto error = libra_preset_create("../../../slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp", &preset);
@ -20,7 +32,6 @@ int main()
libra_gl_filter_chain_t chain;
error = libra_gl_filter_chain_create(NULL, NULL, &chain);
if (error != NULL) {
libra_error_print(error);
char* error_str;