diff --git a/include/README.md b/include/README.md index b5540e6..b1c5aaf 100644 --- a/include/README.md +++ b/include/README.md @@ -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) { diff --git a/include/librashader.h b/include/librashader.h index c904f51..91897a7 100644 --- a/include/librashader.h +++ b/include/librashader.h @@ -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 diff --git a/include/librashader_ld.h b/include/librashader_ld.h index c784a2e..3f71014 100644 --- a/include/librashader_ld.h +++ b/include/librashader_ld.h @@ -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); diff --git a/librashader-capi/cbindgen.toml b/librashader-capi/cbindgen.toml index 7f35f03..ef39ebd 100644 --- a/librashader-capi/cbindgen.toml +++ b/librashader-capi/cbindgen.toml @@ -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", diff --git a/librashader-capi/src/error.rs b/librashader-capi/src/error.rs index 9f04b52..c56dfa0 100644 --- a/librashader-capi/src/error.rs +++ b/librashader-capi/src/error.rs @@ -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; diff --git a/librashader-capi/src/lib.rs b/librashader-capi/src/lib.rs index 2eed5e0..fa6fc89 100644 --- a/librashader-capi/src/lib.rs +++ b/librashader-capi/src/lib.rs @@ -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>() {} diff --git a/librashader-capi/src/presets.rs b/librashader-capi/src/presets.rs index 4179741..591c4f7 100644 --- a/librashader-capi/src/presets.rs +++ b/librashader-capi/src/presets.rs @@ -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; diff --git a/librashader-capi/src/runtime/d3d11/mod.rs b/librashader-capi/src/runtime/d3d11/mod.rs index 5557f2b..1a42c7a 100644 --- a/librashader-capi/src/runtime/d3d11/mod.rs +++ b/librashader-capi/src/runtime/d3d11/mod.rs @@ -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::*; diff --git a/librashader-capi/src/runtime/d3d12/mod.rs b/librashader-capi/src/runtime/d3d12/mod.rs index 3c6ecda..e45700f 100644 --- a/librashader-capi/src/runtime/d3d12/mod.rs +++ b/librashader-capi/src/runtime/d3d12/mod.rs @@ -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::*; diff --git a/librashader-capi/src/runtime/gl/mod.rs b/librashader-capi/src/runtime/gl/mod.rs index f33b437..1d4a8f1 100644 --- a/librashader-capi/src/runtime/gl/mod.rs +++ b/librashader-capi/src/runtime/gl/mod.rs @@ -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::*; diff --git a/librashader-capi/src/runtime/mod.rs b/librashader-capi/src/runtime/mod.rs index 5424b22..62e8efc 100644 --- a/librashader-capi/src/runtime/mod.rs +++ b/librashader-capi/src/runtime/mod.rs @@ -1,4 +1,4 @@ -//! librashader runtime C APIs +//! librashader runtime C APIs. #[doc(cfg(feature = "runtime-opengl"))] #[cfg(feature = "runtime-opengl")] pub mod gl; diff --git a/librashader-capi/src/runtime/vk/mod.rs b/librashader-capi/src/runtime/vk/mod.rs index 167e387..0b250cf 100644 --- a/librashader-capi/src/runtime/vk/mod.rs +++ b/librashader-capi/src/runtime/vk/mod.rs @@ -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::*; diff --git a/librashader-capi/src/version.rs b/librashader-capi/src/version.rs new file mode 100644 index 0000000..86cf558 --- /dev/null +++ b/librashader-capi/src/version.rs @@ -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 +}