librashader/include/librashader_ld.h
2023-01-14 01:53:39 -05:00

343 lines
13 KiB
C

/*
librashader_ld.h
SPDX-License-Identifier: MIT
This file is part of the librashader C headers.
Copyright 2022 chyyran
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRASHADER_LD_H__
#define __LIBRASHADER_LD_H__
#pragma once
#define LIBRA_RUNTIME_OPENGL
#define LIBRA_RUNTIME_D3D11
#define LIBRA_RUNTIME_VULKAN
#if defined(_WIN32)
#include <libloaderapi.h>
#elif defined(__linux__)
#include <dlfcn.h>
#endif
#include "librashader.h"
LIBRA_ERRNO __librashader__noop_error_errno(libra_error_t error) {
return LIBRA_ERRNO_UNKNOWN_ERROR;
}
int32_t __librashader__noop_error_print(libra_error_t error) { return 1; }
int32_t __librashader__noop_error_free(libra_error_t *error) { return 1; }
int32_t __librashader__noop_error_write(libra_error_t error, char **out) {
return 1;
}
int32_t __librashader__noop_error_free_string(char **out) { return 1; }
libra_error_t __librashader__noop_preset_create(const char *filename,
libra_shader_preset_t *out) {
return NULL;
}
libra_error_t __librashader__noop_preset_free(libra_shader_preset_t *preset) {
return NULL;
}
libra_error_t __librashader__noop_preset_set_param(
libra_shader_preset_t *preset, const char *name, float value) {
return NULL;
}
libra_error_t __librashader__noop_preset_get_param(
libra_shader_preset_t *preset, const char *name, float *value) {
return NULL;
}
libra_error_t __librashader__noop_preset_print(libra_shader_preset_t *preset) {
return NULL;
}
libra_error_t __librashader__noop_preset_get_runtime_param_names(
libra_shader_preset_t *preset, const char **value) {
return NULL;
}
#if defined(LIBRA_RUNTIME_OPENGL)
libra_error_t __librashader__noop_gl_init_context(libra_gl_loader_t loader) {
return NULL;
}
libra_error_t __librashader__noop_gl_filter_chain_create(
libra_shader_preset_t *preset, const struct filter_chain_gl_opt_t *options,
libra_gl_filter_chain_t *out) {
return NULL;
}
libra_error_t __librashader__noop_gl_filter_chain_frame(
libra_gl_filter_chain_t *chain, size_t frame_count,
struct libra_source_image_gl_t image, struct libra_viewport_t viewport,
struct libra_draw_framebuffer_gl_t out, const float *mvp,
const struct frame_gl_opt_t *opt) {
return NULL;
}
libra_error_t __librashader__noop_gl_filter_chain_free(
libra_gl_filter_chain_t *chain) {
return NULL;
}
#endif
#if defined(LIBRA_RUNTIME_D3D11)
libra_error_t __librashader__noop_d3d11_filter_chain_create(
libra_shader_preset_t *preset,
const struct filter_chain_d3d11_opt_t *options, const ID3D11Device *device,
libra_d3d11_filter_chain_t *out) {
return NULL;
}
libra_error_t __librashader__noop_d3d11_filter_chain_frame(
libra_d3d11_filter_chain_t *chain, size_t frame_count,
struct libra_source_image_d3d11_t image, struct libra_viewport_t viewport,
const ID3D11RenderTargetView *out, const float *mvp,
const struct frame_vk_opt_t *opt) {
return NULL;
}
libra_error_t __librashader__noop_d3d11_filter_chain_free(
libra_d3d11_filter_chain_t *chain) {
return NULL;
}
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
libra_error_t __librashader__noop_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) {
return NULL;
}
libra_error_t __librashader__noop_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) {
return NULL;
}
libra_error_t __librashader__noop_vk_filter_chain_free(
libra_vk_filter_chain_t *chain) {
return NULL;
}
#endif
typedef struct libra_instance_t {
PFN_libra_preset_create preset_create;
PFN_libra_preset_free preset_free;
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_param_names preset_get_runtime_param_names;
PFN_libra_error_errno error_errno;
PFN_libra_error_print error_print;
PFN_libra_error_free error_free;
PFN_libra_error_write error_write;
PFN_libra_error_free_string error_free_string;
#if defined(LIBRA_RUNTIME_OPENGL)
PFN_libra_gl_init_context gl_init_context;
PFN_libra_gl_filter_chain_create gl_filter_chain_create;
PFN_libra_gl_filter_chain_frame gl_filter_chain_frame;
PFN_libra_gl_filter_chain_free gl_filter_chain_free;
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
PFN_libra_d3d11_filter_chain_create d3d11_filter_chain_create;
PFN_libra_d3d11_filter_chain_frame d3d11_filter_chain_frame;
PFN_libra_d3d11_filter_chain_free d3d11_filter_chain_free;
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
PFN_libra_vk_filter_chain_create vk_filter_chain_create;
PFN_libra_vk_filter_chain_frame vk_filter_chain_frame;
PFN_libra_vk_filter_chain_free vk_filter_chain_free;
#endif
} libra_instance_t;
libra_instance_t __librashader_make_null_instance() {
return libra_instance_t{
.preset_create = __librashader__noop_preset_create,
.preset_free = __librashader__noop_preset_free,
.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_param_names =
__librashader__noop_preset_get_runtime_param_names,
.error_errno = __librashader__noop_error_errno,
.error_print = __librashader__noop_error_print,
.error_free = __librashader__noop_error_free,
.error_write = __librashader__noop_error_write,
.error_free_string = __librashader__noop_error_free_string,
#if defined(LIBRA_RUNTIME_OPENGL)
.gl_init_context = __librashader__noop_gl_init_context,
.gl_filter_chain_create = __librashader__noop_gl_filter_chain_create,
.gl_filter_chain_frame = __librashader__noop_gl_filter_chain_frame,
.gl_filter_chain_free = __librashader__noop_gl_filter_chain_free,
#endif
#if defined(LIBRA_RUNTIME_D3D11)
.d3d11_filter_chain_create =
__librashader__noop_d3d11_filter_chain_create,
.d3d11_filter_chain_frame =
__librashader__noop_d3d11_filter_chain_frame,
.d3d11_filter_chain_free = __librashader__noop_d3d11_filter_chain_free,
#endif
#if defined(LIBRA_RUNTIME_VULKAN)
.vk_filter_chain_create = __librashader__noop_vk_filter_chain_create,
.vk_filter_chain_frame = __librashader__noop_vk_filter_chain_frame,
.vk_filter_chain_free = __librashader__noop_vk_filter_chain_free,
#endif
};
}
/// Load an instance of librashader in the OS-dependent search path of the
/// current directory.
///
/// `librashader_load_instance` loads from `librashader.dll` on Windows,
/// or `librashader.so` on Linux.
///
/// If no librashader implementation is found, the returned `libra_instance_t`
/// will have all function pointers set to no-op functions.
///
/// If any symbol fails to load, the function will be set to a no-op function.
///
/// \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; \
} \
}
libra_instance_t librashader_load_instance() {
HMODULE librashader = LoadLibraryW(L"librashader.dll");
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_FARPROC(librashader, instance, preset_get_runtime_param_names);
_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);
#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);
#endif
#if defined(LIBRA_RUNTIME_D3D11)
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, d3d11_filter_chain_create);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, d3d11_filter_chain_frame);
_LIBRASHADER_ASSIGN_FARPROC(librashader, instance, d3d11_filter_chain_free);
#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);
#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, preset_get_runtime_param_names);
_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);
#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);
#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);
#endif
return instance;
}
#else
libra_instance_t librashader_load_instance() {
return __librashader_make_null_instance();
}
#endif
#endif