capi: expose helpers to ensure ABI version compatibility

This commit is contained in:
chyyran 2023-02-11 15:37:21 -05:00
parent 0eac766685
commit d925dc95c6
13 changed files with 127 additions and 17 deletions

View file

@ -20,12 +20,15 @@ A basic example of using `librashader_ld.h` to load a shader preset.
#include "librashader_ld.h"
libra_gl_filter_chain_t load_gl_filter_chain(libra_gl_loader_t opengl, const char *preset_path) {
// Ideally you should not need to check for success. If loading fails, then everything should just no-op.
// If you want to check for failure, all function pointers are intialized by default to their corresponding
// __librashader__noop_* functions in librashader.h.
libra_instance_t librashader = librashader_load_instance();
// If the instance ABI version is 0, then either librashader is not found, or
// the ABI is incompatible.
if (librashader.instance_abi_version() == 0) {
std::cout << "Could not load librashader\n";
return NULL;
}
libra_shader_preset_t preset;
libra_error_t error = librashader.preset_create(preset_path, &preset);
if (error != NULL) {

View file

@ -139,6 +139,7 @@ typedef struct libra_preset_param_list_t {
typedef const void *(*libra_gl_loader_t)(const char*);
#endif
/// API version type alias.
typedef size_t LIBRASHADER_API_VERSION;
#if defined(LIBRA_RUNTIME_OPENGL)
@ -384,6 +385,14 @@ typedef struct frame_d3d12_opt_t {
} frame_d3d12_opt_t;
#endif
typedef size_t LIBRASHADER_ABI_VERSION;
/// Function pointer definition for libra_abi_version
typedef LIBRASHADER_ABI_VERSION (*PFN_libra_instance_abi_version)(void);
/// Function pointer definition for libra_abi_version
typedef LIBRASHADER_API_VERSION (*PFN_libra_instance_api_version)(void);
/// Function pointer definition for
///libra_preset_create
typedef libra_error_t (*PFN_libra_preset_create)(const char *filename, libra_shader_preset_t *out);
@ -698,10 +707,29 @@ typedef libra_error_t (*PFN_libra_d3d12_filter_chain_get_active_pass_count)(libr
typedef libra_error_t (*PFN_libra_d3d12_filter_chain_free)(libra_d3d12_filter_chain_t *chain);
#endif
/// The current version of the librashader API/ABI.
/// The current version of the librashader API.
/// Pass this into `version` for config structs.
///
/// API versions are backwards compatible. It is valid to load
/// a librashader C API instance for all API versions less than
/// or equal to LIBRASHADER_CURRENT_VERSION, and subsequent API
/// versions must remain backwards compatible.
/// ## API Versions
/// - API version 0: 0.1.0
#define LIBRASHADER_CURRENT_VERSION 0
/// The current version of the librashader ABI.
/// Used by the loader to check ABI compatibility.
///
/// ABI version 0 is reserved as a sentinel value.
///
/// ABI versions are not backwards compatible. It is not
/// valid to load a librashader C API instance for any ABI
/// version not equal to LIBRASHADER_CURRENT_ABI.
/// ## ABI Versions
/// - ABI version 1: 0.1.0
#define LIBRASHADER_CURRENT_ABI 1
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
@ -1306,6 +1334,12 @@ libra_error_t libra_d3d12_filter_chain_get_active_pass_count(libra_d3d12_filter_
libra_error_t libra_d3d12_filter_chain_free(libra_d3d12_filter_chain_t *chain);
#endif
/// Get the ABI version of the loaded instance.
LIBRASHADER_ABI_VERSION libra_instance_abi_version(void);
/// Get the API version of the loaded instance.
LIBRASHADER_API_VERSION libra_instance_api_version(void);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View file

@ -64,6 +64,10 @@ typedef void* _LIBRASHADER_IMPL_HANDLE;
#include "librashader.h"
size_t __librashader__noop_instance_abi_version() { return 0; }
size_t __librashader__noop_instance_api_version() { return 0; }
LIBRA_ERRNO __librashader__noop_error_errno(libra_error_t error) {
return LIBRA_ERRNO_UNKNOWN_ERROR;
}
@ -302,6 +306,17 @@ libra_error_t __librashader__noop_d3d12_filter_chain_get_active_pass_count(
}
#endif
typedef struct libra_instance_t {
/// Get the supported ABI version of the loaded instance.
///
/// The null instance has ABI version 0. Any valid loaded
/// instance must have ABI version greater than or equal to 1.
PFN_libra_instance_abi_version instance_abi_version;
/// Get the supported API version of the loaded instance.
///
/// The null instance has API version 0.
PFN_libra_instance_api_version instance_api_version;
/// Load a preset.
///
/// ## Safety
@ -815,6 +830,9 @@ typedef struct libra_instance_t {
libra_instance_t __librashader_make_null_instance() {
return libra_instance_t {
.instance_abi_version = __librashader__noop_instance_abi_version,
.instance_api_version = __librashader__noop_instance_api_version,
.preset_create = __librashader__noop_preset_create,
.preset_free = __librashader__noop_preset_free,
.preset_set_param = __librashader__noop_preset_set_param,
@ -921,6 +939,14 @@ libra_instance_t librashader_load_instance() {
return instance;
}
_LIBRASHADER_ASSIGN(librashader, instance, instance_abi_version);
_LIBRASHADER_ASSIGN(librashader, instance, instance_api_version);
// Ensure ABI matches.
if (instance.instance_abi_version() != LIBRASHADER_CURRENT_ABI) {
return instance;
}
_LIBRASHADER_ASSIGN(librashader, instance, preset_create);
_LIBRASHADER_ASSIGN(librashader, instance, preset_free);
_LIBRASHADER_ASSIGN(librashader, instance, preset_set_param);

View file

@ -87,6 +87,10 @@ prefix_with_name = true
[export]
include = [
# instance
"PFN_libra_instance_abi_version",
"PFN_libra_instance_api_version",
# preset
"PFN_libra_preset_create",
"PFN_libra_preset_free",

View file

@ -1,4 +1,4 @@
//! The librashader error C API. (`libra_error_*`).
//! librashader error C API. (`libra_error_*`).
use std::any::Any;
use std::ffi::{c_char, CString};
use std::mem::MaybeUninit;

View file

@ -79,12 +79,10 @@ pub mod presets;
pub mod reflect;
pub mod runtime;
pub mod version;
pub type LIBRASHADER_API_VERSION = usize;
/// The current version of the librashader API/ABI.
/// Pass this into `version` for config structs.
pub const LIBRASHADER_CURRENT_VERSION: LIBRASHADER_API_VERSION = 0;
pub use version::LIBRASHADER_ABI_VERSION;
pub use version::LIBRASHADER_API_VERSION;
#[allow(dead_code)]
const fn assert_thread_safe<T: Send + Sync>() {}

View file

@ -1,4 +1,4 @@
//! The librashader preset C API (`libra_preset_*`).
//! librashader preset C API (`libra_preset_*`).
use crate::ctypes::libra_shader_preset_t;
use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::extern_fn;

View file

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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
//! librashader runtime C APIs
//! librashader runtime C APIs.
#[doc(cfg(feature = "runtime-opengl"))]
#[cfg(feature = "runtime-opengl")]
pub mod gl;

View file

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

View file

@ -0,0 +1,45 @@
//! librashader instance version helpers.
/// API version type alias.
pub type LIBRASHADER_API_VERSION = usize;
pub type LIBRASHADER_ABI_VERSION = usize;
/// The current version of the librashader API.
/// Pass this into `version` for config structs.
///
/// API versions are backwards compatible. It is valid to load
/// a librashader C API instance for all API versions less than
/// or equal to LIBRASHADER_CURRENT_VERSION, and subsequent API
/// versions must remain backwards compatible.
/// ## API Versions
/// - API version 0: 0.1.0
pub const LIBRASHADER_CURRENT_VERSION: LIBRASHADER_API_VERSION = 0;
/// The current version of the librashader ABI.
/// Used by the loader to check ABI compatibility.
///
/// ABI version 0 is reserved as a sentinel value.
///
/// ABI versions are not backwards compatible. It is not
/// valid to load a librashader C API instance for any ABI
/// version not equal to LIBRASHADER_CURRENT_ABI.
/// ## ABI Versions
/// - ABI version 0: null instance (unloaded)
/// - ABI version 1: 0.1.0
pub const LIBRASHADER_CURRENT_ABI: LIBRASHADER_ABI_VERSION = 1;
/// Function pointer definition for libra_abi_version
pub type PFN_libra_instance_abi_version = extern "C" fn() -> LIBRASHADER_ABI_VERSION;
/// Get the ABI version of the loaded instance.
#[no_mangle]
pub extern "C" fn libra_instance_abi_version() -> LIBRASHADER_ABI_VERSION {
LIBRASHADER_CURRENT_ABI
}
/// Function pointer definition for libra_abi_version
pub type PFN_libra_instance_api_version = extern "C" fn() -> LIBRASHADER_API_VERSION;
/// Get the API version of the loaded instance.
#[no_mangle]
pub extern "C" fn libra_instance_api_version() -> LIBRASHADER_API_VERSION {
LIBRASHADER_CURRENT_VERSION
}