diff --git a/Cargo.lock b/Cargo.lock index 0e54942..f4e2c82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -108,54 +108,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anstream" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" - -[[package]] -name = "anstyle-parse" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - [[package]] name = "array-concat" version = "0.5.2" @@ -404,9 +356,9 @@ checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "bytemuck" -version = "1.14.2" +version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" dependencies = [ "bytemuck_derive", ] @@ -538,36 +490,30 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.18" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "aa91278560fc226a5d9d736cc21e485ff9aad47d26b8ffe1f54cba868b684b9f" dependencies = [ - "clap_builder", + "bitflags 1.3.2", "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" -dependencies = [ - "anstream", - "anstyle", - "clap_lex 0.6.0", + "clap_lex 0.3.3", + "is-terminal", + "once_cell", "strsim", + "termcolor", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" dependencies = [ "heck", + "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.48", + "syn 1.0.109", ] [[package]] @@ -581,9 +527,12 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" +dependencies = [ + "os_str_bytes", +] [[package]] name = "cmake" @@ -656,12 +605,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "com" version = "0.6.0" @@ -1355,9 +1298,9 @@ dependencies = [ [[package]] name = "glslang-sys" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d76f2d75ad6e8a12c26e77ed6443a9369ef7957daf361e751c3489a97f8b816" +checksum = "6a47e052f086ec9b43df0bca02c1675c2a89bceb5386dd64382dc36143930985" dependencies = [ "cc", "glob", @@ -1591,12 +1534,12 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "fe8f25ce1159c7740ff0b9b2f5cdf4a8428742ba7c112b9f20f22cd5219c7dab" dependencies = [ "hermit-abi 0.3.5", - "rustix", + "libc", "windows-sys 0.52.0", ] @@ -1630,9 +1573,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] @@ -1723,13 +1666,13 @@ dependencies = [ [[package]] name = "librashader" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "ash", "librashader-cache", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-preprocess", - "librashader-presets 0.2.0-beta.7", + "librashader-presets 0.2.0-beta.8", "librashader-reflect", "librashader-runtime", "librashader-runtime-d3d11", @@ -1747,12 +1690,12 @@ name = "librashader-build-script" version = "0.1.0" dependencies = [ "cbindgen", - "clap 4.4.18", + "clap 4.1.0", ] [[package]] name = "librashader-cache" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "bincode", "blake3", @@ -1768,7 +1711,7 @@ dependencies = [ [[package]] name = "librashader-capi" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "ash", "gl", @@ -1791,7 +1734,7 @@ dependencies = [ [[package]] name = "librashader-common" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "ash", "gl", @@ -1802,11 +1745,11 @@ dependencies = [ [[package]] name = "librashader-preprocess" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "encoding_rs", "glob", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-presets 0.1.4", "nom", "rayon", @@ -1829,27 +1772,32 @@ dependencies = [ [[package]] name = "librashader-presets" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "glob", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "nom", "nom_locate", "num-traits", + "once_cell", + "os_str_bytes", + "regex", + "rustc-hash", + "rustversion", "thiserror", ] [[package]] name = "librashader-reflect" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "bitflags 2.4.2", "bytemuck", "glslang", "indexmap 2.2.2", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-preprocess", - "librashader-presets 0.2.0-beta.7", + "librashader-presets 0.2.0-beta.8", "librashader-spirv-cross", "matches", "naga", @@ -1863,13 +1811,13 @@ dependencies = [ [[package]] name = "librashader-runtime" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "bytemuck", "image", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-preprocess", - "librashader-presets 0.2.0-beta.7", + "librashader-presets 0.2.0-beta.8", "librashader-reflect", "num-traits", "rustc-hash", @@ -1877,15 +1825,15 @@ dependencies = [ [[package]] name = "librashader-runtime-d3d11" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "array-concat", "bytemuck", "gfx-maths", "librashader-cache", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-preprocess", - "librashader-presets 0.2.0-beta.7", + "librashader-presets 0.2.0-beta.8", "librashader-reflect", "librashader-runtime", "librashader-spirv-cross", @@ -1897,7 +1845,7 @@ dependencies = [ [[package]] name = "librashader-runtime-d3d12" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "array-concat", "array-init", @@ -1905,9 +1853,9 @@ dependencies = [ "bytemuck", "gfx-maths", "librashader-cache", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-preprocess", - "librashader-presets 0.2.0-beta.7", + "librashader-presets 0.2.0-beta.8", "librashader-reflect", "librashader-runtime", "librashader-spirv-cross", @@ -1921,15 +1869,15 @@ dependencies = [ [[package]] name = "librashader-runtime-gl" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "bytemuck", "gl", "glfw 0.47.0", "librashader-cache", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-preprocess", - "librashader-presets 0.2.0-beta.7", + "librashader-presets 0.2.0-beta.8", "librashader-reflect", "librashader-runtime", "librashader-spirv-cross", @@ -1941,7 +1889,7 @@ dependencies = [ [[package]] name = "librashader-runtime-vk" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "ash", "ash-window", @@ -1949,9 +1897,9 @@ dependencies = [ "glfw 0.49.1", "gpu-allocator 0.22.0", "librashader-cache", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-preprocess", - "librashader-presets 0.2.0-beta.7", + "librashader-presets 0.2.0-beta.8", "librashader-reflect", "librashader-runtime", "librashader-spirv-cross", @@ -1966,16 +1914,16 @@ dependencies = [ [[package]] name = "librashader-runtime-wgpu" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" dependencies = [ "array-concat", "bytemuck", "config", "env_logger", "image", - "librashader-common 0.2.0-beta.7", + "librashader-common 0.2.0-beta.8", "librashader-preprocess", - "librashader-presets 0.2.0-beta.7", + "librashader-presets 0.2.0-beta.8", "librashader-reflect", "librashader-runtime", "log", @@ -2497,6 +2445,9 @@ name = "os_str_bytes" version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +dependencies = [ + "memchr", +] [[package]] name = "owned_ttf_parser" @@ -2682,6 +2633,30 @@ dependencies = [ "toml_edit 0.21.1", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.78" @@ -2923,6 +2898,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.16" @@ -2980,7 +2961,7 @@ dependencies = [ "ab_glyph", "log", "memmap2 0.9.4", - "smithay-client-toolkit 0.18.0", + "smithay-client-toolkit 0.18.1", "tiny-skia 0.11.4", ] @@ -3098,9 +3079,9 @@ dependencies = [ [[package]] name = "smithay-client-toolkit" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e3d9941fa3bacf7c2bf4b065304faa14164151254cd16ce1b1bc8fc381600f" +checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ "bitflags 2.4.2", "calloop 0.12.4", @@ -3425,12 +3406,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - [[package]] name = "vcpkg" version = "0.2.15" @@ -4221,7 +4196,7 @@ dependencies = [ "redox_syscall 0.3.5", "rustix", "sctk-adwaita 0.8.1", - "smithay-client-toolkit 0.18.0", + "smithay-client-toolkit 0.18.1", "smol_str", "unicode-segmentation", "wasm-bindgen", diff --git a/include/librashader.h b/include/librashader.h index 12e305f..83b0f6c 100644 --- a/include/librashader.h +++ b/include/librashader.h @@ -23,7 +23,6 @@ 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_H__ #define __LIBRASHADER_H__ @@ -47,9 +46,9 @@ typedef void ID3D11ShaderResourceView; #else typedef int32_t VkFormat; typedef uint64_t VkImage; -typedef void* VkPhysicalDevice; -typedef void* VkInstance; -typedef void* VkCommandBuffer; +typedef void *VkPhysicalDevice; +typedef void *VkInstance; +typedef void *VkCommandBuffer; #endif #if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D12) #include @@ -60,83 +59,115 @@ typedef void ID3D12Resource; typedef void D3D12_CPU_DESCRIPTOR_HANDLE; #endif - /// Error codes for librashader error types. enum LIBRA_ERRNO #ifdef __cplusplus - : int32_t -#endif // __cplusplus - { - LIBRA_ERRNO_UNKNOWN_ERROR = 0, - LIBRA_ERRNO_INVALID_PARAMETER = 1, - LIBRA_ERRNO_INVALID_STRING = 2, - LIBRA_ERRNO_PRESET_ERROR = 3, - LIBRA_ERRNO_PREPROCESS_ERROR = 4, - LIBRA_ERRNO_SHADER_PARAMETER_ERROR = 5, - LIBRA_ERRNO_REFLECT_ERROR = 6, - LIBRA_ERRNO_RUNTIME_ERROR = 7, + : int32_t +#endif // __cplusplus +{ + LIBRA_ERRNO_UNKNOWN_ERROR = 0, + LIBRA_ERRNO_INVALID_PARAMETER = 1, + LIBRA_ERRNO_INVALID_STRING = 2, + LIBRA_ERRNO_PRESET_ERROR = 3, + LIBRA_ERRNO_PREPROCESS_ERROR = 4, + LIBRA_ERRNO_SHADER_PARAMETER_ERROR = 5, + LIBRA_ERRNO_REFLECT_ERROR = 6, + LIBRA_ERRNO_RUNTIME_ERROR = 7, }; #ifndef __cplusplus typedef int32_t LIBRA_ERRNO; -#endif // __cplusplus +#endif // __cplusplus -/// A Direct3D 11 filter chain. +/// An enum representing orientation for use in preset contexts. +enum LIBRA_PRESET_CTX_ORIENTATION +#ifdef __cplusplus + : uint32_t +#endif // __cplusplus +{ + LIBRA_PRESET_CTX_ORIENTATION_VERTICAL = 0, + LIBRA_PRESET_CTX_ORIENTATION_HORIZONTAL, +}; +#ifndef __cplusplus +typedef uint32_t LIBRA_PRESET_CTX_ORIENTATION; +#endif // __cplusplus + +enum LIBRA_PRESET_CTX_RUNTIME +#ifdef __cplusplus + : uint32_t +#endif // __cplusplus +{ + LIBRA_PRESET_CTX_RUNTIME_NONE = 0, + LIBRA_PRESET_CTX_RUNTIME_GL_CORE, + LIBRA_PRESET_CTX_RUNTIME_VULKAN, + LIBRA_PRESET_CTX_RUNTIME_D3D11, + LIBRA_PRESET_CTX_RUNTIME_D3D12, + LIBRA_PRESET_CTX_RUNTIME_METAL, +}; +#ifndef __cplusplus +typedef uint32_t LIBRA_PRESET_CTX_RUNTIME; +#endif // __cplusplus + +/// Opaque struct for a Direct3D 11 filter chain. typedef struct _filter_chain_d3d11 _filter_chain_d3d11; -/// A Direct3D 12 filter chain. +/// Opaque struct for a Direct3D 12 filter chain. typedef struct _filter_chain_d3d12 _filter_chain_d3d12; -/// An OpenGL filter chain. +/// Opaque struct for an OpenGL filter chain. typedef struct _filter_chain_gl _filter_chain_gl; -/// A Vulkan filter chain. +/// Opaque struct for a Vulkan filter chain. typedef struct _filter_chain_vk _filter_chain_vk; -/// The error type for librashader. +/// The error type for librashader C API. typedef struct _libra_error _libra_error; -/// A shader preset including all specified parameters, textures, and paths to specified shaders. -/// -/// A shader preset can be used to create a filter chain runtime instance, or reflected to get -/// parameter metadata. +/// Opaque struct for a shader preset. typedef struct _shader_preset _shader_preset; +/// Opaque struct for a preset context. +typedef struct _preset_ctx _preset_ctx; + /// A handle to a librashader error object. typedef struct _libra_error *libra_error_t; /// A handle to a shader preset object. typedef struct _shader_preset *libra_shader_preset_t; +/// A handle to a preset wildcard context object. +typedef struct _preset_ctx *libra_preset_ctx_t; + /// A preset parameter. typedef struct libra_preset_param_t { - /// The name of the parameter - const char *name; - /// The description of the parameter. - const char *description; - /// The initial value the parameter is set to. - float initial; - /// The minimum value that the parameter can be set to. - float minimum; - /// The maximum value that the parameter can be set to. - float maximum; - /// The step by which this parameter can be incremented or decremented. - float step; + /// The name of the parameter + const char *name; + /// The description of the parameter. + const char *description; + /// The initial value the parameter is set to. + float initial; + /// The minimum value that the parameter can be set to. + float minimum; + /// The maximum value that the parameter can be set to. + float maximum; + /// The step by which this parameter can be incremented or decremented. + float step; } libra_preset_param_t; /// A list of preset parameters. 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. - uint64_t length; - /// For internal use only. - /// Changing this causes immediate undefined behaviour on freeing this parameter list. - uint64_t _internal_alloc; + /// A pointer to the parameter + const struct libra_preset_param_t *parameters; + /// 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_param_list_t; #if defined(LIBRA_RUNTIME_OPENGL) /// A GL function loader that librashader needs to be initialized with. -typedef const void *(*libra_gl_loader_t)(const char*); +typedef const void *(*libra_gl_loader_t)(const char *); #endif /// API version type alias. @@ -145,19 +176,20 @@ typedef size_t LIBRASHADER_API_VERSION; #if defined(LIBRA_RUNTIME_OPENGL) /// Options for filter chain creation. typedef struct filter_chain_gl_opt_t { - /// The librashader API version. - LIBRASHADER_API_VERSION version; - /// The GLSL version. Should be at least `330`. - uint16_t glsl_version; - /// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+. - /// Using the shader cache requires this option, so this option will implicitly - /// disables the shader cache if false. - bool use_dsa; - /// Whether or not to explicitly disable mipmap generation regardless of shader preset settings. - bool force_no_mipmaps; - /// Disable the shader object cache. Shaders will be - /// recompiled rather than loaded from the cache. - bool disable_cache; + /// The librashader API version. + LIBRASHADER_API_VERSION version; + /// The GLSL version. Should be at least `330`. + uint16_t glsl_version; + /// Whether or not to use the Direct State Access APIs. Only available on + /// OpenGL 4.5+. Using the shader cache requires this option, so this option + /// will implicitly disables the shader cache if false. + bool use_dsa; + /// Whether or not to explicitly disable mipmap generation regardless of + /// shader preset settings. + bool force_no_mipmaps; + /// Disable the shader object cache. Shaders will be + /// recompiled rather than loaded from the cache. + bool disable_cache; } filter_chain_gl_opt_t; #endif @@ -169,86 +201,88 @@ typedef struct _filter_chain_gl *libra_gl_filter_chain_t; #if defined(LIBRA_RUNTIME_OPENGL) /// OpenGL parameters for the source image. typedef struct libra_source_image_gl_t { - /// A texture GLuint to the source image. - uint32_t handle; - /// The format of the source image. - uint32_t format; - /// The width of the source image. - uint32_t width; - /// The height of the source image. - uint32_t height; + /// A texture GLuint to the source image. + uint32_t handle; + /// The format of the source image. + uint32_t format; + /// The width of the source image. + uint32_t width; + /// The height of the source image. + uint32_t height; } libra_source_image_gl_t; #endif /// Defines the output viewport for a rendered frame. typedef struct libra_viewport_t { - /// The x offset in the viewport framebuffer to begin rendering from. - float x; - /// The y offset in the viewport framebuffer to begin rendering from. - float y; - /// The width of the viewport framebuffer. - uint32_t width; - /// The height of the viewport framebuffer. - uint32_t height; + /// The x offset in the viewport framebuffer to begin rendering from. + float x; + /// The y offset in the viewport framebuffer to begin rendering from. + float y; + /// The width of the viewport framebuffer. + uint32_t width; + /// The height of the viewport framebuffer. + uint32_t height; } libra_viewport_t; #if defined(LIBRA_RUNTIME_OPENGL) /// OpenGL parameters for the output framebuffer. typedef struct libra_output_framebuffer_gl_t { - /// A framebuffer GLuint to the output framebuffer. - uint32_t fbo; - /// A texture GLuint to the logical buffer of the output framebuffer. - uint32_t texture; - /// The format of the output framebuffer. - uint32_t format; + /// A framebuffer GLuint to the output framebuffer. + uint32_t fbo; + /// A texture GLuint to the logical buffer of the output framebuffer. + uint32_t texture; + /// The format of the output framebuffer. + uint32_t format; } libra_output_framebuffer_gl_t; #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Options for each OpenGL shader frame. typedef struct frame_gl_opt_t { - /// The librashader API version. - LIBRASHADER_API_VERSION version; - /// Whether or not to clear the history buffers. - bool clear_history; - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - int32_t frame_direction; + /// The librashader API version. + LIBRASHADER_API_VERSION version; + /// Whether or not to clear the history buffers. + bool clear_history; + /// The direction of rendering. + /// -1 indicates that the frames are played in reverse order. + int32_t frame_direction; } frame_gl_opt_t; #endif #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; + /// 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 #if defined(LIBRA_RUNTIME_VULKAN) /// Options for filter chain creation. typedef struct filter_chain_vk_opt_t { - /// The librashader API version. - size_t version; - /// 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; - /// Use explicit render pass objects It is recommended if possible to use dynamic rendering, - /// because render-pass mode will create new framebuffers per pass. - bool use_render_pass; - /// Disable the shader object cache. Shaders will be - /// recompiled rather than loaded from the cache. - bool disable_cache; + /// The librashader API version. + size_t version; + /// 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; + /// Use explicit render pass objects It is recommended if possible to use + /// dynamic rendering, because render-pass mode will create new framebuffers + /// per pass. + bool use_render_pass; + /// Disable the shader object cache. Shaders will be + /// recompiled rather than loaded from the cache. + bool disable_cache; } filter_chain_vk_opt_t; #endif @@ -260,51 +294,51 @@ typedef struct _filter_chain_vk *libra_vk_filter_chain_t; #if defined(LIBRA_RUNTIME_VULKAN) /// Vulkan parameters for the source image. typedef struct libra_source_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; + /// 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_source_image_vk_t; #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Vulkan parameters for the output image. typedef struct libra_output_image_vk_t { - /// A raw `VkImage` handle to the output image. - VkImage handle; - /// The `VkFormat` of the output image. - VkFormat format; + /// A raw `VkImage` handle to the output image. + VkImage handle; + /// The `VkFormat` of the output image. + VkFormat format; } libra_output_image_vk_t; #endif #if defined(LIBRA_RUNTIME_VULKAN) -/// Options for each OpenGL shader frame. +/// Options for each Vulkan shader frame. typedef struct frame_vk_opt_t { - /// The librashader API version. - size_t version; - /// Whether or not to clear the history buffers. - bool clear_history; - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - int32_t frame_direction; + /// The librashader API version. + size_t version; + /// Whether or not to clear the history buffers. + bool clear_history; + /// The direction of rendering. + /// -1 indicates that the frames are played in reverse order. + int32_t frame_direction; } frame_vk_opt_t; #endif #if defined(LIBRA_RUNTIME_D3D11) /// Options for Direct3D 11 filter chain creation. typedef struct filter_chain_d3d11_opt_t { - /// The librashader API version. - LIBRASHADER_API_VERSION version; - /// Whether or not to explicitly disable mipmap - /// generation regardless of shader preset settings. - bool force_no_mipmaps; - /// Disable the shader object cache. Shaders will be - /// recompiled rather than loaded from the cache. - bool disable_cache; + /// The librashader API version. + LIBRASHADER_API_VERSION version; + /// Whether or not to explicitly disable mipmap + /// generation regardless of shader preset settings. + bool force_no_mipmaps; + /// Disable the shader object cache. Shaders will be + /// recompiled rather than loaded from the cache. + bool disable_cache; } filter_chain_d3d11_opt_t; #endif @@ -316,42 +350,42 @@ typedef struct _filter_chain_d3d11 *libra_d3d11_filter_chain_t; #if defined(LIBRA_RUNTIME_D3D11) /// Direct3D 11 parameters for the source image. typedef struct libra_source_image_d3d11_t { - /// A shader resource view into the source image - ID3D11ShaderResourceView * handle; - /// The width of the source image. - uint32_t width; - /// The height of the source image. - uint32_t height; + /// A shader resource view into the source image + ID3D11ShaderResourceView *handle; + /// The width of the source image. + uint32_t width; + /// The height of the source image. + uint32_t height; } libra_source_image_d3d11_t; #endif #if defined(LIBRA_RUNTIME_D3D11) /// Options for each Direct3D 11 shader frame. typedef struct frame_d3d11_opt_t { - /// The librashader API version. - LIBRASHADER_API_VERSION version; - /// Whether or not to clear the history buffers. - bool clear_history; - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - int32_t frame_direction; + /// The librashader API version. + LIBRASHADER_API_VERSION version; + /// Whether or not to clear the history buffers. + bool clear_history; + /// The direction of rendering. + /// -1 indicates that the frames are played in reverse order. + int32_t frame_direction; } frame_d3d11_opt_t; #endif #if defined(LIBRA_RUNTIME_D3D12) /// Options for Direct3D11 filter chain creation. typedef struct filter_chain_d3d12_opt_t { - /// The librashader API version. - LIBRASHADER_API_VERSION version; - /// Force the HLSL shader pipeline. This may reduce shader compatibility. - bool force_hlsl_pipeline; - /// Whether or not to explicitly disable mipmap - /// generation for intermediate passes regardless - /// of shader preset settings. - bool force_no_mipmaps; - /// Disable the shader object cache. Shaders will be - /// recompiled rather than loaded from the cache. - bool disable_cache; + /// The librashader API version. + LIBRASHADER_API_VERSION version; + /// Force the HLSL shader pipeline. This may reduce shader compatibility. + bool force_hlsl_pipeline; + /// Whether or not to explicitly disable mipmap + /// generation for intermediate passes regardless + /// of shader preset settings. + bool force_no_mipmaps; + /// Disable the shader object cache. Shaders will be + /// recompiled rather than loaded from the cache. + bool disable_cache; } filter_chain_d3d12_opt_t; #endif @@ -363,39 +397,39 @@ typedef struct _filter_chain_d3d12 *libra_d3d12_filter_chain_t; #if defined(LIBRA_RUNTIME_D3D12) /// Direct3D 12 parameters for the source image. typedef struct libra_source_image_d3d12_t { - /// The resource containing the image. - ID3D12Resource * resource; - /// A CPU descriptor handle to a shader resource view of the image. - D3D12_CPU_DESCRIPTOR_HANDLE descriptor; - /// The format of the image. - DXGI_FORMAT format; - /// The width of the source image. - uint32_t width; - /// The height of the source image. - uint32_t height; + /// The resource containing the image. + ID3D12Resource *resource; + /// A CPU descriptor handle to a shader resource view of the image. + D3D12_CPU_DESCRIPTOR_HANDLE descriptor; + /// The format of the image. + DXGI_FORMAT format; + /// The width of the source image. + uint32_t width; + /// The height of the source image. + uint32_t height; } libra_source_image_d3d12_t; #endif #if defined(LIBRA_RUNTIME_D3D12) /// Direct3D 12 parameters for the output image. typedef struct libra_output_image_d3d12_t { - /// A CPU descriptor handle to a shader resource view of the image. - D3D12_CPU_DESCRIPTOR_HANDLE descriptor; - /// The format of the image. - DXGI_FORMAT format; + /// A CPU descriptor handle to a shader resource view of the image. + D3D12_CPU_DESCRIPTOR_HANDLE descriptor; + /// The format of the image. + DXGI_FORMAT format; } libra_output_image_d3d12_t; #endif #if defined(LIBRA_RUNTIME_D3D12) /// Options for each Direct3D 12 shader frame. typedef struct frame_d3d12_opt_t { - /// The librashader API version. - LIBRASHADER_API_VERSION version; - /// Whether or not to clear the history buffers. - bool clear_history; - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - int32_t frame_direction; + /// The librashader API version. + LIBRASHADER_API_VERSION version; + /// Whether or not to clear the history buffers. + bool clear_history; + /// The direction of rendering. + /// -1 indicates that the frames are played in reverse order. + int32_t frame_direction; } frame_d3d12_opt_t; #endif @@ -408,37 +442,101 @@ typedef LIBRASHADER_ABI_VERSION (*PFN_libra_instance_abi_version)(void); 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); +/// libra_preset_create +typedef libra_error_t (*PFN_libra_preset_create)(const char *filename, + libra_shader_preset_t *out); /// Function pointer definition for -///libra_preset_free +/// libra_preset_free typedef libra_error_t (*PFN_libra_preset_free)(libra_shader_preset_t *preset); /// Function pointer definition for -///libra_preset_set_param -typedef libra_error_t (*PFN_libra_preset_set_param)(libra_shader_preset_t *preset, - const char *name, - float value); +/// libra_preset_set_param +typedef libra_error_t (*PFN_libra_preset_set_param)( + libra_shader_preset_t *preset, const char *name, float value); /// Function pointer definition for -///libra_preset_get_param -typedef libra_error_t (*PFN_libra_preset_get_param)(libra_shader_preset_t *preset, - const char *name, - float *value); +/// libra_preset_get_param +typedef libra_error_t (*PFN_libra_preset_get_param)( + libra_shader_preset_t *preset, const char *name, float *value); /// Function pointer definition for -///libra_preset_print +/// 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); +/// 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); +/// 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_preset_create_with_context +typedef libra_error_t (*PFN_libra_preset_create_with_context)( + const char *filename, libra_preset_ctx_t *context, + libra_shader_preset_t *out); + +/// Function pointer definition for +/// libra_preset_ctx_create +typedef libra_error_t (*PFN_libra_preset_ctx_create)(libra_preset_ctx_t *out); + +/// Function pointer definition for +/// libra_preset_ctx_free +typedef libra_error_t (*PFN_libra_preset_ctx_free)(libra_preset_ctx_t *context); + +/// Function pointer definition for +/// libra_preset_ctx_set_core_name +typedef libra_error_t (*PFN_libra_preset_ctx_set_core_name)( + libra_preset_ctx_t *context, const char *name); + +/// Function pointer definition for +/// libra_preset_ctx_set_content_dir +typedef libra_error_t (*PFN_libra_preset_ctx_set_content_dir)( + libra_preset_ctx_t *context, const char *name); + +/// Function pointer definition for +/// libra_preset_ctx_set_param +typedef libra_error_t (*PFN_libra_preset_ctx_set_param)( + libra_preset_ctx_t *context, const char *name, const char *value); + +/// Function pointer definition for +/// libra_preset_ctx_set_core_rotation +typedef libra_error_t (*PFN_libra_preset_ctx_set_core_rotation)( + libra_preset_ctx_t *context, uint32_t value); + +/// Function pointer definition for +/// libra_preset_ctx_set_user_rotation +typedef libra_error_t (*PFN_libra_preset_ctx_set_user_rotation)( + libra_preset_ctx_t *context, uint32_t value); + +/// Function pointer definition for +/// libra_preset_ctx_set_screen_orientation +typedef libra_error_t (*PFN_libra_preset_ctx_set_screen_orientation)( + libra_preset_ctx_t *context, uint32_t value); + +/// Function pointer definition for +/// libra_preset_ctx_set_allow_rotation +typedef libra_error_t (*PFN_libra_preset_ctx_set_allow_rotation)( + libra_preset_ctx_t *context, bool value); + +/// Function pointer definition for +/// libra_preset_ctx_set_view_aspect_orientation +typedef libra_error_t (*PFN_libra_preset_ctx_set_view_aspect_orientation)( + libra_preset_ctx_t *context, LIBRA_PRESET_CTX_ORIENTATION value); + +/// Function pointer definition for +/// libra_preset_ctx_set_core_aspect_orientation +typedef libra_error_t (*PFN_libra_preset_ctx_set_core_aspect_orientation)( + libra_preset_ctx_t *context, LIBRA_PRESET_CTX_ORIENTATION value); + +/// Function pointer definition for +/// libra_preset_ctx_set_runtime +typedef libra_error_t (*PFN_libra_preset_ctx_set_runtime)( + libra_preset_ctx_t *context, LIBRA_PRESET_CTX_RUNTIME value); /// Function pointer definition for libra_error_errno typedef LIBRA_ERRNO (*PFN_libra_error_errno)(libra_error_t error); @@ -457,268 +555,251 @@ typedef int32_t (*PFN_libra_error_free_string)(char **out); #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for -///libra_gl_init_context +/// libra_gl_init_context typedef libra_error_t (*PFN_libra_gl_init_context)(libra_gl_loader_t loader); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for -///libra_gl_filter_chain_create -typedef libra_error_t (*PFN_libra_gl_filter_chain_create)(libra_shader_preset_t *preset, - const struct filter_chain_gl_opt_t *options, - libra_gl_filter_chain_t *out); +/// libra_gl_filter_chain_create +typedef libra_error_t (*PFN_libra_gl_filter_chain_create)( + libra_shader_preset_t *preset, const struct filter_chain_gl_opt_t *options, + libra_gl_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for -///libra_gl_filter_chain_frame -typedef libra_error_t (*PFN_libra_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_output_framebuffer_gl_t out, - const float *mvp, - const struct frame_gl_opt_t *opt); +/// libra_gl_filter_chain_frame +typedef libra_error_t (*PFN_libra_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_output_framebuffer_gl_t out, const float *mvp, + const struct frame_gl_opt_t *opt); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for -///libra_gl_filter_chain_set_param -typedef libra_error_t (*PFN_libra_gl_filter_chain_set_param)(libra_gl_filter_chain_t *chain, - const char *param_name, - float value); +/// libra_gl_filter_chain_set_param +typedef libra_error_t (*PFN_libra_gl_filter_chain_set_param)( + libra_gl_filter_chain_t *chain, const char *param_name, float value); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for -///libra_gl_filter_chain_get_param -typedef libra_error_t (*PFN_libra_gl_filter_chain_get_param)(libra_gl_filter_chain_t *chain, - const char *param_name, - float *out); +/// libra_gl_filter_chain_get_param +typedef libra_error_t (*PFN_libra_gl_filter_chain_get_param)( + libra_gl_filter_chain_t *chain, const char *param_name, float *out); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for -///libra_gl_filter_chain_set_active_pass_count -typedef libra_error_t (*PFN_libra_gl_filter_chain_set_active_pass_count)(libra_gl_filter_chain_t *chain, - uint32_t value); +/// libra_gl_filter_chain_set_active_pass_count +typedef libra_error_t (*PFN_libra_gl_filter_chain_set_active_pass_count)( + libra_gl_filter_chain_t *chain, uint32_t value); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for -///libra_gl_filter_chain_get_active_pass_count -typedef libra_error_t (*PFN_libra_gl_filter_chain_get_active_pass_count)(libra_gl_filter_chain_t *chain, - uint32_t *out); +/// libra_gl_filter_chain_get_active_pass_count +typedef libra_error_t (*PFN_libra_gl_filter_chain_get_active_pass_count)( + libra_gl_filter_chain_t *chain, uint32_t *out); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for -///libra_gl_filter_chain_free -typedef libra_error_t (*PFN_libra_gl_filter_chain_free)(libra_gl_filter_chain_t *chain); +/// libra_gl_filter_chain_free +typedef libra_error_t (*PFN_libra_gl_filter_chain_free)( + libra_gl_filter_chain_t *chain); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Function pointer definition for -///libra_vk_filter_chain_create -typedef libra_error_t (*PFN_libra_vk_filter_chain_create)(libra_shader_preset_t *preset, - struct libra_device_vk_t vulkan, - const struct filter_chain_vk_opt_t *options, - libra_vk_filter_chain_t *out); +/// libra_vk_filter_chain_create +typedef libra_error_t (*PFN_libra_vk_filter_chain_create)( + libra_shader_preset_t *preset, struct libra_device_vk_t vulkan, + const struct filter_chain_vk_opt_t *options, libra_vk_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Function pointer definition for -///libra_vk_filter_chain_create_deferred -typedef libra_error_t (*PFN_libra_vk_filter_chain_create_deferred)(libra_shader_preset_t *preset, - struct libra_device_vk_t vulkan, - VkCommandBuffer command_buffer, - const struct filter_chain_vk_opt_t *options, - libra_vk_filter_chain_t *out); +/// libra_vk_filter_chain_create_deferred +typedef libra_error_t (*PFN_libra_vk_filter_chain_create_deferred)( + libra_shader_preset_t *preset, struct libra_device_vk_t vulkan, + VkCommandBuffer command_buffer, const struct filter_chain_vk_opt_t *options, + libra_vk_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Function pointer definition for -///libra_vk_filter_chain_frame -typedef libra_error_t (*PFN_libra_vk_filter_chain_frame)(libra_vk_filter_chain_t *chain, - VkCommandBuffer command_buffer, - size_t frame_count, - struct libra_source_image_vk_t image, - struct libra_viewport_t viewport, - struct libra_output_image_vk_t out, - const float *mvp, - const struct frame_vk_opt_t *opt); +/// libra_vk_filter_chain_frame +typedef libra_error_t (*PFN_libra_vk_filter_chain_frame)( + libra_vk_filter_chain_t *chain, VkCommandBuffer command_buffer, + size_t frame_count, struct libra_source_image_vk_t image, + struct libra_viewport_t viewport, struct libra_output_image_vk_t out, + const float *mvp, const struct frame_vk_opt_t *opt); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Function pointer definition for -///libra_vk_filter_chain_set_param -typedef libra_error_t (*PFN_libra_vk_filter_chain_set_param)(libra_vk_filter_chain_t *chain, - const char *param_name, - float value); +/// libra_vk_filter_chain_set_param +typedef libra_error_t (*PFN_libra_vk_filter_chain_set_param)( + libra_vk_filter_chain_t *chain, const char *param_name, float value); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Function pointer definition for -///libra_vk_filter_chain_get_param -typedef libra_error_t (*PFN_libra_vk_filter_chain_get_param)(libra_vk_filter_chain_t *chain, - const char *param_name, - float *out); +/// libra_vk_filter_chain_get_param +typedef libra_error_t (*PFN_libra_vk_filter_chain_get_param)( + libra_vk_filter_chain_t *chain, const char *param_name, float *out); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Function pointer definition for -///libra_vk_filter_chain_set_active_pass_count -typedef libra_error_t (*PFN_libra_vk_filter_chain_set_active_pass_count)(libra_vk_filter_chain_t *chain, - uint32_t value); +/// libra_vk_filter_chain_set_active_pass_count +typedef libra_error_t (*PFN_libra_vk_filter_chain_set_active_pass_count)( + libra_vk_filter_chain_t *chain, uint32_t value); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Function pointer definition for -///libra_vk_filter_chain_get_active_pass_count -typedef libra_error_t (*PFN_libra_vk_filter_chain_get_active_pass_count)(libra_vk_filter_chain_t *chain, - uint32_t *out); +/// libra_vk_filter_chain_get_active_pass_count +typedef libra_error_t (*PFN_libra_vk_filter_chain_get_active_pass_count)( + libra_vk_filter_chain_t *chain, uint32_t *out); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Function pointer definition for -///libra_vk_filter_chain_free -typedef libra_error_t (*PFN_libra_vk_filter_chain_free)(libra_vk_filter_chain_t *chain); +/// libra_vk_filter_chain_free +typedef libra_error_t (*PFN_libra_vk_filter_chain_free)( + libra_vk_filter_chain_t *chain); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for -///libra_d3d11_filter_chain_create -typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create)(libra_shader_preset_t *preset, - ID3D11Device * device, - const struct filter_chain_d3d11_opt_t *options, - libra_d3d11_filter_chain_t *out); +/// libra_d3d11_filter_chain_create +typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create)( + libra_shader_preset_t *preset, ID3D11Device *device, + const struct filter_chain_d3d11_opt_t *options, + libra_d3d11_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for -///libra_d3d11_filter_chain_create_deferred -typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create_deferred)(libra_shader_preset_t *preset, - ID3D11Device * device, - ID3D11DeviceContext * device_context, - const struct filter_chain_d3d11_opt_t *options, - libra_d3d11_filter_chain_t *out); +/// libra_d3d11_filter_chain_create_deferred +typedef libra_error_t (*PFN_libra_d3d11_filter_chain_create_deferred)( + libra_shader_preset_t *preset, ID3D11Device *device, + ID3D11DeviceContext *device_context, + const struct filter_chain_d3d11_opt_t *options, + libra_d3d11_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for -///libra_d3d11_filter_chain_frame -typedef libra_error_t (*PFN_libra_d3d11_filter_chain_frame)(libra_d3d11_filter_chain_t *chain, - ID3D11DeviceContext * device_context, - size_t frame_count, - struct libra_source_image_d3d11_t image, - struct libra_viewport_t viewport, - ID3D11RenderTargetView * out, - const float *mvp, - const struct frame_d3d11_opt_t *options); +/// libra_d3d11_filter_chain_frame +typedef libra_error_t (*PFN_libra_d3d11_filter_chain_frame)( + libra_d3d11_filter_chain_t *chain, ID3D11DeviceContext *device_context, + size_t frame_count, struct libra_source_image_d3d11_t image, + struct libra_viewport_t viewport, ID3D11RenderTargetView *out, + const float *mvp, const struct frame_d3d11_opt_t *options); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for -///libra_d3d11_filter_chain_set_param -typedef libra_error_t (*PFN_libra_d3d11_filter_chain_set_param)(libra_d3d11_filter_chain_t *chain, - const char *param_name, - float value); +/// libra_d3d11_filter_chain_set_param +typedef libra_error_t (*PFN_libra_d3d11_filter_chain_set_param)( + libra_d3d11_filter_chain_t *chain, const char *param_name, float value); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for -///libra_d3d11_filter_chain_get_param -typedef libra_error_t (*PFN_libra_d3d11_filter_chain_get_param)(libra_d3d11_filter_chain_t *chain, - const char *param_name, - float *out); +/// libra_d3d11_filter_chain_get_param +typedef libra_error_t (*PFN_libra_d3d11_filter_chain_get_param)( + libra_d3d11_filter_chain_t *chain, const char *param_name, float *out); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for -///libra_d3d11_filter_chain_set_active_pass_count -typedef libra_error_t (*PFN_libra_d3d11_filter_chain_set_active_pass_count)(libra_d3d11_filter_chain_t *chain, - uint32_t value); +/// libra_d3d11_filter_chain_set_active_pass_count +typedef libra_error_t (*PFN_libra_d3d11_filter_chain_set_active_pass_count)( + libra_d3d11_filter_chain_t *chain, uint32_t value); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for -///libra_d3d11_filter_chain_get_active_pass_count -typedef libra_error_t (*PFN_libra_d3d11_filter_chain_get_active_pass_count)(libra_d3d11_filter_chain_t *chain, - uint32_t *out); +/// libra_d3d11_filter_chain_get_active_pass_count +typedef libra_error_t (*PFN_libra_d3d11_filter_chain_get_active_pass_count)( + libra_d3d11_filter_chain_t *chain, uint32_t *out); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for -///libra_d3d11_filter_chain_free -typedef libra_error_t (*PFN_libra_d3d11_filter_chain_free)(libra_d3d11_filter_chain_t *chain); +/// libra_d3d11_filter_chain_free +typedef libra_error_t (*PFN_libra_d3d11_filter_chain_free)( + libra_d3d11_filter_chain_t *chain); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_d3d12_filter_chain_create -typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)(libra_shader_preset_t *preset, - ID3D12Device * device, - const struct filter_chain_d3d12_opt_t *options, - libra_d3d12_filter_chain_t *out); +/// libra_d3d12_filter_chain_create +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)( + libra_shader_preset_t *preset, ID3D12Device *device, + const struct filter_chain_d3d12_opt_t *options, + libra_d3d12_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_d3d12_filter_chain_create_deferred -typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create_deferred)(libra_shader_preset_t *preset, - ID3D12Device * device, - ID3D12GraphicsCommandList * command_list, - const struct filter_chain_d3d12_opt_t *options, - libra_d3d12_filter_chain_t *out); +/// libra_d3d12_filter_chain_create_deferred +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create_deferred)( + libra_shader_preset_t *preset, ID3D12Device *device, + ID3D12GraphicsCommandList *command_list, + const struct filter_chain_d3d12_opt_t *options, + libra_d3d12_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_d3d12_filter_chain_frame -typedef libra_error_t (*PFN_libra_d3d12_filter_chain_frame)(libra_d3d12_filter_chain_t *chain, - ID3D12GraphicsCommandList * command_list, - size_t frame_count, - struct libra_source_image_d3d12_t image, - struct libra_viewport_t viewport, - struct libra_output_image_d3d12_t out, - const float *mvp, - const struct frame_d3d12_opt_t *options); +/// libra_d3d12_filter_chain_frame +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_frame)( + libra_d3d12_filter_chain_t *chain, ID3D12GraphicsCommandList *command_list, + size_t frame_count, struct libra_source_image_d3d12_t image, + struct libra_viewport_t viewport, struct libra_output_image_d3d12_t out, + const float *mvp, const struct frame_d3d12_opt_t *options); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_d3d12_filter_chain_set_param -typedef libra_error_t (*PFN_libra_d3d12_filter_chain_set_param)(libra_d3d12_filter_chain_t *chain, - const char *param_name, - float value); +/// libra_d3d12_filter_chain_set_param +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_set_param)( + libra_d3d12_filter_chain_t *chain, const char *param_name, float value); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_d3d12_filter_chain_get_param -typedef libra_error_t (*PFN_libra_d3d12_filter_chain_get_param)(libra_d3d12_filter_chain_t *chain, - const char *param_name, - float *out); +/// libra_d3d12_filter_chain_get_param +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_get_param)( + libra_d3d12_filter_chain_t *chain, const char *param_name, float *out); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_d3d12_filter_chain_set_active_pass_count -typedef libra_error_t (*PFN_libra_d3d12_filter_chain_set_active_pass_count)(libra_d3d12_filter_chain_t *chain, - uint32_t value); +/// libra_d3d12_filter_chain_set_active_pass_count +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_set_active_pass_count)( + libra_d3d12_filter_chain_t *chain, uint32_t value); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_d3d12_filter_chain_get_active_pass_count -typedef libra_error_t (*PFN_libra_d3d12_filter_chain_get_active_pass_count)(libra_d3d12_filter_chain_t *chain, - uint32_t *out); +/// libra_d3d12_filter_chain_get_active_pass_count +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_get_active_pass_count)( + libra_d3d12_filter_chain_t *chain, uint32_t *out); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_d3d12_filter_chain_free -typedef libra_error_t (*PFN_libra_d3d12_filter_chain_free)(libra_d3d12_filter_chain_t *chain); +/// libra_d3d12_filter_chain_free +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_free)( + libra_d3d12_filter_chain_t *chain); #endif /// The current version of the librashader API. @@ -747,7 +828,7 @@ typedef libra_error_t (*PFN_libra_d3d12_filter_chain_free)(libra_d3d12_filter_ch #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /// Get the error code corresponding to this error object. /// @@ -757,62 +838,93 @@ LIBRA_ERRNO libra_error_errno(libra_error_t error); /// Print the error message. /// -/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0. +/// If `error` is null, this function does nothing and returns 1. Otherwise, +/// this function returns 0. /// ## Safety /// - `error` must be a valid and initialized instance of `libra_error_t`. int32_t libra_error_print(libra_error_t error); /// Frees any internal state kept by the error. /// -/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0. -/// The resulting error object becomes null. +/// If `error` is null, this function does nothing and returns 1. Otherwise, +/// this function returns 0. The resulting error object becomes null. /// ## Safety -/// - `error` must be null or a pointer to a valid and initialized instance of `libra_error_t`. +/// - `error` must be null or a pointer to a valid and initialized instance of +/// `libra_error_t`. int32_t libra_error_free(libra_error_t *error); /// Writes the error message into `out` /// -/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0. +/// If `error` is null, this function does nothing and returns 1. Otherwise, +/// this function returns 0. /// ## Safety /// - `error` must be a valid and initialized instance of `libra_error_t`. -/// - `out` must be a non-null pointer. The resulting string must not be modified. -int32_t libra_error_write(libra_error_t error, - char **out); +/// - `out` must be a non-null pointer. The resulting string must not be +/// modified. +int32_t libra_error_write(libra_error_t error, char **out); /// Frees an error string previously allocated by `libra_error_write`. /// /// After freeing, the pointer will be set to null. /// ## Safety -/// - If `libra_error_write` is not null, it must point to a string previously returned by `libra_error_write`. -/// Attempting to free anything else, including strings or objects from other librashader functions, is immediate -/// Undefined Behaviour. +/// - If `libra_error_write` is not null, it must point to a string previously +/// returned by `libra_error_write`. +/// Attempting to free anything else, including strings or objects from +/// other librashader functions, is immediate Undefined Behaviour. int32_t libra_error_free_string(char **out); /// Load a preset. /// /// ## Safety -/// - `filename` must be either null or a valid, aligned pointer to a string path to the shader preset. -/// - `out` must be either null, or an aligned pointer to an uninitialized or invalid `libra_shader_preset_t`. +/// - `filename` must be either null or a valid, aligned pointer to a string +/// path to the shader preset. +/// - `out` must be either null, or an aligned pointer to an uninitialized or +/// invalid `libra_shader_preset_t`. /// ## Returns -/// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`. +/// - If any parameters are null, `out` is unchanged, and this function returns +/// `LIBRA_ERR_INVALID_PARAMETER`. libra_error_t libra_preset_create(const char *filename, libra_shader_preset_t *out); +/// Load a preset with the given wildcard context. +/// +/// The wildcard context is immediately invalidated and must be recreated after +/// the preset is created. +/// +/// Path information variables `PRESET_DIR` and `PRESET` will automatically be +/// filled in. +/// ## Safety +/// - `filename` must be either null or a valid, aligned pointer to a string +/// path to the shader preset. +/// - `context` must be either null or a valid, aligned pointer to a +/// initialized `libra_preset_ctx_t`. +/// - `context` is invalidated after this function returns. +/// - `out` must be either null, or an aligned pointer to an uninitialized or +/// invalid `libra_shader_preset_t`. +/// ## Returns +/// - If any parameters are null, `out` is unchanged, and this function returns +/// `LIBRA_ERR_INVALID_PARAMETER`. +libra_error_t libra_preset_create_with_context(const char *filename, + libra_preset_ctx_t *context, + libra_shader_preset_t *out); + /// Free the preset. /// -/// If `preset` is null, this function does nothing. The resulting value in `preset` then becomes -/// null. +/// If `preset` is null, this function does nothing. The resulting value in +/// `preset` then becomes null. /// /// ## Safety -/// - `preset` must be a valid and aligned pointer to a shader preset. +/// - `preset` must be a valid and aligned pointer to a `libra_shader_preset_t`. libra_error_t libra_preset_free(libra_shader_preset_t *preset); /// Set the value of the parameter in the preset. /// /// ## Safety -/// - `preset` must be null or a valid and aligned pointer to a shader preset. +/// - `preset` must be null or a valid and aligned pointer to a +/// `libra_shader_preset_t`. /// - `name` must be null or a valid and aligned pointer to a string. -libra_error_t libra_preset_set_param(libra_shader_preset_t *preset, const char *name, float value); +libra_error_t libra_preset_set_param(libra_shader_preset_t *preset, + const char *name, float value); /// Get the value of the parameter as set in the preset. /// @@ -820,26 +932,31 @@ libra_error_t libra_preset_set_param(libra_shader_preset_t *preset, const char * /// - `preset` must be null or a valid and aligned pointer to a shader preset. /// - `name` must be null or a valid and aligned pointer to a string. /// - `value` may be a pointer to a uninitialized `float`. -libra_error_t libra_preset_get_param(libra_shader_preset_t *preset, const char *name, float *value); +libra_error_t libra_preset_get_param(libra_shader_preset_t *preset, + const char *name, float *value); /// Pretty print the shader preset. /// /// ## Safety -/// - `preset` must be null or a valid and aligned pointer to a shader preset. +/// - `preset` must be null or a valid and aligned pointer to a +/// `libra_shader_preset_t`. libra_error_t libra_preset_print(libra_shader_preset_t *preset); /// Get a list of runtime parameters. /// /// ## Safety -/// - `preset` must be null or a valid and aligned pointer to a shader preset. +/// - `preset` must be null or a valid and aligned pointer to a +/// `libra_shader_preset_t`. /// - `out` must be an aligned pointer to a `libra_preset_parameter_list_t`. -/// - The output struct should be treated as immutable. Mutating any struct fields +/// - 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 +/// - 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); +libra_error_t libra_preset_get_runtime_params( + libra_shader_preset_t *preset, struct libra_preset_param_list_t *out); /// Free the runtime parameters. /// @@ -849,18 +966,23 @@ libra_error_t libra_preset_get_runtime_params(libra_shader_preset_t *preset, /// 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`. +/// - 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 +/// - 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 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. @@ -869,10 +991,12 @@ libra_error_t libra_preset_free_runtime_params(struct libra_preset_param_list_t /// unless for whatever reason you switch OpenGL loaders mid-flight. /// /// ## Safety -/// Attempting to create a filter chain will fail if the GL context is not initialized. +/// Attempting to create a filter chain will fail if the GL context is not +/// initialized. /// -/// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter -/// chain objects, and drawing with them causes immediate undefined behaviour. +/// 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(libra_gl_loader_t loader); #endif @@ -886,32 +1010,35 @@ libra_error_t libra_gl_init_context(libra_gl_loader_t loader); /// - `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_gl_filter_chain_create(libra_shader_preset_t *preset, - const struct filter_chain_gl_opt_t *options, - libra_gl_filter_chain_t *out); +libra_error_t libra_gl_filter_chain_create( + libra_shader_preset_t *preset, const struct filter_chain_gl_opt_t *options, + libra_gl_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Draw a frame with the given parameters for the given filter chain. /// /// ## Safety -/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this +/// - `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` +/// - `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` +/// - `opt` may be null, or if it is not null, must be an aligned pointer to a +/// valid `frame_gl_opt_t` /// struct. -/// - You must ensure that only one thread has access to `chain` before you call this function. Only one -/// thread at a time may call this function. The thread `libra_gl_filter_chain_frame` is called from -/// must have its thread-local OpenGL context initialized with the same context used to create -/// the filter chain. -libra_error_t libra_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_output_framebuffer_gl_t out, - const float *mvp, - const struct frame_gl_opt_t *opt); +/// - You must ensure that only one thread has access to `chain` before you call +/// this function. Only one +/// thread at a time may call this function. The thread +/// `libra_gl_filter_chain_frame` is called from must have its thread-local +/// OpenGL context initialized with the same context used to create the filter +/// chain. +libra_error_t libra_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_output_framebuffer_gl_t out, const float *mvp, + const struct frame_gl_opt_t *opt); #endif #if defined(LIBRA_RUNTIME_OPENGL) @@ -919,7 +1046,8 @@ libra_error_t libra_gl_filter_chain_frame(libra_gl_filter_chain_t *chain, /// /// If the parameter does not exist, returns an error. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_gl_filter_chain_t`. /// - `param_name` must be either null or a null terminated string. libra_error_t libra_gl_filter_chain_set_param(libra_gl_filter_chain_t *chain, const char *param_name, @@ -931,7 +1059,8 @@ libra_error_t libra_gl_filter_chain_set_param(libra_gl_filter_chain_t *chain, /// /// If the parameter does not exist, returns an error. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_gl_filter_chain_t`. /// - `param_name` must be either null or a null terminated string. libra_error_t libra_gl_filter_chain_get_param(libra_gl_filter_chain_t *chain, const char *param_name, @@ -942,18 +1071,20 @@ libra_error_t libra_gl_filter_chain_get_param(libra_gl_filter_chain_t *chain, /// Sets the number of active passes for this chain. /// /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. -libra_error_t libra_gl_filter_chain_set_active_pass_count(libra_gl_filter_chain_t *chain, - uint32_t value); +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_gl_filter_chain_t`. +libra_error_t libra_gl_filter_chain_set_active_pass_count( + libra_gl_filter_chain_t *chain, uint32_t value); #endif #if defined(LIBRA_RUNTIME_OPENGL) /// Gets the number of active passes for this chain. /// /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. -libra_error_t libra_gl_filter_chain_get_active_pass_count(libra_gl_filter_chain_t *chain, - uint32_t *out); +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_gl_filter_chain_t`. +libra_error_t libra_gl_filter_chain_get_active_pass_count( + libra_gl_filter_chain_t *chain, uint32_t *out); #endif #if defined(LIBRA_RUNTIME_OPENGL) @@ -961,7 +1092,8 @@ libra_error_t libra_gl_filter_chain_get_active_pass_count(libra_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`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_gl_filter_chain_t`. libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t *chain); #endif @@ -972,73 +1104,79 @@ libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t *chain); /// 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 +/// - 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(libra_shader_preset_t *preset, - struct libra_device_vk_t vulkan, - const struct filter_chain_vk_opt_t *options, - libra_vk_filter_chain_t *out); +libra_error_t libra_vk_filter_chain_create( + libra_shader_preset_t *preset, struct libra_device_vk_t vulkan, + const struct filter_chain_vk_opt_t *options, libra_vk_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_VULKAN) -/// Create the filter chain given the shader preset deferring and GPU-side initialization -/// to the caller. This function therefore requires no external synchronization of the device queue. +/// Create the filter chain given the shader preset deferring and GPU-side +/// initialization to the caller. This function therefore requires no external +/// synchronization of the device queue. /// /// 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 +/// - 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. /// -/// The provided command buffer must be ready for recording and contain no prior commands. -/// The caller is responsible for ending the command buffer and immediately submitting it to a -/// graphics queue. The command buffer must be completely executed before calling `libra_vk_filter_chain_frame`. -libra_error_t libra_vk_filter_chain_create_deferred(libra_shader_preset_t *preset, - struct libra_device_vk_t vulkan, - VkCommandBuffer command_buffer, - const struct filter_chain_vk_opt_t *options, - libra_vk_filter_chain_t *out); +/// The provided command buffer must be ready for recording and contain no prior +/// commands. The caller is responsible for ending the command buffer and +/// immediately submitting it to a graphics queue. The command buffer must be +/// completely executed before calling `libra_vk_filter_chain_frame`. +libra_error_t libra_vk_filter_chain_create_deferred( + libra_shader_preset_t *preset, struct libra_device_vk_t vulkan, + VkCommandBuffer command_buffer, 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. +/// Records rendering commands for a frame with the given parameters for the +/// given filter chain to the input command buffer. /// /// * The input image must be in the `VK_SHADER_READ_ONLY_OPTIMAL` layout. /// * The output image must be in `VK_COLOR_ATTACHMENT_OPTIMAL` layout. /// -/// librashader **will not** create a pipeline barrier for the final pass. The output image will -/// remain in `VK_COLOR_ATTACHMENT_OPTIMAL` after all shader passes. The caller must transition -/// the output image to the final layout. +/// librashader **will not** create a pipeline barrier for the final pass. The +/// output image will remain in `VK_COLOR_ATTACHMENT_OPTIMAL` after all shader +/// passes. The caller must transition the output image to the final layout. /// /// ## 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 +/// - `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` +/// - `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_vk_opt_t` +/// - `opt` may be null, or if it is not null, must be an aligned pointer to a +/// valid `frame_vk_opt_t` /// struct. -/// - You must ensure that only one thread has access to `chain` before you call this function. Only one +/// - You must ensure that only one thread has access to `chain` before you call +/// this function. Only one /// thread at a time may call this function. -libra_error_t libra_vk_filter_chain_frame(libra_vk_filter_chain_t *chain, - VkCommandBuffer command_buffer, - size_t frame_count, - struct libra_source_image_vk_t image, - struct libra_viewport_t viewport, - struct libra_output_image_vk_t out, - const float *mvp, - const struct frame_vk_opt_t *opt); +libra_error_t libra_vk_filter_chain_frame( + libra_vk_filter_chain_t *chain, VkCommandBuffer command_buffer, + size_t frame_count, struct libra_source_image_vk_t image, + struct libra_viewport_t viewport, struct libra_output_image_vk_t out, + const float *mvp, const struct frame_vk_opt_t *opt); #endif #if defined(LIBRA_RUNTIME_VULKAN) @@ -1046,7 +1184,8 @@ libra_error_t libra_vk_filter_chain_frame(libra_vk_filter_chain_t *chain, /// /// If the parameter does not exist, returns an error. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_vk_filter_chain_t`. /// - `param_name` must be either null or a null terminated string. libra_error_t libra_vk_filter_chain_set_param(libra_vk_filter_chain_t *chain, const char *param_name, @@ -1058,7 +1197,8 @@ libra_error_t libra_vk_filter_chain_set_param(libra_vk_filter_chain_t *chain, /// /// If the parameter does not exist, returns an error. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_vk_filter_chain_t`. /// - `param_name` must be either null or a null terminated string. libra_error_t libra_vk_filter_chain_get_param(libra_vk_filter_chain_t *chain, const char *param_name, @@ -1069,18 +1209,20 @@ libra_error_t libra_vk_filter_chain_get_param(libra_vk_filter_chain_t *chain, /// Sets the number of active passes for this chain. /// /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. -libra_error_t libra_vk_filter_chain_set_active_pass_count(libra_vk_filter_chain_t *chain, - uint32_t value); +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_vk_filter_chain_t`. +libra_error_t libra_vk_filter_chain_set_active_pass_count( + libra_vk_filter_chain_t *chain, uint32_t value); #endif #if defined(LIBRA_RUNTIME_VULKAN) /// Gets the number of active passes for this chain. /// /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_vk_filter_chain_t`. -libra_error_t libra_vk_filter_chain_get_active_pass_count(libra_vk_filter_chain_t *chain, - uint32_t *out); +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_vk_filter_chain_t`. +libra_error_t libra_vk_filter_chain_get_active_pass_count( + libra_vk_filter_chain_t *chain, uint32_t *out); #endif #if defined(LIBRA_RUNTIME_VULKAN) @@ -1088,7 +1230,8 @@ libra_error_t libra_vk_filter_chain_get_active_pass_count(libra_vk_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_vk_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_vk_filter_chain_t`. libra_error_t libra_vk_filter_chain_free(libra_vk_filter_chain_t *chain); #endif @@ -1103,17 +1246,18 @@ libra_error_t libra_vk_filter_chain_free(libra_vk_filter_chain_t *chain); /// - `options` must be either null, or valid and aligned. /// - `device` must not be null. /// - `out` must be aligned, but may be null, invalid, or uninitialized. -libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t *preset, - ID3D11Device * device, - const struct filter_chain_d3d11_opt_t *options, - libra_d3d11_filter_chain_t *out); +libra_error_t libra_d3d11_filter_chain_create( + libra_shader_preset_t *preset, ID3D11Device *device, + const struct filter_chain_d3d11_opt_t *options, + libra_d3d11_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_D3D11) -/// Create the filter chain given the shader preset, deferring and GPU-side initialization -/// to the caller. This function is therefore requires no external synchronization of the -/// immediate context, as long as the immediate context is not used as the input context, -/// nor of the device, as long as the device is not single-threaded only. +/// Create the filter chain given the shader preset, deferring and GPU-side +/// initialization to the caller. This function is therefore requires no +/// external synchronization of the immediate context, as long as the immediate +/// context is not used as the input context, nor of the device, as long as the +/// device is not single-threaded only. /// /// The shader preset is immediately invalidated and must be recreated after /// the filter chain is created. @@ -1125,51 +1269,58 @@ libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t *preset, /// - `device_context` not be null. /// - `out` must be aligned, but may be null, invalid, or uninitialized. /// -/// The provided context must either be immediate, or immediately submitted after this function -/// returns, **before drawing frames**, or lookup textures will fail to load and the filter chain -/// will be in an invalid state. +/// The provided context must either be immediate, or immediately submitted +/// after this function returns, **before drawing frames**, or lookup textures +/// will fail to load and the filter chain will be in an invalid state. /// -/// If the context is deferred, it must be ready for command recording, and have no prior commands -/// recorded. No commands shall be recorded after, the caller must immediately call [`FinishCommandList`](https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-finishcommandlist) -/// and execute the command list on the immediate context after this function returns. +/// If the context is deferred, it must be ready for command recording, and have +/// no prior commands recorded. No commands shall be recorded after, the caller +/// must immediately call +/// [`FinishCommandList`](https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-finishcommandlist) +/// and execute the command list on the immediate context after this function +/// returns. /// -/// If the context is immediate, then access to the immediate context requires external synchronization. -libra_error_t libra_d3d11_filter_chain_create_deferred(libra_shader_preset_t *preset, - ID3D11Device * device, - ID3D11DeviceContext * device_context, - const struct filter_chain_d3d11_opt_t *options, - libra_d3d11_filter_chain_t *out); +/// If the context is immediate, then access to the immediate context requires +/// external synchronization. +libra_error_t libra_d3d11_filter_chain_create_deferred( + libra_shader_preset_t *preset, ID3D11Device *device, + ID3D11DeviceContext *device_context, + const struct filter_chain_d3d11_opt_t *options, + libra_d3d11_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Draw a frame with the given parameters for the given filter chain. /// -/// If `device_context` is null, then commands are recorded onto the immediate context. Otherwise, -/// it will record commands onto the provided context. If the context is deferred, librashader -/// will not finalize command lists. The context must otherwise be associated with the `ID3D11Device` +/// If `device_context` is null, then commands are recorded onto the immediate +/// context. Otherwise, it will record commands onto the provided context. If +/// the context is deferred, librashader will not finalize command lists. The +/// context must otherwise be associated with the `ID3D11Device` /// /// ## Safety -/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this +/// - `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` +/// - `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_d3d11_opt_t` +/// - `opt` may be null, or if it is not null, must be an aligned pointer to a +/// valid `frame_d3d11_opt_t` /// struct. /// - `out` must not be null. /// - `image.handle` must not be null. -/// - If `device_context` is null, commands will be recorded onto the immediate context of the `ID3D11Device` -/// this filter chain was created with. The context must otherwise be associated with the `ID3D11Device` -/// the filter chain was created with. -/// - You must ensure that only one thread has access to `chain` before you call this function. Only one +/// - If `device_context` is null, commands will be recorded onto the immediate +/// context of the `ID3D11Device` +/// this filter chain was created with. The context must otherwise be +/// associated with the `ID3D11Device` the filter chain was created with. +/// - You must ensure that only one thread has access to `chain` before you call +/// this function. Only one /// thread at a time may call this function. -libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain, - ID3D11DeviceContext * device_context, - size_t frame_count, - struct libra_source_image_d3d11_t image, - struct libra_viewport_t viewport, - ID3D11RenderTargetView * out, - const float *mvp, - const struct frame_d3d11_opt_t *options); +libra_error_t libra_d3d11_filter_chain_frame( + libra_d3d11_filter_chain_t *chain, ID3D11DeviceContext *device_context, + size_t frame_count, struct libra_source_image_d3d11_t image, + struct libra_viewport_t viewport, ID3D11RenderTargetView *out, + const float *mvp, const struct frame_d3d11_opt_t *options); #endif #if defined(LIBRA_RUNTIME_D3D11) @@ -1177,11 +1328,11 @@ libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain, /// /// If the parameter does not exist, returns an error. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d11_filter_chain_t`. /// - `param_name` must be either null or a null terminated string. -libra_error_t libra_d3d11_filter_chain_set_param(libra_d3d11_filter_chain_t *chain, - const char *param_name, - float value); +libra_error_t libra_d3d11_filter_chain_set_param( + libra_d3d11_filter_chain_t *chain, const char *param_name, float value); #endif #if defined(LIBRA_RUNTIME_D3D11) @@ -1189,29 +1340,31 @@ libra_error_t libra_d3d11_filter_chain_set_param(libra_d3d11_filter_chain_t *cha /// /// If the parameter does not exist, returns an error. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d11_filter_chain_t`. /// - `param_name` must be either null or a null terminated string. -libra_error_t libra_d3d11_filter_chain_get_param(libra_d3d11_filter_chain_t *chain, - const char *param_name, - float *out); +libra_error_t libra_d3d11_filter_chain_get_param( + libra_d3d11_filter_chain_t *chain, const char *param_name, float *out); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Sets the number of active passes for this chain. /// /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. -libra_error_t libra_d3d11_filter_chain_set_active_pass_count(libra_d3d11_filter_chain_t *chain, - uint32_t value); +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d11_filter_chain_t`. +libra_error_t libra_d3d11_filter_chain_set_active_pass_count( + libra_d3d11_filter_chain_t *chain, uint32_t value); #endif #if defined(LIBRA_RUNTIME_D3D11) /// Gets the number of active passes for this chain. /// /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. -libra_error_t libra_d3d11_filter_chain_get_active_pass_count(libra_d3d11_filter_chain_t *chain, - uint32_t *out); +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d11_filter_chain_t`. +libra_error_t libra_d3d11_filter_chain_get_active_pass_count( + libra_d3d11_filter_chain_t *chain, uint32_t *out); #endif #if defined(LIBRA_RUNTIME_D3D11) @@ -1219,7 +1372,8 @@ libra_error_t libra_d3d11_filter_chain_get_active_pass_count(libra_d3d11_filter_ /// /// The resulting value in `chain` then becomes null. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d11_filter_chain_t`. libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain); #endif @@ -1234,15 +1388,16 @@ libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain); /// - `options` must be either null, or valid and aligned. /// - `device` must not be null. /// - `out` must be aligned, but may be null, invalid, or uninitialized. -libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset, - ID3D12Device * device, - const struct filter_chain_d3d12_opt_t *options, - libra_d3d12_filter_chain_t *out); +libra_error_t libra_d3d12_filter_chain_create( + libra_shader_preset_t *preset, ID3D12Device *device, + const struct filter_chain_d3d12_opt_t *options, + libra_d3d12_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_D3D12) -/// Create the filter chain given the shader preset deferring and GPU-side initialization -/// to the caller. This function therefore requires no external synchronization of the device queue. +/// Create the filter chain given the shader preset deferring and GPU-side +/// initialization to the caller. This function therefore requires no external +/// synchronization of the device queue. /// /// The shader preset is immediately invalidated and must be recreated after /// the filter chain is created. @@ -1254,48 +1409,55 @@ libra_error_t libra_d3d12_filter_chain_create(libra_shader_preset_t *preset, /// - `out` must be aligned, but may be null, invalid, or uninitialized. /// - `cmd` must not be null. /// -/// The provided command list must be ready for recording and contain no prior commands. -/// The caller is responsible for ending the command list and immediately submitting it to a -/// graphics queue. The command list must be completely executed before calling `libra_d3d12_filter_chain_frame`. -libra_error_t libra_d3d12_filter_chain_create_deferred(libra_shader_preset_t *preset, - ID3D12Device * device, - ID3D12GraphicsCommandList * command_list, - const struct filter_chain_d3d12_opt_t *options, - libra_d3d12_filter_chain_t *out); +/// The provided command list must be ready for recording and contain no prior +/// commands. The caller is responsible for ending the command list and +/// immediately submitting it to a graphics queue. The command list must be +/// completely executed before calling `libra_d3d12_filter_chain_frame`. +libra_error_t libra_d3d12_filter_chain_create_deferred( + libra_shader_preset_t *preset, ID3D12Device *device, + ID3D12GraphicsCommandList *command_list, + const struct filter_chain_d3d12_opt_t *options, + libra_d3d12_filter_chain_t *out); #endif #if defined(LIBRA_RUNTIME_D3D12) -/// Records rendering commands for a frame with the given parameters for the given filter chain -/// to the input command list. +/// Records rendering commands for a frame with the given parameters for the +/// given filter chain to the input command list. /// -/// * The input image must be in the `D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE` resource state. -/// * The output image must be in `D3D12_RESOURCE_STATE_RENDER_TARGET` resource state. +/// * The input image must be in the +/// `D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE` resource state. +/// * The output image must be in `D3D12_RESOURCE_STATE_RENDER_TARGET` resource +/// state. /// -/// librashader **will not** create a resource barrier for the final pass. The output image will -/// remain in `D3D12_RESOURCE_STATE_RENDER_TARGET` after all shader passes. The caller must transition -/// the output image to the final resource state. +/// librashader **will not** create a resource barrier for the final pass. The +/// output image will remain in `D3D12_RESOURCE_STATE_RENDER_TARGET` after all +/// shader passes. The caller must transition the output image to the final +/// resource state. /// /// ## Safety -/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this +/// - `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` +/// - `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_d3d12_opt_t` +/// - `opt` may be null, or if it is not null, must be an aligned pointer to a +/// valid `frame_d3d12_opt_t` /// struct. /// - `out` must be a descriptor handle to a render target view. /// - `image.resource` must not be null. -/// - `command_list` must be a non-null pointer to a `ID3D12GraphicsCommandList` that is open, -/// and must be associated with the `ID3D12Device` this filter chain was created with. -/// - You must ensure that only one thread has access to `chain` before you call this function. Only one +/// - `command_list` must be a non-null pointer to a `ID3D12GraphicsCommandList` +/// that is open, +/// and must be associated with the `ID3D12Device` this filter chain was +/// created with. +/// - You must ensure that only one thread has access to `chain` before you call +/// this function. Only one /// thread at a time may call this function. -libra_error_t libra_d3d12_filter_chain_frame(libra_d3d12_filter_chain_t *chain, - ID3D12GraphicsCommandList * command_list, - size_t frame_count, - struct libra_source_image_d3d12_t image, - struct libra_viewport_t viewport, - struct libra_output_image_d3d12_t out, - const float *mvp, - const struct frame_d3d12_opt_t *options); +libra_error_t libra_d3d12_filter_chain_frame( + libra_d3d12_filter_chain_t *chain, ID3D12GraphicsCommandList *command_list, + size_t frame_count, struct libra_source_image_d3d12_t image, + struct libra_viewport_t viewport, struct libra_output_image_d3d12_t out, + const float *mvp, const struct frame_d3d12_opt_t *options); #endif #if defined(LIBRA_RUNTIME_D3D12) @@ -1303,11 +1465,11 @@ libra_error_t libra_d3d12_filter_chain_frame(libra_d3d12_filter_chain_t *chain, /// /// If the parameter does not exist, returns an error. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d12_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d12_filter_chain_t`. /// - `param_name` must be either null or a null terminated string. -libra_error_t libra_d3d12_filter_chain_set_param(libra_d3d12_filter_chain_t *chain, - const char *param_name, - float value); +libra_error_t libra_d3d12_filter_chain_set_param( + libra_d3d12_filter_chain_t *chain, const char *param_name, float value); #endif #if defined(LIBRA_RUNTIME_D3D12) @@ -1315,29 +1477,31 @@ libra_error_t libra_d3d12_filter_chain_set_param(libra_d3d12_filter_chain_t *cha /// /// If the parameter does not exist, returns an error. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d12_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d12_filter_chain_t`. /// - `param_name` must be either null or a null terminated string. -libra_error_t libra_d3d12_filter_chain_get_param(libra_d3d12_filter_chain_t *chain, - const char *param_name, - float *out); +libra_error_t libra_d3d12_filter_chain_get_param( + libra_d3d12_filter_chain_t *chain, const char *param_name, float *out); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Sets the number of active passes for this chain. /// /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d12_filter_chain_t`. -libra_error_t libra_d3d12_filter_chain_set_active_pass_count(libra_d3d12_filter_chain_t *chain, - uint32_t value); +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d12_filter_chain_t`. +libra_error_t libra_d3d12_filter_chain_set_active_pass_count( + libra_d3d12_filter_chain_t *chain, uint32_t value); #endif #if defined(LIBRA_RUNTIME_D3D12) /// Gets the number of active passes for this chain. /// /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d12_filter_chain_t`. -libra_error_t libra_d3d12_filter_chain_get_active_pass_count(libra_d3d12_filter_chain_t *chain, - uint32_t *out); +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d12_filter_chain_t`. +libra_error_t libra_d3d12_filter_chain_get_active_pass_count( + libra_d3d12_filter_chain_t *chain, uint32_t *out); #endif #if defined(LIBRA_RUNTIME_D3D12) @@ -1345,7 +1509,8 @@ libra_error_t libra_d3d12_filter_chain_get_active_pass_count(libra_d3d12_filter_ /// /// The resulting value in `chain` then becomes null. /// ## Safety -/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d12_filter_chain_t`. +/// - `chain` must be either null or a valid and aligned pointer to an +/// initialized `libra_d3d12_filter_chain_t`. libra_error_t libra_d3d12_filter_chain_free(libra_d3d12_filter_chain_t *chain); #endif @@ -1355,8 +1520,156 @@ LIBRASHADER_ABI_VERSION libra_instance_abi_version(void); /// Get the API version of the loaded instance. LIBRASHADER_API_VERSION libra_instance_api_version(void); +/// Create a wildcard context +/// +/// The C API does not allow directly setting certain variables +/// +/// - `PRESET_DIR` and `PRESET` are inferred on preset creation. +/// - `VID-DRV-SHADER-EXT` and `VID-DRV-PRESET-EXT` are always set to `slang` +/// and `slangp` for librashader. +/// - `VID-FINAL-ROT` is automatically calculated as the sum of `VID-USER-ROT` +/// and `CORE-REQ-ROT` if either are present. +/// +/// These automatically inferred variables, as well as all other variables can +/// be overridden with `libra_preset_ctx_set_param`, but the expected string +/// values must be provided. See +/// https://github.com/libretro/RetroArch/pull/15023 for a list of expected +/// string values. +/// +/// No variables can be removed once added to the context, however subsequent +/// calls to set the same variable will overwrite the expected variable. +/// ## Safety +/// - `out` must be either null, or an aligned pointer to an uninitialized or +/// invalid `libra_preset_ctx_t`. +/// ## Returns +/// - If any parameters are null, `out` is unchanged, and this function returns +/// `LIBRA_ERR_INVALID_PARAMETER`. +libra_error_t libra_preset_ctx_create(libra_preset_ctx_t *out); + +/// Free the wildcard context. +/// +/// If `context` is null, this function does nothing. The resulting value in +/// `context` then becomes null. +/// +/// ## Safety +/// - `context` must be a valid and aligned pointer to a `libra_preset_ctx_t` +libra_error_t libra_preset_ctx_free(libra_preset_ctx_t *context); + +/// Set the core name (`CORE`) variable in the context +/// +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +/// - `name` must be null or a valid and aligned pointer to a string. +libra_error_t libra_preset_ctx_set_core_name(libra_preset_ctx_t *context, + const char *name); + +/// Set the content directory (`CONTENT-DIR`) variable in the context. +/// +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +/// - `name` must be null or a valid and aligned pointer to a string. +libra_error_t libra_preset_ctx_set_content_dir(libra_preset_ctx_t *context, + const char *name); + +/// Set a custom string variable in context. +/// +/// If the path contains this variable when loading a preset, it will be +/// replaced with the provided contents. +/// +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +/// - `name` must be null or a valid and aligned pointer to a string. +/// - `value` must be null or a valid and aligned pointer to a string. +libra_error_t libra_preset_ctx_set_param(libra_preset_ctx_t *context, + const char *name, const char *value); + +/// Set the graphics runtime (`VID-DRV`) variable in the context. +/// +/// Note that librashader only supports the following runtimes. +/// +/// - Vulkan +/// - GLCore +/// - Direct3D11 +/// - Direct3D12 +/// +/// This will also set the appropriate video driver extensions. +/// +/// For librashader, `VID-DRV-SHADER-EXT` and `VID-DRV-PRESET-EXT` are always +/// `slang` and `slangp`. To override this, use `libra_preset_ctx_set_param`. +/// +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +/// - `name` must be null or a valid and aligned pointer to a string. +libra_error_t libra_preset_ctx_set_runtime(libra_preset_ctx_t *context, + LIBRA_PRESET_CTX_RUNTIME value); + +/// Set the core requested rotation (`CORE-REQ-ROT`) variable in the context. +/// +/// Rotation is represented by quarter rotations around the unit circle. +/// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = +/// 0deg. +/// +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +libra_error_t libra_preset_ctx_set_core_rotation(libra_preset_ctx_t *context, + uint32_t value); + +/// Set the user rotation (`VID-USER-ROT`) variable in the context. +/// +/// Rotation is represented by quarter rotations around the unit circle. +/// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = +/// 0deg. +/// +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +libra_error_t libra_preset_ctx_set_user_rotation(libra_preset_ctx_t *context, + uint32_t value); + +/// Set the screen orientation (`SCREEN-ORIENT`) variable in the context. +/// +/// Orientation is represented by quarter rotations around the unit circle. +/// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = +/// 0deg. +/// +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +libra_error_t libra_preset_ctx_set_screen_orientation( + libra_preset_ctx_t *context, uint32_t value); + +/// Set whether or not to allow rotation (`VID-ALLOW-CORE-ROT`) variable in the +/// context. +/// +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +libra_error_t libra_preset_ctx_set_allow_rotation(libra_preset_ctx_t *context, + bool value); + +/// Set the view aspect orientation (`VIEW-ASPECT-ORIENT`) variable in the +/// context. +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +libra_error_t libra_preset_ctx_set_view_aspect_orientation( + libra_preset_ctx_t *context, LIBRA_PRESET_CTX_ORIENTATION value); + +/// Set the core aspect orientation (`CORE-ASPECT-ORIENT`) variable in the +/// context. +/// ## Safety +/// - `context` must be null or a valid and aligned pointer to a +/// `libra_preset_ctx_t`. +libra_error_t libra_preset_ctx_set_core_aspect_orientation( + libra_preset_ctx_t *context, LIBRA_PRESET_CTX_ORIENTATION value); + #ifdef __cplusplus -} // extern "C" -#endif // __cplusplus +} // extern "C" +#endif // __cplusplus #endif /* __LIBRASHADER_H__ */ diff --git a/include/librashader_ld.h b/include/librashader_ld.h index c5936ec..87180f2 100644 --- a/include/librashader_ld.h +++ b/include/librashader_ld.h @@ -28,7 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #pragma once // Uncomment the following defines to activate runtimes. - + // #define LIBRA_RUNTIME_OPENGL // #define LIBRA_RUNTIME_VULKAN @@ -39,7 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #if defined(_WIN32) #include -#define _LIBRASHADER_ASSIGN(HMOD, INSTANCE, NAME) \ +#define _LIBRASHADER_ASSIGN(HMOD, INSTANCE, NAME) \ { \ FARPROC address = GetProcAddress(HMOD, "libra_" #NAME); \ if (address != NULL) { \ @@ -57,9 +57,9 @@ typedef HMODULE _LIBRASHADER_IMPL_HANDLE; (INSTANCE).NAME = (PFN_libra_##NAME)address; \ } \ } -typedef void* _LIBRASHADER_IMPL_HANDLE; +typedef void *_LIBRASHADER_IMPL_HANDLE; #define _LIBRASHADER_LOAD dlopen("librashader.dylib", RTLD_LAZY) -#elif defined(__unix__) || defined (__linux__) +#elif defined(__unix__) || defined(__linux__) #include #define _LIBRASHADER_ASSIGN(HMOD, INSTANCE, NAME) \ { \ @@ -68,7 +68,7 @@ typedef void* _LIBRASHADER_IMPL_HANDLE; (INSTANCE).NAME = (PFN_libra_##NAME)address; \ } \ } -typedef void* _LIBRASHADER_IMPL_HANDLE; +typedef void *_LIBRASHADER_IMPL_HANDLE; #define _LIBRASHADER_LOAD dlopen("librashader.so", RTLD_LAZY) #endif @@ -92,6 +92,72 @@ int32_t __librashader__noop_error_write(libra_error_t error, char **out) { int32_t __librashader__noop_error_free_string(char **out) { return 1; } +libra_error_t __librashader__noop_preset_ctx_create(libra_preset_ctx_t *out) { + *out = NULL; + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_free(libra_preset_ctx_t *context) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_core_name( + libra_preset_ctx_t *context, const char *name) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_content_dir( + libra_preset_ctx_t *context, const char *name) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_param( + libra_preset_ctx_t *context, const char *name, const char *value) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_runtime( + libra_preset_ctx_t *context, LIBRA_PRESET_CTX_RUNTIME value) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_core_rotation( + libra_preset_ctx_t *context, uint32_t value) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_user_rotation( + libra_preset_ctx_t *context, uint32_t value) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_screen_orientation( + libra_preset_ctx_t *context, uint32_t value) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_allow_rotation( + libra_preset_ctx_t *context, bool value) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_view_aspect_orientation( + libra_preset_ctx_t *context, LIBRA_PRESET_CTX_ORIENTATION value) { + return NULL; +} + +libra_error_t __librashader__noop_preset_ctx_set_core_aspect_orientation( + libra_preset_ctx_t *context, LIBRA_PRESET_CTX_ORIENTATION value) { + return NULL; +} + +libra_error_t __librashader__noop_preset_create_with_context( + const char *filename, libra_preset_ctx_t *context, + libra_shader_preset_t *out) { + *out = NULL; + return NULL; +} + libra_error_t __librashader__noop_preset_create(const char *filename, libra_shader_preset_t *out) { *out = NULL; @@ -119,7 +185,8 @@ 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) { +libra_error_t __librashader__noop_preset_free_runtime_params( + struct libra_preset_param_list_t out) { return NULL; } #if defined(LIBRA_RUNTIME_OPENGL) @@ -228,7 +295,8 @@ libra_error_t __librashader__noop_d3d11_filter_chain_create( } libra_error_t __librashader__noop_d3d11_filter_chain_create_deferred( - libra_shader_preset_t *preset, ID3D11Device *device, ID3D11DeviceContext *device_context, + libra_shader_preset_t *preset, ID3D11Device *device, + ID3D11DeviceContext *device_context, const struct filter_chain_d3d11_opt_t *options, libra_d3d11_filter_chain_t *out) { *out = NULL; @@ -236,11 +304,10 @@ libra_error_t __librashader__noop_d3d11_filter_chain_create_deferred( } libra_error_t __librashader__noop_d3d11_filter_chain_frame( - libra_d3d11_filter_chain_t *chain, - ID3D11DeviceContext *device_context, size_t frame_count, - struct libra_source_image_d3d11_t image, struct libra_viewport_t viewport, - ID3D11RenderTargetView *out, const float *mvp, - const struct frame_d3d11_opt_t *opt) { + libra_d3d11_filter_chain_t *chain, ID3D11DeviceContext *device_context, + size_t frame_count, struct libra_source_image_d3d11_t image, + struct libra_viewport_t viewport, ID3D11RenderTargetView *out, + const float *mvp, const struct frame_d3d11_opt_t *opt) { return NULL; } @@ -270,7 +337,6 @@ libra_error_t __librashader__noop_d3d11_filter_chain_get_active_pass_count( } #endif - #if defined(LIBRA_RUNTIME_D3D12) libra_error_t __librashader__noop_d3d12_filter_chain_create( libra_shader_preset_t *preset, ID3D12Device *device, @@ -290,11 +356,10 @@ libra_error_t __librashader__noop_d3d12_filter_chain_create_deferred( } libra_error_t __librashader__noop_d3d12_filter_chain_frame( - libra_d3d12_filter_chain_t *chain, - ID3D12GraphicsCommandList *command_list, size_t frame_count, - struct libra_source_image_d3d12_t image, struct libra_viewport_t viewport, - struct libra_output_image_d3d12_t out, const float *mvp, - const struct frame_d3d12_opt_t *opt) { + libra_d3d12_filter_chain_t *chain, ID3D12GraphicsCommandList *command_list, + size_t frame_count, struct libra_source_image_d3d12_t image, + struct libra_viewport_t viewport, struct libra_output_image_d3d12_t out, + const float *mvp, const struct frame_d3d12_opt_t *opt) { return NULL; } @@ -335,6 +400,151 @@ typedef struct libra_instance_t { /// The null instance has API version 0. PFN_libra_instance_api_version instance_api_version; + /// Create a wildcard context + /// + /// The C API does not allow directly setting certain variables + /// + /// - `PRESET_DIR` and `PRESET` are inferred on preset creation. + /// - `VID-DRV-SHADER-EXT` and `VID-DRV-PRESET-EXT` are always set to + /// `slang` and `slangp` for librashader. + /// - `VID-FINAL-ROT` is automatically calculated as the sum of + /// `VID-USER-ROT` and `CORE-REQ-ROT` if either are present. + /// + /// These automatically inferred variables, as well as all other variables + /// can be overridden with `libra_preset_ctx_set_param`, but the expected + /// string values must be provided. See + /// https://github.com/libretro/RetroArch/pull/15023 for a list of expected + /// string values. + /// + /// No variables can be removed once added to the context, however + /// subsequent calls to set the same variable will overwrite the expected + /// variable. + /// ## Safety + /// - `out` must be either null, or an aligned pointer to an uninitialized + /// or invalid `libra_preset_ctx_t`. + /// ## Returns + /// - If any parameters are null, `out` is unchanged, and this function + /// returns `LIBRA_ERR_INVALID_PARAMETER`. + PFN_libra_preset_ctx_create preset_ctx_create; + + /// Free the wildcard context. + /// + /// If `context` is null, this function does nothing. The resulting value in + /// `context` then becomes null. + /// + /// ## Safety + /// - `context` must be a valid and aligned pointer to a + /// `libra_preset_ctx_t` + PFN_libra_preset_ctx_free preset_ctx_free; + + /// Set the core name (`CORE`) variable in the context + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + /// - `name` must be null or a valid and aligned pointer to a string. + PFN_libra_preset_ctx_set_core_name preset_ctx_set_core_name; + + /// Set the content directory (`CONTENT-DIR`) variable in the context. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + /// - `name` must be null or a valid and aligned pointer to a string. + PFN_libra_preset_ctx_set_content_dir preset_ctx_set_content_dir; + + /// Set a custom string variable in context. + /// + /// If the path contains this variable when loading a preset, it will be + /// replaced with the provided contents. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + /// - `name` must be null or a valid and aligned pointer to a string. + /// - `value` must be null or a valid and aligned pointer to a string. + PFN_libra_preset_ctx_set_param preset_ctx_set_param; + + /// Set the graphics runtime (`VID-DRV`) variable in the context. + /// + /// Note that librashader only supports the following runtimes. + /// + /// - Vulkan + /// - GLCore + /// - Direct3D11 + /// - Direct3D12 + /// + /// This will also set the appropriate video driver extensions. + /// + /// For librashader, `VID-DRV-SHADER-EXT` and `VID-DRV-PRESET-EXT` are + /// always `slang` and `slangp`. To override this, use + /// `libra_preset_ctx_set_param`. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + /// - `name` must be null or a valid and aligned pointer to a string. + PFN_libra_preset_ctx_set_runtime preset_ctx_set_runtime; + + /// Set the core requested rotation (`CORE-REQ-ROT`) variable in the + /// context. + /// + /// Rotation is represented by quarter rotations around the unit circle. + /// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = + /// 0deg. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + PFN_libra_preset_ctx_set_core_rotation preset_ctx_set_core_rotation; + + /// Set the user rotation (`VID-USER-ROT`) variable in the context. + /// + /// Rotation is represented by quarter rotations around the unit circle. + /// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = + /// 0deg. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + PFN_libra_preset_ctx_set_user_rotation preset_ctx_set_user_rotation; + + /// Set the screen orientation (`SCREEN-ORIENT`) variable in the context. + /// + /// Orientation is represented by quarter rotations around the unit circle. + /// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = + /// 0deg. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + PFN_libra_preset_ctx_set_screen_orientation + preset_ctx_set_screen_orientation; + + /// Set whether or not to allow rotation (`VID-ALLOW-CORE-ROT`) variable in + /// the context. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + PFN_libra_preset_ctx_set_allow_rotation preset_ctx_set_allow_rotation; + + /// Set the view aspect orientation (`VIEW-ASPECT-ORIENT`) variable in the + /// context. + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + PFN_libra_preset_ctx_set_view_aspect_orientation + preset_ctx_set_view_aspect_orientation; + + /// Set the core aspect orientation (`CORE-ASPECT-ORIENT`) variable in the + /// context. + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a + /// `libra_preset_ctx_t`. + PFN_libra_preset_ctx_set_core_aspect_orientation + preset_ctx_set_core_aspect_orientation; + /// Load a preset. /// /// If this function is not loaded, `out` will unconditionally be set to @@ -351,6 +561,26 @@ typedef struct libra_instance_t { /// returns `LIBRA_ERR_INVALID_PARAMETER`. PFN_libra_preset_create preset_create; + /// Load a preset with the given wildcard context. + /// + /// The wildcard context is immediately invalidated and must be recreated + /// after the preset is created. + /// + /// Path information variables `PRESET_DIR` and `PRESET` will automatically + /// be filled in. + /// ## Safety + /// - `filename` must be either null or a valid, aligned pointer to a + /// string path to the shader preset. + /// - `context` must be either null or a valid, aligned pointer to a + /// initialized `libra_preset_ctx_t`. + /// - `context` is invalidated after this function returns. + /// - `out` must be either null, or an aligned pointer to an uninitialized + /// or invalid `libra_shader_preset_t`. + /// ## Returns + /// - If any parameters are null, `out` is unchanged, and this function + /// returns `LIBRA_ERR_INVALID_PARAMETER`. + PFN_libra_preset_create_with_context preset_create_with_context; + /// Free the preset. /// /// If `preset` is null, this function does nothing. The resulting value in @@ -425,7 +655,6 @@ typedef struct libra_instance_t { /// result in undefined behaviour. PFN_libra_preset_free_runtime_params preset_free_runtime_params; - /// Get the error code corresponding to this error object. /// /// ## Safety @@ -473,7 +702,8 @@ typedef struct libra_instance_t { /// Initialize the OpenGL Context for librashader. /// /// ## Safety - /// Attempting to create a filter chain will fail if the context is not initialized. + /// Attempting to create a filter chain will fail if the context is not + /// initialized. /// /// Reinitializing the OpenGL context with a different loader immediately /// invalidates previous filter chain objects, and drawing with them causes @@ -717,7 +947,8 @@ typedef struct libra_instance_t { /// /// If the context is immediate, then access to the immediate context /// requires external synchronization. - PFN_libra_d3d11_filter_chain_create_deferred d3d11_filter_chain_create_deferred; + PFN_libra_d3d11_filter_chain_create_deferred + d3d11_filter_chain_create_deferred; /// Draw a frame with the given parameters for the given filter chain. /// @@ -776,7 +1007,6 @@ typedef struct libra_instance_t { PFN_libra_d3d11_filter_chain_set_param d3d11_filter_chain_set_param; #endif - #if defined(LIBRA_RUNTIME_D3D12) /// Create the filter chain given the shader preset. /// @@ -801,8 +1031,9 @@ typedef struct libra_instance_t { /// The shader preset is immediately invalidated and must be recreated after /// the filter chain is created. /// - /// If this function is not loaded, `out` will unconditionally be set to null. - /// If this function returns an error, the state of `out` is unspecified. + /// If this function is not loaded, `out` will unconditionally be set to + /// null. If this function returns an error, the state of `out` is + /// unspecified. /// /// ## Safety: /// - `preset` must be either null, or valid and aligned. @@ -815,7 +1046,8 @@ typedef struct libra_instance_t { /// prior commands. The caller is responsible for ending the command list /// and immediately submitting it to a graphics queue. The command list must /// be completely executed before calling `libra_d3d12_filter_chain_frame` - PFN_libra_d3d12_filter_chain_create_deferred d3d12_filter_chain_create_deferred; + PFN_libra_d3d12_filter_chain_create_deferred + d3d12_filter_chain_create_deferred; /// Draw a frame with the given parameters for the given filter chain. /// @@ -881,7 +1113,8 @@ typedef struct libra_instance_t { /// was created with librashader_load_instance if and only if: /// /// 1. A librashader library was found in the search path. - /// 2. The ABI version of the librashader library in the search path is compatible. + /// 2. The ABI version of the librashader library in the search path is + /// compatible. /// /// This flag can only be relied upon when checked immediately after /// librashader_load_instance as there is no protection against mutating @@ -894,14 +1127,35 @@ typedef struct libra_instance_t { bool instance_loaded; } 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_ctx_create = __librashader__noop_preset_ctx_create, + .preset_ctx_free = __librashader__noop_preset_ctx_free, + .preset_ctx_set_core_name = + __librashader__noop_preset_ctx_set_core_name, + .preset_ctx_set_content_dir = + __librashader__noop_preset_ctx_set_content_dir, + .preset_ctx_set_param = __librashader__noop_preset_ctx_set_param, + .preset_ctx_set_runtime = __librashader__noop_preset_ctx_set_runtime, + .preset_ctx_set_core_rotation = + __librashader__noop_preset_ctx_set_core_rotation, + .preset_ctx_set_user_rotation = + __librashader__noop_preset_ctx_set_user_rotation, + .preset_ctx_set_screen_orientation = + __librashader__noop_preset_ctx_set_screen_orientation, + .preset_ctx_set_allow_rotation = + __librashader__noop_preset_ctx_set_allow_rotation, + .preset_ctx_set_view_aspect_orientation = + __librashader__noop_preset_ctx_set_view_aspect_orientation, + .preset_ctx_set_core_aspect_orientation = + __librashader__noop_preset_ctx_set_core_aspect_orientation, + .preset_create = __librashader__noop_preset_create, + .preset_create_with_context = + __librashader__noop_preset_create_with_context, .preset_free = __librashader__noop_preset_free, .preset_set_param = __librashader__noop_preset_set_param, .preset_get_param = __librashader__noop_preset_get_param, @@ -934,7 +1188,8 @@ libra_instance_t __librashader_make_null_instance() { #if defined(LIBRA_RUNTIME_VULKAN) .vk_filter_chain_create = __librashader__noop_vk_filter_chain_create, - .vk_filter_chain_create_deferred = __librashader__noop_vk_filter_chain_create_deferred, + .vk_filter_chain_create_deferred = + __librashader__noop_vk_filter_chain_create_deferred, .vk_filter_chain_frame = __librashader__noop_vk_filter_chain_frame, .vk_filter_chain_free = __librashader__noop_vk_filter_chain_free, .vk_filter_chain_get_active_pass_count = @@ -1000,7 +1255,8 @@ 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) || defined(__linux__) || defined(__unix__) || defined(__APPLE__) +#if defined(_WIN32) || defined(__linux__) || defined(__unix__) || \ + defined(__APPLE__) libra_instance_t librashader_load_instance() { _LIBRASHADER_IMPL_HANDLE librashader = _LIBRASHADER_LOAD; libra_instance_t instance = __librashader_make_null_instance(); @@ -1016,15 +1272,31 @@ libra_instance_t librashader_load_instance() { return instance; } + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_create); + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_free); + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_set_core_name); + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_set_content_dir); + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_set_param); + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_set_runtime); + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_set_core_rotation); + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_set_user_rotation); + _LIBRASHADER_ASSIGN(librashader, instance, + preset_ctx_set_screen_orientation); + _LIBRASHADER_ASSIGN(librashader, instance, preset_ctx_set_allow_rotation); + _LIBRASHADER_ASSIGN(librashader, instance, + preset_ctx_set_view_aspect_orientation); + _LIBRASHADER_ASSIGN(librashader, instance, + preset_ctx_set_core_aspect_orientation); + _LIBRASHADER_ASSIGN(librashader, instance, preset_create); + _LIBRASHADER_ASSIGN(librashader, instance, preset_create_with_context); + _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(librashader, instance, preset_get_runtime_params); + _LIBRASHADER_ASSIGN(librashader, instance, preset_free_runtime_params); _LIBRASHADER_ASSIGN(librashader, instance, error_errno); _LIBRASHADER_ASSIGN(librashader, instance, error_print); @@ -1037,14 +1309,12 @@ libra_instance_t librashader_load_instance() { _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(librashader, instance, gl_filter_chain_set_param); _LIBRASHADER_ASSIGN(librashader, instance, - gl_filter_chain_get_param); + gl_filter_chain_get_active_pass_count); _LIBRASHADER_ASSIGN(librashader, instance, - gl_filter_chain_set_param); - _LIBRASHADER_ASSIGN(librashader, instance, - gl_filter_chain_get_active_pass_count); - _LIBRASHADER_ASSIGN(librashader, instance, - gl_filter_chain_set_active_pass_count); + gl_filter_chain_set_active_pass_count); #endif @@ -1053,19 +1323,18 @@ libra_instance_t librashader_load_instance() { _LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_create_deferred); _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(librashader, instance, vk_filter_chain_set_param); _LIBRASHADER_ASSIGN(librashader, instance, - vk_filter_chain_get_param); + vk_filter_chain_get_active_pass_count); _LIBRASHADER_ASSIGN(librashader, instance, - vk_filter_chain_set_param); - _LIBRASHADER_ASSIGN(librashader, instance, - vk_filter_chain_get_active_pass_count); - _LIBRASHADER_ASSIGN(librashader, instance, - vk_filter_chain_set_active_pass_count); + vk_filter_chain_set_active_pass_count); #endif #if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D11) _LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_create); - _LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_create_deferred); + _LIBRASHADER_ASSIGN(librashader, instance, + d3d11_filter_chain_create_deferred); _LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_frame); _LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_free); _LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_get_param); @@ -1078,7 +1347,8 @@ libra_instance_t librashader_load_instance() { #if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D12) _LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_create); - _LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_create_deferred); + _LIBRASHADER_ASSIGN(librashader, instance, + d3d12_filter_chain_create_deferred); _LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_frame); _LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_free); _LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_get_param); diff --git a/librashader-build-script/Cargo.toml b/librashader-build-script/Cargo.toml index da511e6..2b84e2c 100644 --- a/librashader-build-script/Cargo.toml +++ b/librashader-build-script/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] cbindgen = "0.26.0" -clap = { version = "4.1.0", features = ["derive"] } +clap = { version = "=4.1.0", features = ["derive"] } [package.metadata.release] diff --git a/librashader-build-script/src/main.rs b/librashader-build-script/src/main.rs index 9965d58..2cb2b85 100644 --- a/librashader-build-script/src/main.rs +++ b/librashader-build-script/src/main.rs @@ -73,8 +73,7 @@ pub fn main() { let ext = ext.replace("_capi", ""); fs::rename(output_dir.join(artifact), output_dir.join(ext)).unwrap(); } - } - else if cfg!(target_family = "unix") { + } else if cfg!(target_family = "unix") { let artifacts = &["liblibrashader_capi.so", "liblibrashader_capi.a"]; for artifact in artifacts { let ext = artifact.strip_prefix("lib").unwrap(); diff --git a/librashader-cache/Cargo.toml b/librashader-cache/Cargo.toml index 3af3293..8eafe6c 100644 --- a/librashader-cache/Cargo.toml +++ b/librashader-cache/Cargo.toml @@ -2,7 +2,7 @@ name = "librashader-cache" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -12,8 +12,8 @@ description = "RetroArch shaders for all." [dependencies] serde = { version = "1.0" } -librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.7", features = ["serialize"] } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } +librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.8", features = ["serialize"] } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } platform-dirs = "0.3.0" blake3 = { version = "1.3.3" } thiserror = "1.0.38" diff --git a/librashader-capi/Cargo.toml b/librashader-capi/Cargo.toml index e6406d1..10c412b 100644 --- a/librashader-capi/Cargo.toml +++ b/librashader-capi/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-capi" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -23,7 +23,7 @@ runtime-d3d12 = ["windows", "librashader/runtime-d3d12", "windows/Win32_Graphics runtime-vulkan = ["ash", "librashader/runtime-vk"] [dependencies] -librashader = { path = "../librashader", version = "0.2.0-beta.7", features = ["internal"] } +librashader = { path = "../librashader", version = "0.2.0-beta.8" } thiserror = "1.0.37" paste = "1.0.9" gl = { version = "0.14.0", optional = true } diff --git a/librashader-capi/cbindgen.toml b/librashader-capi/cbindgen.toml index ef39ebd..d2b6b3d 100644 --- a/librashader-capi/cbindgen.toml +++ b/librashader-capi/cbindgen.toml @@ -68,15 +68,7 @@ typedef void D3D12_CPU_DESCRIPTOR_HANDLE; [parse] parse_deps = true -include = ["librashader", - "librashader-presets", - "librashader-preprocess", - "librashader-reflect", - "librashader-runtime-gl", - "librashader-runtime-vk", - "librashader-runtime-d3d11", - "librashader-runtime-d3d12", -] +include = ["librashader"] expand = ["librashader-capi"] [struct] @@ -99,6 +91,20 @@ include = [ "PFN_libra_preset_print", "PFN_libra_preset_get_runtime_params", "PFN_libra_preset_free_runtime_params", + "PFN_libra_preset_create_with_context", + + "PFN_libra_preset_ctx_create", + "PFN_libra_preset_ctx_free", + "PFN_libra_preset_ctx_set_core_name", + "PFN_libra_preset_ctx_set_content_dir", + "PFN_libra_preset_ctx_set_param", + "PFN_libra_preset_ctx_set_core_rotation", + "PFN_libra_preset_ctx_set_user_rotation", + "PFN_libra_preset_ctx_set_screen_orientation", + "PFN_libra_preset_ctx_set_allow_rotation", + "PFN_libra_preset_ctx_set_view_aspect_orientation", + "PFN_libra_preset_ctx_set_core_aspect_orientation", + "PFN_libra_preset_ctx_set_runtime", # error "PFN_libra_error_errno", @@ -154,6 +160,9 @@ exclude = ["Option_ID3D11DeviceContext"] [export.rename] "LibrashaderError" = "_libra_error" "ShaderPreset" = "_shader_preset" + +"WildcardContext" = "_preset_ctx" + "FilterChainGL" = "_filter_chain_gl" "FilterChainVulkan" = "_filter_chain_vk" "FilterChainD3D11" = "_filter_chain_d3d11" @@ -180,4 +189,4 @@ exclude = ["Option_ID3D11DeviceContext"] # hack to get proper pointer indirection for COM pointers "ID3D12Device" = "ID3D12Device *" "ID3D12Resource" = "ID3D12Resource *" -"ID3D12GraphicsCommandList" = "ID3D12GraphicsCommandList *" \ No newline at end of file +"ID3D12GraphicsCommandList" = "ID3D12GraphicsCommandList *" diff --git a/librashader-capi/src/ctypes.rs b/librashader-capi/src/ctypes.rs index 08351a8..47bd45d 100644 --- a/librashader-capi/src/ctypes.rs +++ b/librashader-capi/src/ctypes.rs @@ -1,5 +1,6 @@ //! Binding types for the librashader C API. use crate::error::LibrashaderError; +use librashader::presets::context::{Orientation, VideoDriver, WildcardContext}; use librashader::presets::ShaderPreset; use std::mem::MaybeUninit; use std::ptr::NonNull; @@ -7,31 +8,86 @@ use std::ptr::NonNull; /// A handle to a shader preset object. pub type libra_shader_preset_t = Option>; +/// A handle to a preset wildcard context object. +pub type libra_preset_ctx_t = Option>; + /// A handle to a librashader error object. pub type libra_error_t = Option>; +/// An enum representing orientation for use in preset contexts. +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum LIBRA_PRESET_CTX_ORIENTATION { + Vertical = 0, + Horizontal, +} +impl From for Orientation { + fn from(value: LIBRA_PRESET_CTX_ORIENTATION) -> Self { + match value { + LIBRA_PRESET_CTX_ORIENTATION::Vertical => Orientation::Vertical, + LIBRA_PRESET_CTX_ORIENTATION::Horizontal => Orientation::Horizontal, + } + } +} + +// An enum representing graphics runtimes (video drivers) for use in preset contexts. +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum LIBRA_PRESET_CTX_RUNTIME { + None = 0, + GlCore, + Vulkan, + D3D11, + D3D12, + Metal, +} + +impl From for VideoDriver { + fn from(value: LIBRA_PRESET_CTX_RUNTIME) -> Self { + match value { + LIBRA_PRESET_CTX_RUNTIME::None => VideoDriver::None, + LIBRA_PRESET_CTX_RUNTIME::GlCore => VideoDriver::GlCore, + LIBRA_PRESET_CTX_RUNTIME::Vulkan => VideoDriver::Vulkan, + LIBRA_PRESET_CTX_RUNTIME::D3D11 => VideoDriver::Direct3D11, + LIBRA_PRESET_CTX_RUNTIME::D3D12 => VideoDriver::Direct3D12, + LIBRA_PRESET_CTX_RUNTIME::Metal => VideoDriver::Metal, + } + } +} + +#[cfg(feature = "runtime-opengl")] +use librashader::runtime::gl::FilterChain as FilterChainGL; + /// A handle to a OpenGL filter chain. #[cfg(feature = "runtime-opengl")] #[doc(cfg(feature = "runtime-opengl"))] -pub type libra_gl_filter_chain_t = Option>; +pub type libra_gl_filter_chain_t = Option>; + +/// A handle to a Direct3D 11 filter chain. +#[cfg(all(target_os = "windows", feature = "runtime-d3d11"))] +use librashader::runtime::d3d11::FilterChain as FilterChainD3D11; /// A handle to a Direct3D 11 filter chain. #[cfg(all(target_os = "windows", feature = "runtime-d3d11"))] #[doc(cfg(all(target_os = "windows", feature = "runtime-d3d11")))] pub type libra_d3d11_filter_chain_t = - Option>; + Option>; +#[cfg(all(target_os = "windows", feature = "runtime-d3d12"))] +use librashader::runtime::d3d12::FilterChain as FilterChainD3D12; /// A handle to a Direct3D 12 filter chain. #[cfg(all(target_os = "windows", feature = "runtime-d3d12"))] #[doc(cfg(all(target_os = "windows", feature = "runtime-d3d12")))] pub type libra_d3d12_filter_chain_t = - Option>; + Option>; +#[cfg(feature = "runtime-vulkan")] +use librashader::runtime::vk::FilterChain as FilterChainVulkan; /// A handle to a Vulkan filter chain. #[cfg(feature = "runtime-vulkan")] #[doc(cfg(feature = "runtime-vulkan"))] pub type libra_vk_filter_chain_t = - Option>; + Option>; /// Defines the output viewport for a rendered frame. #[repr(C)] @@ -87,3 +143,35 @@ macro_rules! config_struct { pub(crate) use config_set_field; pub(crate) use config_struct; pub(crate) use config_version_set; + +#[doc(hidden)] +#[deny(deprecated)] +#[deprecated = "Forward declarations for cbindgen, do not use."] +mod __cbindgen_opaque_forward_declarations { + macro_rules! typedef_struct { + ($($(#[$($attrss:tt)*])* $name:ident;)*) => { + $($(#[$($attrss)*])* + #[allow(unused)] + #[doc(hidden)] + #[deny(deprecated)] + #[deprecated] + pub struct $name; + )* + }; + } + + typedef_struct! { + /// Opaque struct for a preset context. + WildcardContext; + /// Opaque struct for a shader preset. + ShaderPreset; + /// Opaque struct for an OpenGL filter chain. + FilterChainGL; + /// Opaque struct for a Direct3D 11 filter chain. + FilterChainD3D11; + /// Opaque struct for a Direct3D 12 filter chain. + FilterChainD3D12; + /// Opaque struct for a Vulkan filter chain. + FilterChainVulkan; + } +} \ No newline at end of file diff --git a/librashader-capi/src/error.rs b/librashader-capi/src/error.rs index 3ba44f5..9983be4 100644 --- a/librashader-capi/src/error.rs +++ b/librashader-capi/src/error.rs @@ -5,7 +5,7 @@ use std::mem::MaybeUninit; use std::ptr::NonNull; use thiserror::Error; -/// The error type for librashader. +/// The error type for librashader C API. #[non_exhaustive] #[derive(Error, Debug)] pub enum LibrashaderError { diff --git a/librashader-capi/src/lib.rs b/librashader-capi/src/lib.rs index fa6fc89..e01c2d4 100644 --- a/librashader-capi/src/lib.rs +++ b/librashader-capi/src/lib.rs @@ -68,6 +68,7 @@ #![feature(pointer_is_aligned)] #![feature(vec_into_raw_parts)] #![deny(unsafe_op_in_unsafe_fn)] +#![deny(deprecated)] pub mod ctypes; pub mod error; @@ -80,6 +81,7 @@ pub mod reflect; pub mod runtime; pub mod version; +pub mod wildcard; pub use version::LIBRASHADER_ABI_VERSION; pub use version::LIBRASHADER_API_VERSION; diff --git a/librashader-capi/src/presets.rs b/librashader-capi/src/presets.rs index 591c4f7..60cc14f 100644 --- a/librashader-capi/src/presets.rs +++ b/librashader-capi/src/presets.rs @@ -1,5 +1,5 @@ //! librashader preset C API (`libra_preset_*`). -use crate::ctypes::libra_shader_preset_t; +use crate::ctypes::{libra_preset_ctx_t, libra_shader_preset_t}; use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError}; use crate::ffi::extern_fn; use librashader::presets::ShaderPreset; @@ -55,7 +55,6 @@ extern_fn! { let filename = unsafe { CStr::from_ptr(filename) }; let filename = filename.to_str()?; - println!("loading {filename}"); let preset = ShaderPreset::try_parse(filename)?; unsafe { @@ -66,6 +65,49 @@ extern_fn! { } } +extern_fn! { + /// Load a preset with the given wildcard context. + /// + /// The wildcard context is immediately invalidated and must be recreated after + /// the preset is created. + /// + /// Path information variables `PRESET_DIR` and `PRESET` will automatically be filled in. + /// ## Safety + /// - `filename` must be either null or a valid, aligned pointer to a string path to the shader preset. + /// - `context` must be either null or a valid, aligned pointer to a initialized `libra_preset_ctx_t`. + /// - `context` is invalidated after this function returns. + /// - `out` must be either null, or an aligned pointer to an uninitialized or invalid `libra_shader_preset_t`. + /// ## Returns + /// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`. + fn libra_preset_create_with_context( + filename: *const c_char, + context: *mut libra_preset_ctx_t, + out: *mut MaybeUninit + ) { + assert_non_null!(filename); + assert_non_null!(context); + assert_non_null!(out); + + let filename = unsafe { CStr::from_ptr(filename) }; + let filename = filename.to_str()?; + + let mut context = unsafe { + let context_ptr = &mut *context; + let context = context_ptr.take(); + Box::from_raw(context.unwrap().as_ptr()) + }; + + context.add_path_defaults(filename); + + let preset = ShaderPreset::try_parse_with_context(filename, *context)?; + unsafe { + out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( + preset, + ))))) + } + } +} + extern_fn! { /// Free the preset. /// @@ -73,7 +115,7 @@ extern_fn! { /// null. /// /// ## Safety - /// - `preset` must be a valid and aligned pointer to a shader preset. + /// - `preset` must be a valid and aligned pointer to a `libra_shader_preset_t`. fn libra_preset_free(preset: *mut libra_shader_preset_t) { assert_non_null!(preset); unsafe { @@ -88,7 +130,7 @@ extern_fn! { /// Set the value of the parameter in the preset. /// /// ## Safety - /// - `preset` must be null or a valid and aligned pointer to a shader preset. + /// - `preset` must be null or a valid and aligned pointer to a `libra_shader_preset_t`. /// - `name` must be null or a valid and aligned pointer to a string. fn libra_preset_set_param( preset: *mut libra_shader_preset_t, @@ -135,7 +177,7 @@ extern_fn! { /// Pretty print the shader preset. /// /// ## Safety - /// - `preset` must be null or a valid and aligned pointer to a shader preset. + /// - `preset` must be null or a valid and aligned pointer to a `libra_shader_preset_t`. fn libra_preset_print(preset: *mut libra_shader_preset_t) |preset| { assert_some_ptr!(preset); println!("{preset:#?}"); @@ -146,7 +188,7 @@ extern_fn! { /// Get a list of runtime parameters. /// /// ## Safety - /// - `preset` must be null or a valid and aligned pointer to a shader preset. + /// - `preset` must be null or a valid and aligned pointer to a `libra_shader_preset_t`. /// - `out` must be an aligned pointer to a `libra_preset_parameter_list_t`. /// - 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 diff --git a/librashader-capi/src/runtime/d3d11/filter_chain.rs b/librashader-capi/src/runtime/d3d11/filter_chain.rs index b76c92f..128608f 100644 --- a/librashader-capi/src/runtime/d3d11/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d11/filter_chain.rs @@ -3,7 +3,7 @@ use crate::ctypes::{ }; use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError}; use crate::ffi::extern_fn; -use librashader::runtime::d3d11::{D3D11InputView, D3D11OutputView}; +use librashader::runtime::d3d11::{FilterChain, FilterChainOptions, FrameOptions, D3D11InputView, D3D11OutputView}; use std::ffi::c_char; use std::ffi::CStr; use std::mem::{ManuallyDrop, MaybeUninit}; @@ -13,9 +13,6 @@ use windows::Win32::Graphics::Direct3D11::{ ID3D11Device, ID3D11DeviceContext, ID3D11RenderTargetView, ID3D11ShaderResourceView, }; -use librashader::runtime::d3d11::capi::options::FilterChainOptionsD3D11; -use librashader::runtime::d3d11::capi::options::FrameOptionsD3D11; - use crate::LIBRASHADER_API_VERSION; use librashader::runtime::{FilterChainParameters, Size, Viewport}; @@ -58,7 +55,7 @@ pub struct filter_chain_d3d11_opt_t { } config_struct! { - impl FilterChainOptionsD3D11 => filter_chain_d3d11_opt_t { + impl FilterChainOptions => filter_chain_d3d11_opt_t { 0 => [force_no_mipmaps, disable_cache]; } } @@ -77,7 +74,7 @@ pub struct frame_d3d11_opt_t { } config_struct! { - impl FrameOptionsD3D11 => frame_d3d11_opt_t { + impl FrameOptions => frame_d3d11_opt_t { 0 => [clear_history, frame_direction]; } } @@ -114,7 +111,7 @@ extern_fn! { let options = options.map(FromUninit::from_uninit); unsafe { - let chain = librashader::runtime::d3d11::capi::FilterChainD3D11::load_from_preset( + let chain = FilterChain::load_from_preset( *preset, &device, options.as_ref(), @@ -174,7 +171,7 @@ extern_fn! { let options = options.map(FromUninit::from_uninit); unsafe { - let chain = librashader::runtime::d3d11::capi::FilterChainD3D11::load_from_preset_deferred( + let chain = FilterChain::load_from_preset_deferred( *preset, &device, &device_context, diff --git a/librashader-capi/src/runtime/d3d12/filter_chain.rs b/librashader-capi/src/runtime/d3d12/filter_chain.rs index 21cfe10..3b8249a 100644 --- a/librashader-capi/src/runtime/d3d12/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d12/filter_chain.rs @@ -13,11 +13,8 @@ use windows::Win32::Graphics::Direct3D12::{ }; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT; -use librashader::runtime::d3d12::capi::options::FilterChainOptionsD3D12; -use librashader::runtime::d3d12::capi::options::FrameOptionsD3D12; - use crate::LIBRASHADER_API_VERSION; -use librashader::runtime::d3d12::{D3D12InputImage, D3D12OutputView}; +use librashader::runtime::d3d12::{FilterChain, FilterChainOptions, FrameOptions, D3D12InputImage, D3D12OutputView}; use librashader::runtime::{FilterChainParameters, Size, Viewport}; /// Direct3D 12 parameters for the source image. @@ -58,7 +55,7 @@ pub struct frame_d3d12_opt_t { } config_struct! { - impl FrameOptionsD3D12 => frame_d3d12_opt_t { + impl FrameOptions => frame_d3d12_opt_t { 0 => [clear_history, frame_direction]; } } @@ -84,7 +81,7 @@ pub struct filter_chain_d3d12_opt_t { } config_struct! { - impl FilterChainOptionsD3D12 => filter_chain_d3d12_opt_t { + impl FilterChainOptions => filter_chain_d3d12_opt_t { 0 => [force_hlsl_pipeline, force_no_mipmaps, disable_cache]; } } @@ -136,7 +133,7 @@ extern_fn! { let options = options.map(FromUninit::from_uninit); unsafe { - let chain = librashader::runtime::d3d12::capi::FilterChainD3D12::load_from_preset( + let chain = FilterChain::load_from_preset( *preset, &device, options.as_ref(), @@ -188,7 +185,7 @@ extern_fn! { let options = options.map(FromUninit::from_uninit); unsafe { - let chain = librashader::runtime::d3d12::capi::FilterChainD3D12::load_from_preset_deferred( + let chain = FilterChain::load_from_preset_deferred( *preset, &device, &command_list, diff --git a/librashader-capi/src/runtime/gl/filter_chain.rs b/librashader-capi/src/runtime/gl/filter_chain.rs index c73ee6d..0d5c336 100644 --- a/librashader-capi/src/runtime/gl/filter_chain.rs +++ b/librashader-capi/src/runtime/gl/filter_chain.rs @@ -3,7 +3,7 @@ use crate::ctypes::{ }; use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError}; use crate::ffi::extern_fn; -use librashader::runtime::gl::{GLFramebuffer, GLImage}; +use librashader::runtime::gl::{FilterChain, FilterChainOptions, FrameOptions, GLFramebuffer, GLImage}; use std::ffi::CStr; use std::ffi::{c_char, c_void, CString}; use std::mem::MaybeUninit; @@ -11,8 +11,6 @@ use std::ptr::NonNull; use std::slice; use crate::LIBRASHADER_API_VERSION; -use librashader::runtime::gl::capi::options::FilterChainOptionsGL; -use librashader::runtime::gl::capi::options::FrameOptionsGL; use librashader::runtime::FilterChainParameters; use librashader::runtime::{Size, Viewport}; @@ -67,7 +65,7 @@ pub struct frame_gl_opt_t { } config_struct! { - impl FrameOptionsGL => frame_gl_opt_t { + impl FrameOptions => frame_gl_opt_t { 0 => [clear_history, frame_direction]; } } @@ -92,7 +90,7 @@ pub struct filter_chain_gl_opt_t { } config_struct! { - impl FilterChainOptionsGL => filter_chain_gl_opt_t { + impl FilterChainOptions => filter_chain_gl_opt_t { 0 => [glsl_version, use_dsa, force_no_mipmaps, disable_cache]; } } @@ -149,7 +147,7 @@ extern_fn! { let options = options.map(FromUninit::from_uninit); unsafe { - let chain = librashader::runtime::gl::capi::FilterChainGL::load_from_preset(*preset, options.as_ref())?; + let chain = FilterChain::load_from_preset(*preset, options.as_ref())?; out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( chain, diff --git a/librashader-capi/src/runtime/vk/filter_chain.rs b/librashader-capi/src/runtime/vk/filter_chain.rs index efe9323..a84a55d 100644 --- a/librashader-capi/src/runtime/vk/filter_chain.rs +++ b/librashader-capi/src/runtime/vk/filter_chain.rs @@ -3,15 +3,13 @@ use crate::ctypes::{ }; use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError}; use crate::ffi::extern_fn; -use librashader::runtime::vk::{VulkanImage, VulkanInstance}; +use librashader::runtime::vk::{FrameOptions, FilterChainOptions, FilterChain, VulkanImage, VulkanInstance}; use std::ffi::CStr; use std::ffi::{c_char, c_void}; use std::mem::MaybeUninit; use std::ptr::NonNull; use std::slice; -use librashader::runtime::vk::capi::options::FilterChainOptionsVulkan; -use librashader::runtime::vk::capi::options::FrameOptionsVulkan; use librashader::runtime::FilterChainParameters; use librashader::runtime::{Size, Viewport}; @@ -96,7 +94,7 @@ pub struct frame_vk_opt_t { } config_struct! { - impl FrameOptionsVulkan => frame_vk_opt_t { + impl FrameOptions => frame_vk_opt_t { 0 => [clear_history, frame_direction]; } } @@ -120,7 +118,7 @@ pub struct filter_chain_vk_opt_t { } config_struct! { - impl FilterChainOptionsVulkan => filter_chain_vk_opt_t { + impl FilterChainOptions => filter_chain_vk_opt_t { 0 => [frames_in_flight, force_no_mipmaps, use_render_pass, disable_cache]; } } @@ -161,7 +159,7 @@ extern_fn! { let options = options.map(FromUninit::from_uninit); unsafe { - let chain = librashader::runtime::vk::capi::FilterChainVulkan::load_from_preset(*preset, vulkan, options.as_ref())?; + let chain = FilterChain::load_from_preset(*preset, vulkan, options.as_ref())?; out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( chain, @@ -212,7 +210,7 @@ extern_fn! { let options = options.map(FromUninit::from_uninit); unsafe { - let chain = librashader::runtime::vk::capi::FilterChainVulkan::load_from_preset_deferred(*preset, + let chain = FilterChain::load_from_preset_deferred(*preset, vulkan, command_buffer, options.as_ref())?; diff --git a/librashader-capi/src/wildcard.rs b/librashader-capi/src/wildcard.rs new file mode 100644 index 0000000..90d9ef8 --- /dev/null +++ b/librashader-capi/src/wildcard.rs @@ -0,0 +1,263 @@ +//! librashader preset wildcard context C API (`libra_preset_ctx_*`). + +use crate::ctypes::{libra_preset_ctx_t, LIBRA_PRESET_CTX_ORIENTATION, LIBRA_PRESET_CTX_RUNTIME}; +use crate::error::{assert_non_null, assert_some_ptr}; + +use librashader::presets::context::{ + ContextItem, PresetExtension, Rotation, ShaderExtension, WildcardContext, +}; +use std::ffi::{c_char, CStr}; +use std::mem::MaybeUninit; +use std::ptr::NonNull; + +use crate::ffi::extern_fn; + +const _: () = crate::assert_thread_safe::(); + +extern_fn! { + /// Create a wildcard context + /// + /// The C API does not allow directly setting certain variables + /// + /// - `PRESET_DIR` and `PRESET` are inferred on preset creation. + /// - `VID-DRV-SHADER-EXT` and `VID-DRV-PRESET-EXT` are always set to `slang` and `slangp` for librashader. + /// - `VID-FINAL-ROT` is automatically calculated as the sum of `VID-USER-ROT` and `CORE-REQ-ROT` if either are present. + /// + /// These automatically inferred variables, as well as all other variables can be overridden with + /// `libra_preset_ctx_set_param`, but the expected string values must be provided. + /// See https://github.com/libretro/RetroArch/pull/15023 for a list of expected string values. + /// + /// No variables can be removed once added to the context, however subsequent calls to set the same + /// variable will overwrite the expected variable. + /// ## Safety + /// - `out` must be either null, or an aligned pointer to an uninitialized or invalid `libra_preset_ctx_t`. + /// ## Returns + /// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`. + fn libra_preset_ctx_create( + out: *mut MaybeUninit + ) { + assert_non_null!(out); + + unsafe { + out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( + WildcardContext::new(), + ))))); + } + } +} + +extern_fn! { + /// Free the wildcard context. + /// + /// If `context` is null, this function does nothing. The resulting value in `context` then becomes + /// null. + /// + /// ## Safety + /// - `context` must be a valid and aligned pointer to a `libra_preset_ctx_t` + fn libra_preset_ctx_free(context: *mut libra_preset_ctx_t) { + assert_non_null!(context); + unsafe { + let context_ptr = &mut *context; + let context = context_ptr.take(); + drop(Box::from_raw(context.unwrap().as_ptr())); + } + } +} + +extern_fn! { + /// Set the core name (`CORE`) variable in the context + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + /// - `name` must be null or a valid and aligned pointer to a string. + fn libra_preset_ctx_set_core_name( + context: *mut libra_preset_ctx_t, + name: *const c_char, + ) |name|; mut |context| { + let name = unsafe { + CStr::from_ptr(name) + }; + + let name = name.to_str()?; + assert_some_ptr!(mut context); + + context.append_item(ContextItem::CoreName(String::from(name))); + } +} + +extern_fn! { + /// Set the content directory (`CONTENT-DIR`) variable in the context. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + /// - `name` must be null or a valid and aligned pointer to a string. + fn libra_preset_ctx_set_content_dir( + context: *mut libra_preset_ctx_t, + name: *const c_char, + ) |name|; mut |context| { + let name = unsafe { + CStr::from_ptr(name) + }; + + let name = name.to_str()?; + assert_some_ptr!(mut context); + context.append_item(ContextItem::ContentDirectory(String::from(name))); + } +} + +extern_fn! { + /// Set a custom string variable in context. + /// + /// If the path contains this variable when loading a preset, it will be replaced with the + /// provided contents. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + /// - `name` must be null or a valid and aligned pointer to a string. + /// - `value` must be null or a valid and aligned pointer to a string. + fn libra_preset_ctx_set_param( + context: *mut libra_preset_ctx_t, + name: *const c_char, + value: *const c_char, + ) |name, value|; mut |context| { + let name = unsafe { + CStr::from_ptr(name) + }; + let name = name.to_str()?; + + let value = unsafe { + CStr::from_ptr(value) + }; + let value = value.to_str()?; + + assert_some_ptr!(mut context); + context.append_item(ContextItem::ExternContext(String::from(name), String::from(value))); + } +} + +extern_fn! { + /// Set the graphics runtime (`VID-DRV`) variable in the context. + /// + /// Note that librashader only supports the following runtimes. + /// + /// - Vulkan + /// - GLCore + /// - Direct3D11 + /// - Direct3D12 + /// + /// This will also set the appropriate video driver extensions. + /// + /// For librashader, `VID-DRV-SHADER-EXT` and `VID-DRV-PRESET-EXT` are always `slang` and `slangp`. + /// To override this, use `libra_preset_ctx_set_param`. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + /// - `name` must be null or a valid and aligned pointer to a string. + fn libra_preset_ctx_set_runtime( + context: *mut libra_preset_ctx_t, + value: LIBRA_PRESET_CTX_RUNTIME, + ) mut |context| { + assert_some_ptr!(mut context); + + context.append_item(ContextItem::VideoDriverPresetExtension( + PresetExtension::Slangp, + )); + context.append_item(ContextItem::VideoDriverShaderExtension( + ShaderExtension::Slang, + )); + context.append_item(ContextItem::VideoDriver(value.into())); + } +} + +extern_fn! { + /// Set the core requested rotation (`CORE-REQ-ROT`) variable in the context. + /// + /// Rotation is represented by quarter rotations around the unit circle. + /// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = 0deg. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + fn libra_preset_ctx_set_core_rotation( + context: *mut libra_preset_ctx_t, + value: u32, + ) mut |context| { + assert_some_ptr!(mut context); + context.append_item(ContextItem::CoreRequestedRotation(Rotation::from(value))) + } +} + +extern_fn! { + /// Set the user rotation (`VID-USER-ROT`) variable in the context. + /// + /// Rotation is represented by quarter rotations around the unit circle. + /// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = 0deg. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + fn libra_preset_ctx_set_user_rotation( + context: *mut libra_preset_ctx_t, + value: u32, + ) mut |context| { + assert_some_ptr!(mut context); + context.append_item(ContextItem::UserRotation(Rotation::from(value))) + } +} + +extern_fn! { + /// Set the screen orientation (`SCREEN-ORIENT`) variable in the context. + /// + /// Orientation is represented by quarter rotations around the unit circle. + /// For example. `0` = 0deg, `1` = 90deg, `2` = 180deg, `3` = 270deg, `4` = 0deg. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + fn libra_preset_ctx_set_screen_orientation( + context: *mut libra_preset_ctx_t, + value: u32, + ) mut |context| { + assert_some_ptr!(mut context); + context.append_item(ContextItem::ScreenOrientation(Rotation::from(value))) + } +} + +extern_fn! { + /// Set whether or not to allow rotation (`VID-ALLOW-CORE-ROT`) variable in the context. + /// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + fn libra_preset_ctx_set_allow_rotation( + context: *mut libra_preset_ctx_t, + value: bool, + ) mut |context| { + assert_some_ptr!(mut context); + context.append_item(ContextItem::AllowCoreRotation(value.into())) + } +} + +extern_fn! { + /// Set the view aspect orientation (`VIEW-ASPECT-ORIENT`) variable in the context. + ////// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + fn libra_preset_ctx_set_view_aspect_orientation( + context: *mut libra_preset_ctx_t, + value: LIBRA_PRESET_CTX_ORIENTATION, + ) mut |context| { + assert_some_ptr!(mut context); + context.append_item(ContextItem::ViewAspectOrientation(value.into())) + } +} + +extern_fn! { + /// Set the core aspect orientation (`CORE-ASPECT-ORIENT`) variable in the context. + ////// + /// ## Safety + /// - `context` must be null or a valid and aligned pointer to a `libra_preset_ctx_t`. + fn libra_preset_ctx_set_core_aspect_orientation( + context: *mut libra_preset_ctx_t, + value: LIBRA_PRESET_CTX_ORIENTATION, + ) mut |context| { + assert_some_ptr!(mut context); + context.append_item(ContextItem::CoreAspectOrientation(value.into())) + } +} diff --git a/librashader-common/Cargo.toml b/librashader-common/Cargo.toml index deb7e8d..b64275a 100644 --- a/librashader-common/Cargo.toml +++ b/librashader-common/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-common" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" diff --git a/librashader-preprocess/Cargo.toml b/librashader-preprocess/Cargo.toml index eba3d66..b15d345 100644 --- a/librashader-preprocess/Cargo.toml +++ b/librashader-preprocess/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-preprocess" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -14,7 +14,7 @@ description = "RetroArch shaders for all." [dependencies] thiserror = "1.0.37" nom = "7.1.1" -librashader-common = { path = "../librashader-common", version = "0.2.0-beta.7" } +librashader-common = { path = "../librashader-common", version = "0.2.0-beta.8" } rustc-hash = "1.1.0" encoding_rs = "0.8.31" diff --git a/librashader-presets/Cargo.toml b/librashader-presets/Cargo.toml index 18e2358..89bab04 100644 --- a/librashader-presets/Cargo.toml +++ b/librashader-presets/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-presets" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -15,8 +15,15 @@ description = "RetroArch shaders for all." thiserror = "1.0.37" nom = "7.1.1" nom_locate = "4.0.0" -librashader-common = { path = "../librashader-common", version = "0.2.0-beta.7" } +librashader-common = { path = "../librashader-common", version = "0.2.0-beta.8" } num-traits = "0.2" +once_cell = "1" +# we don't need unicode +regex = { version = "1", default-features = false, features = ["perf"] } +rustc-hash = "1.1.0" + +rustversion = "1.0" +os_str_bytes = { version = "6", features = ["conversions"] } [features] parse_legacy_glsl = [] diff --git a/librashader-presets/src/context.rs b/librashader-presets/src/context.rs new file mode 100644 index 0000000..b9a977e --- /dev/null +++ b/librashader-presets/src/context.rs @@ -0,0 +1,460 @@ +// pub use librashader_presets_context::*; + +//! Shader preset wildcard replacement context handling. +//! +//! Implements wildcard replacement of shader paths specified in +//! [RetroArch#15023](https://github.com/libretro/RetroArch/pull/15023). +use once_cell::sync::Lazy; +use regex::bytes::Regex; +use rustc_hash::FxHashMap; +use std::collections::VecDeque; +use std::fmt::{Debug, Display, Formatter}; +use std::ops::Add; +use std::path::{Component, Path, PathBuf}; + +/// Valid video driver or runtime. This list is non-exhaustive. +#[repr(u32)] +#[non_exhaustive] +#[derive(Debug, Copy, Clone)] +pub enum VideoDriver { + /// None (`null`) + None = 0, + /// OpenGL Core (`glcore`) + GlCore, + /// Legacy OpenGL (`gl`) + Gl, + /// Vulkan (`vulkan`) + Vulkan, + /// Direct3D 9 (`d3d9_hlsl`) + Direct3D9Hlsl, + /// Direct3D 11 (`d3d11`) + Direct3D11, + /// Direct3D12 (`d3d12`) + Direct3D12, + /// Metal (`metal`) + Metal, +} + +impl Display for VideoDriver { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + VideoDriver::None => f.write_str("null"), + VideoDriver::GlCore => f.write_str("glcore"), + VideoDriver::Gl => f.write_str("gl"), + VideoDriver::Vulkan => f.write_str("vulkan"), + VideoDriver::Direct3D11 => f.write_str("d3d11"), + VideoDriver::Direct3D9Hlsl => f.write_str("d3d9_hlsl"), + VideoDriver::Direct3D12 => f.write_str("d3d12"), + VideoDriver::Metal => f.write_str("metal"), + } + } +} + +/// Valid extensions for shader extensions. +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum ShaderExtension { + /// `.slang` + Slang = 0, + /// `.glsl` + Glsl, + /// `.cg` + Cg, +} + +impl Display for ShaderExtension { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ShaderExtension::Slang => f.write_str("slang"), + ShaderExtension::Glsl => f.write_str("glsl"), + ShaderExtension::Cg => f.write_str("cg"), + } + } +} + +/// Valid extensions for shader presets +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum PresetExtension { + /// `.slangp` + Slangp = 0, + /// `.glslp` + Glslp, + /// `.cgp` + Cgp, +} + +impl Display for PresetExtension { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + PresetExtension::Slangp => f.write_str("slangp"), + PresetExtension::Glslp => f.write_str("glslp"), + PresetExtension::Cgp => f.write_str("cgp"), + } + } +} + +/// Rotation of the viewport. +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum Rotation { + /// Zero + Zero = 0, + /// 90 degrees + Right = 1, + /// 180 degrees + Straight = 2, + /// 270 degrees + Reflex = 3, +} + +impl From for Rotation { + fn from(value: u32) -> Self { + let value = value % 4; + match value { + 0 => Rotation::Zero, + 1 => Rotation::Right, + 2 => Rotation::Straight, + 3 => Rotation::Reflex, + _ => unreachable!(), + } + } +} + +impl Add for Rotation { + type Output = Rotation; + + fn add(self, rhs: Self) -> Self::Output { + let lhs = self as u32; + let out = lhs + rhs as u32; + Rotation::from(out) + } +} + +impl Display for Rotation { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Rotation::Zero => f.write_str("0"), + Rotation::Right => f.write_str("90"), + Rotation::Straight => f.write_str("180"), + Rotation::Reflex => f.write_str("270"), + } + } +} + +/// Orientation of aspect ratios +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum Orientation { + /// Vertical orientation. + Vertical = 0, + /// Horizontal orientation. + Horizontal, +} + +impl Display for Orientation { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Orientation::Vertical => f.write_str("VERT"), + Orientation::Horizontal => f.write_str("HORZ"), + } + } +} + +/// An item representing a variable that can be replaced in a path preset. +#[derive(Debug, Clone)] +pub enum ContextItem { + /// The content directory of the game (`CONTENT-DIR`) + ContentDirectory(String), + /// The name of the libretro core (`CORE`) + CoreName(String), + /// The filename of the game (`GAME`) + GameName(String), + /// The name of the preset (`PRESET`) + Preset(String), + /// The name of the preset directory (`PRESET_DIR`) + PresetDirectory(String), + /// The video driver (runtime) (`VID-DRV`) + VideoDriver(VideoDriver), + /// The extension of shader types supported by the driver (`VID-DRV-SHADER-EXT`) + VideoDriverShaderExtension(ShaderExtension), + /// The extension of shader presets supported by the driver (`VID-DRV-PRESET-EXT`) + VideoDriverPresetExtension(PresetExtension), + /// The rotation that the core is requesting (`CORE-REQ-ROT`) + CoreRequestedRotation(Rotation), + /// Whether or not to allow core-requested rotation (`VID-ALLOW-CORE-ROT`) + AllowCoreRotation(bool), + /// The rotation the user is requesting (`VID-USER-ROT`) + UserRotation(Rotation), + /// The final rotation (`VID-FINAL-ROT`) calculated by the sum of `VID-USER-ROT` and `CORE-REQ-ROT` + FinalRotation(Rotation), + /// The user-adjusted screen orientation (`SCREEN-ORIENT`) + ScreenOrientation(Rotation), + /// The orientation of the viewport aspect ratio (`VIEW-ASPECT-ORIENT`) + ViewAspectOrientation(Orientation), + /// The orientation of the aspect ratio requested by the core (`CORE-ASPECT-ORIENT`) + CoreAspectOrientation(Orientation), + /// An external, arbitrary context variable. + ExternContext(String, String), +} + +impl ContextItem { + fn toggle_str(v: bool) -> &'static str { + if v { + "ON" + } else { + "OFF" + } + } + + pub fn key(&self) -> &str { + match self { + ContextItem::ContentDirectory(_) => "CONTENT-DIR", + ContextItem::CoreName(_) => "CORE", + ContextItem::GameName(_) => "GAME", + ContextItem::Preset(_) => "PRESET", + ContextItem::PresetDirectory(_) => "PRESET_DIR", + ContextItem::VideoDriver(_) => "VID-DRV", + ContextItem::CoreRequestedRotation(_) => "CORE-REQ-ROT", + ContextItem::AllowCoreRotation(_) => "VID-ALLOW-CORE-ROT", + ContextItem::UserRotation(_) => "VID-USER-ROT", + ContextItem::FinalRotation(_) => "VID-FINAL-ROT", + ContextItem::ScreenOrientation(_) => "SCREEN-ORIENT", + ContextItem::ViewAspectOrientation(_) => "VIEW-ASPECT-ORIENT", + ContextItem::CoreAspectOrientation(_) => "CORE-ASPECT-ORIENT", + ContextItem::VideoDriverShaderExtension(_) => "VID-DRV-SHADER-EXT", + ContextItem::VideoDriverPresetExtension(_) => "VID-DRV-PRESET-EXT", + ContextItem::ExternContext(key, _) => key, + } + } +} + +impl Display for ContextItem { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ContextItem::ContentDirectory(v) => f.write_str(v), + ContextItem::CoreName(v) => f.write_str(v), + ContextItem::GameName(v) => f.write_str(v), + ContextItem::Preset(v) => f.write_str(v), + ContextItem::PresetDirectory(v) => f.write_str(v), + ContextItem::VideoDriver(v) => f.write_fmt(format_args!("{}", v)), + ContextItem::CoreRequestedRotation(v) => { + f.write_fmt(format_args!("{}-{}", self.key(), v)) + } + ContextItem::AllowCoreRotation(v) => f.write_fmt(format_args!( + "{}-{}", + self.key(), + ContextItem::toggle_str(*v) + )), + ContextItem::UserRotation(v) => f.write_fmt(format_args!("{}-{}", self.key(), v)), + ContextItem::FinalRotation(v) => f.write_fmt(format_args!("{}-{}", self.key(), v)), + ContextItem::ScreenOrientation(v) => f.write_fmt(format_args!("{}-{}", self.key(), v)), + ContextItem::ViewAspectOrientation(v) => { + f.write_fmt(format_args!("{}-{}", self.key(), v)) + } + ContextItem::CoreAspectOrientation(v) => { + f.write_fmt(format_args!("{}-{}", self.key(), v)) + } + ContextItem::VideoDriverShaderExtension(v) => f.write_fmt(format_args!("{}", v)), + ContextItem::VideoDriverPresetExtension(v) => f.write_fmt(format_args!("{}", v)), + ContextItem::ExternContext(_, v) => f.write_fmt(format_args!("{}", v)), + } + } +} + +/// A preset wildcard context. +/// +/// Any items added after will have higher priority +/// when passed to the shader preset parser. +/// +/// When passed to the preset parser, the preset parser +/// will automatically add inferred items at lowest priority. +/// +/// Any items added by the user will override the automatically +/// inferred items. +#[derive(Debug, Clone)] +pub struct WildcardContext(VecDeque); + +impl WildcardContext { + /// Create a new wildcard context. + pub fn new() -> Self { + Self(VecDeque::new()) + } + + /// Prepend an item to the context builder. + pub fn prepend_item(&mut self, item: ContextItem) { + self.0.push_front(item); + } + + /// Append an item to the context builder. + /// The new item will take precedence over all items added before it. + pub fn append_item(&mut self, item: ContextItem) { + self.0.push_back(item); + } + + /// Prepend sensible defaults for the given video driver. + /// + /// Any values added, either previously or afterwards will not be overridden. + pub fn add_video_driver_defaults(&mut self, video_driver: VideoDriver) { + self.prepend_item(ContextItem::VideoDriverPresetExtension( + PresetExtension::Slangp, + )); + self.prepend_item(ContextItem::VideoDriverShaderExtension( + ShaderExtension::Slang, + )); + self.prepend_item(ContextItem::VideoDriver(video_driver)); + } + + /// Prepend default entries from the path of the preset. + /// + /// Any values added, either previously or afterwards will not be overridden. + pub fn add_path_defaults(&mut self, path: impl AsRef) { + let path = path.as_ref(); + if let Some(preset_name) = path.file_stem() { + let preset_name = preset_name.to_string_lossy(); + self.prepend_item(ContextItem::Preset(preset_name.into())) + } + + if let Some(preset_dir_name) = path.parent().and_then(|p| { + if !p.is_dir() { + return None; + }; + p.file_name() + }) { + let preset_dir_name = preset_dir_name.to_string_lossy(); + self.prepend_item(ContextItem::PresetDirectory(preset_dir_name.into())) + } + } + + pub fn to_hashmap(mut self) -> FxHashMap { + let mut map = FxHashMap::default(); + let last_user_rot = self + .0 + .iter() + .rfind(|i| matches!(i, ContextItem::UserRotation(_))); + let last_core_rot = self + .0 + .iter() + .rfind(|i| matches!(i, ContextItem::CoreRequestedRotation(_))); + + let final_rot = match (last_core_rot, last_user_rot) { + (Some(ContextItem::UserRotation(u)), None) => Some(ContextItem::FinalRotation(*u)), + (None, Some(ContextItem::CoreRequestedRotation(c))) => { + Some(ContextItem::FinalRotation(*c)) + } + (Some(ContextItem::UserRotation(u)), Some(ContextItem::CoreRequestedRotation(c))) => { + Some(ContextItem::FinalRotation(*u + *c)) + } + _ => None, + }; + + if let Some(final_rot) = final_rot { + self.prepend_item(final_rot); + } + + for item in self.0 { + map.insert(String::from(item.key()), item.to_string()); + } + + map + } +} + +#[rustversion::since(1.74)] +pub(crate) fn apply_context(path: &mut PathBuf, context: &FxHashMap) { + use std::ffi::{OsStr, OsString}; + + static WILDCARD_REGEX: Lazy = Lazy::new(|| Regex::new("\\$([A-Z-_]+)\\$").unwrap()); + if context.is_empty() { + return; + } + // Don't want to do any extra work if there's no match. + if !WILDCARD_REGEX.is_match(path.as_os_str().as_encoded_bytes()) { + return; + } + + let mut new_path = PathBuf::with_capacity(path.capacity()); + for component in path.components() { + match component { + Component::Normal(path) => { + let haystack = path.as_encoded_bytes(); + + + let replaced = + WILDCARD_REGEX.replace_all(haystack, |caps: ®ex::bytes::Captures| { + let Some(name) = caps.get(1) else { + return caps[0].to_vec(); + }; + + let Ok(key) = std::str::from_utf8(name.as_bytes()) else { + return caps[0].to_vec(); + }; + if let Some(replacement) = context.get(key) { + return OsString::from(replacement.to_string()).into_encoded_bytes(); + } + return caps[0].to_vec(); + }); + + // SAFETY: The original source is valid encoded bytes, and our replacement is + // valid encoded bytes. This upholds the safety requirements of `from_encoded_bytes_unchecked`. + new_path.push(unsafe { OsStr::from_encoded_bytes_unchecked(&replaced.as_ref()) }) + } + _ => new_path.push(component), + } + } + + // If no wildcards are found within the path, or the path after replacing the wildcards does not exist on disk, the path returned will be unaffected. + if let Ok(true) = new_path.try_exists() { + *path = new_path; + } +} + +#[rustversion::before(1.74)] +pub(crate) fn apply_context(path: &mut PathBuf, context: &FxHashMap) { + use os_str_bytes::RawOsStr; + static WILDCARD_REGEX: Lazy = Lazy::new(|| Regex::new("\\$([A-Z-_]+)\\$").unwrap()); + if context.is_empty() { + return; + } + let path_str = RawOsStr::new(path.as_os_str()); + let path_bytes = path_str.to_raw_bytes(); + // Don't want to do any extra work if there's no match. + if !WILDCARD_REGEX.is_match(&path_bytes) { + return; + } + + let mut new_path = PathBuf::with_capacity(path.capacity()); + for component in path.components() { + match component { + Component::Normal(path) => { + let haystack = RawOsStr::new(path); + let haystack = haystack.to_raw_bytes(); + + let replaced = + WILDCARD_REGEX.replace_all(&haystack, |caps: ®ex::bytes::Captures| { + let Some(name) = caps.get(1) else { + return caps[0].to_vec(); + }; + + let Ok(key) = std::str::from_utf8(name.as_bytes()) else { + return caps[0].to_vec(); + }; + if let Some(replacement) = context.get(key) { + return RawOsStr::from_str(replacement).to_raw_bytes().to_vec(); + } + return caps[0].to_vec(); + }); + + // SAFETY: The original source is valid encoded bytes, and our replacement is + // valid encoded bytes. This upholds the safety requirements of `from_encoded_bytes_unchecked`. + new_path.push(RawOsStr::assert_cow_from_raw_bytes(&replaced.as_ref()).to_os_str()) + } + _ => new_path.push(component), + } + } + + // If no wildcards are found within the path, or the path after replacing the wildcards does not exist on disk, the path returned will be unaffected. + if let Ok(true) = new_path.try_exists() { + *path = new_path; + } +} diff --git a/librashader-presets/src/extract_if.rs b/librashader-presets/src/extract_if.rs index 7f38dc4..0901df4 100644 --- a/librashader-presets/src/extract_if.rs +++ b/librashader-presets/src/extract_if.rs @@ -148,7 +148,7 @@ where #[cfg(test)] mod test { - use crate::MakeExtractIf; + use crate::extract_if::MakeExtractIf; #[test] fn drain_filter_empty() { let mut vec: Vec = vec![]; diff --git a/librashader-presets/src/lib.rs b/librashader-presets/src/lib.rs index 3200ffd..4cb0de1 100644 --- a/librashader-presets/src/lib.rs +++ b/librashader-presets/src/lib.rs @@ -8,12 +8,15 @@ //! //! Re-exported as [`librashader::presets`](https://docs.rs/librashader/latest/librashader/presets/index.html). +#![allow(stable_features)] #![allow(unstable_name_collisions)] mod error; mod extract_if; mod parse; mod preset; +pub mod context; +pub use context::WildcardContext; pub use error::*; pub use preset::*; diff --git a/librashader-presets/src/parse/context.rs b/librashader-presets/src/parse/context.rs new file mode 100644 index 0000000..fb31a0b --- /dev/null +++ b/librashader-presets/src/parse/context.rs @@ -0,0 +1,404 @@ +//! Shader preset wildcard replacement context handling. +//! +//! Implements wildcard replacement of shader paths specified in +//! [RetroArch#15023](https://github.com/libretro/RetroArch/pull/15023). +use once_cell::sync::Lazy; +use regex::bytes::Regex; +use rustc_hash::FxHashMap; +use std::collections::VecDeque; +use std::ffi::{OsStr, OsString}; +use std::fmt::{Debug, Display, Formatter}; +use std::ops::Add; +use std::path::{Component, Path, PathBuf}; + +/// Valid video driver or runtime. This list is non-exhaustive. +#[repr(u32)] +#[non_exhaustive] +#[derive(Debug, Copy, Clone)] +pub enum VideoDriver { + /// None (`null`) + None = 0, + /// OpenGL Core (`glcore`) + GlCore, + /// Legacy OpenGL (`gl`) + Gl, + /// Vulkan (`vulkan`) + Vulkan, + /// Direct3D 9 (`d3d9_hlsl`) + Direct3D9Hlsl, + /// Direct3D 11 (`d3d11`) + Direct3D11, + /// Direct3D12 (`d3d12`) + Direct3D12, + /// Metal (`metal`) + Metal, +} + +impl Display for VideoDriver { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + VideoDriver::None => f.write_str("null"), + VideoDriver::GlCore => f.write_str("glcore"), + VideoDriver::Gl => f.write_str("gl"), + VideoDriver::Vulkan => f.write_str("vulkan"), + VideoDriver::Direct3D11 => f.write_str("d3d11"), + VideoDriver::Direct3D9Hlsl => f.write_str("d3d9_hlsl"), + VideoDriver::Direct3D12 => f.write_str("d3d12"), + VideoDriver::Metal => f.write_str("metal"), + } + } +} + +/// Valid extensions for shader extensions. +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum ShaderExtension { + /// `.slang` + Slang = 0, + /// `.glsl` + Glsl, + /// `.cg` + Cg, +} + +impl Display for ShaderExtension { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ShaderExtension::Slang => f.write_str("slang"), + ShaderExtension::Glsl => f.write_str("glsl"), + ShaderExtension::Cg => f.write_str("cg"), + } + } +} + +/// Valid extensions for shader presets +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum PresetExtension { + /// `.slangp` + Slangp = 0, + /// `.glslp` + Glslp, + /// `.cgp` + Cgp, +} + +impl Display for PresetExtension { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + PresetExtension::Slangp => f.write_str("slangp"), + PresetExtension::Glslp => f.write_str("glslp"), + PresetExtension::Cgp => f.write_str("cgp"), + } + } +} + +/// Rotation of the viewport. +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum Rotation { + /// Zero + Zero = 0, + /// 90 degrees + Right = 1, + /// 180 degrees + Straight = 2, + /// 270 degrees + Reflex = 3, +} + +impl From for Rotation { + fn from(value: u32) -> Self { + let value = value % 4; + match value { + 0 => Rotation::Zero, + 1 => Rotation::Right, + 2 => Rotation::Straight, + 3 => Rotation::Reflex, + _ => unreachable!(), + } + } +} + +impl Add for Rotation { + type Output = Rotation; + + fn add(self, rhs: Self) -> Self::Output { + let lhs = self as u32; + let out = lhs + rhs as u32; + Rotation::from(out) + } +} + +impl Display for Rotation { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Rotation::Zero => f.write_str("0"), + Rotation::Right => f.write_str("90"), + Rotation::Straight => f.write_str("180"), + Rotation::Reflex => f.write_str("270"), + } + } +} + +/// Orientation of aspect ratios +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum Orientation { + /// Vertical orientation. + Vertical = 0, + /// Horizontal orientation. + Horizontal, +} + +impl Display for Orientation { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Orientation::Vertical => f.write_str("VERT"), + Orientation::Horizontal => f.write_str("HORZ"), + } + } +} + +/// An item representing a variable that can be replaced in a path preset. +#[derive(Debug, Clone)] +pub enum ContextItem { + /// The content directory of the game (`CONTENT-DIR`) + ContentDirectory(String), + /// The name of the libretro core (`CORE`) + CoreName(String), + /// The filename of the game (`GAME`) + GameName(String), + /// The name of the preset (`PRESET`) + Preset(String), + /// The name of the preset directory (`PRESET_DIR`) + PresetDirectory(String), + /// The video driver (runtime) (`VID-DRV`) + VideoDriver(VideoDriver), + /// The extension of shader types supported by the driver (`VID-DRV-SHADER-EXT`) + VideoDriverShaderExtension(ShaderExtension), + /// The extension of shader presets supported by the driver (`VID-DRV-PRESET-EXT`) + VideoDriverPresetExtension(PresetExtension), + /// The rotation that the core is requesting (`CORE-REQ-ROT`) + CoreRequestedRotation(Rotation), + /// Whether or not to allow core-requested rotation (`VID-ALLOW-CORE-ROT`) + AllowCoreRotation(bool), + /// The rotation the user is requesting (`VID-USER-ROT`) + UserRotation(Rotation), + /// The final rotation (`VID-FINAL-ROT`) calculated by the sum of `VID-USER-ROT` and `CORE-REQ-ROT` + FinalRotation(Rotation), + /// The user-adjusted screen orientation (`SCREEN-ORIENT`) + ScreenOrientation(Rotation), + /// The orientation of the viewport aspect ratio (`VIEW-ASPECT-ORIENT`) + ViewAspectOrientation(Orientation), + /// The orientation of the aspect ratio requested by the core (`CORE-ASPECT-ORIENT`) + CoreAspectOrientation(Orientation), + /// An external, arbitrary context variable. + ExternContext(String, String), +} + +impl ContextItem { + fn toggle_str(v: bool) -> &'static str { + if v { + "ON" + } else { + "OFF" + } + } + + pub fn key(&self) -> &str { + match self { + ContextItem::ContentDirectory(_) => "CONTENT-DIR", + ContextItem::CoreName(_) => "CORE", + ContextItem::GameName(_) => "GAME", + ContextItem::Preset(_) => "PRESET", + ContextItem::PresetDirectory(_) => "PRESET_DIR", + ContextItem::VideoDriver(_) => "VID-DRV", + ContextItem::CoreRequestedRotation(_) => "CORE-REQ-ROT", + ContextItem::AllowCoreRotation(_) => "VID-ALLOW-CORE-ROT", + ContextItem::UserRotation(_) => "VID-USER-ROT", + ContextItem::FinalRotation(_) => "VID-FINAL-ROT", + ContextItem::ScreenOrientation(_) => "SCREEN-ORIENT", + ContextItem::ViewAspectOrientation(_) => "VIEW-ASPECT-ORIENT", + ContextItem::CoreAspectOrientation(_) => "CORE-ASPECT-ORIENT", + ContextItem::VideoDriverShaderExtension(_) => "VID-DRV-SHADER-EXT", + ContextItem::VideoDriverPresetExtension(_) => "VID-DRV-PRESET-EXT", + ContextItem::ExternContext(key, _) => key, + } + } +} + +impl Display for ContextItem { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ContextItem::ContentDirectory(v) => f.write_str(v), + ContextItem::CoreName(v) => f.write_str(v), + ContextItem::GameName(v) => f.write_str(v), + ContextItem::Preset(v) => f.write_str(v), + ContextItem::PresetDirectory(v) => f.write_str(v), + ContextItem::VideoDriver(v) => f.write_fmt(format_args!("{}", v)), + ContextItem::CoreRequestedRotation(v) => { + f.write_fmt(format_args!("{}-{}", self.key(), v)) + } + ContextItem::AllowCoreRotation(v) => f.write_fmt(format_args!( + "{}-{}", + self.key(), + ContextItem::toggle_str(*v) + )), + ContextItem::UserRotation(v) => f.write_fmt(format_args!("{}-{}", self.key(), v)), + ContextItem::FinalRotation(v) => f.write_fmt(format_args!("{}-{}", self.key(), v)), + ContextItem::ScreenOrientation(v) => f.write_fmt(format_args!("{}-{}", self.key(), v)), + ContextItem::ViewAspectOrientation(v) => { + f.write_fmt(format_args!("{}-{}", self.key(), v)) + } + ContextItem::CoreAspectOrientation(v) => { + f.write_fmt(format_args!("{}-{}", self.key(), v)) + } + ContextItem::VideoDriverShaderExtension(v) => f.write_fmt(format_args!("{}", v)), + ContextItem::VideoDriverPresetExtension(v) => f.write_fmt(format_args!("{}", v)), + ContextItem::ExternContext(_, v) => f.write_fmt(format_args!("{}", v)), + } + } +} + +/// A preset wildcard context. +/// +/// Any items added after will have higher priority +/// when passed to the shader preset parser. +/// +/// When passed to the preset parser, the preset parser +/// will automatically add inferred items at lowest priority. +/// +/// Any items added by the user will override the automatically +/// inferred items. +#[derive(Debug, Clone)] +pub struct WildcardContext(VecDeque); + +impl WildcardContext { + /// Create a new wildcard context. + pub fn new() -> Self { + Self(VecDeque::new()) + } + + /// Prepend an item to the context builder. + pub fn prepend_item(&mut self, item: ContextItem) { + self.0.push_front(item); + } + + /// Append an item to the context builder. + /// The new item will take precedence over all items added before it. + pub fn append_item(&mut self, item: ContextItem) { + self.0.push_back(item); + } + + /// Prepend sensible defaults for the given video driver. + /// + /// Any values added, either previously or afterwards will not be overridden. + pub fn add_video_driver_defaults(&mut self, video_driver: VideoDriver) { + self.prepend_item(ContextItem::VideoDriverPresetExtension( + PresetExtension::Slangp, + )); + self.prepend_item(ContextItem::VideoDriverShaderExtension( + ShaderExtension::Slang, + )); + self.prepend_item(ContextItem::VideoDriver(video_driver)); + } + + /// Prepend default entries from the path of the preset. + /// + /// Any values added, either previously or afterwards will not be overridden. + pub fn add_path_defaults(&mut self, path: impl AsRef) { + let path = path.as_ref(); + if let Some(preset_name) = path.file_stem() { + let preset_name = preset_name.to_string_lossy(); + self.prepend_item(ContextItem::Preset(preset_name.into())) + } + + if let Some(preset_dir_name) = path.parent().and_then(|p| { + if !p.is_dir() { + return None; + }; + p.file_name() + }) { + let preset_dir_name = preset_dir_name.to_string_lossy(); + self.prepend_item(ContextItem::PresetDirectory(preset_dir_name.into())) + } + } + + pub(crate) fn to_hashmap(mut self) -> FxHashMap { + let mut map = FxHashMap::default(); + let last_user_rot = self + .0 + .iter() + .rfind(|i| matches!(i, ContextItem::UserRotation(_))); + let last_core_rot = self + .0 + .iter() + .rfind(|i| matches!(i, ContextItem::CoreRequestedRotation(_))); + + let final_rot = match (last_core_rot, last_user_rot) { + (Some(ContextItem::UserRotation(u)), None) => Some(ContextItem::FinalRotation(*u)), + (None, Some(ContextItem::CoreRequestedRotation(c))) => { + Some(ContextItem::FinalRotation(*c)) + } + (Some(ContextItem::UserRotation(u)), Some(ContextItem::CoreRequestedRotation(c))) => { + Some(ContextItem::FinalRotation(*u + *c)) + } + _ => None, + }; + + if let Some(final_rot) = final_rot { + self.prepend_item(final_rot); + } + + for item in self.0 { + map.insert(String::from(item.key()), item.to_string()); + } + + map + } +} + +pub(crate) fn apply_context(path: &mut PathBuf, context: &FxHashMap) { + static WILDCARD_REGEX: Lazy = Lazy::new(|| Regex::new("\\$([A-Z-_]+)\\$").unwrap()); + if context.is_empty() { + return; + } + // Don't want to do any extra work if there's no match. + if !WILDCARD_REGEX.is_match(path.as_os_str().as_encoded_bytes()) { + return; + } + + let mut new_path = PathBuf::with_capacity(path.capacity()); + for component in path.components() { + match component { + Component::Normal(path) => { + let haystack = path.as_encoded_bytes(); + let replaced = + WILDCARD_REGEX.replace_all(haystack, |caps: ®ex::bytes::Captures| { + let Some(name) = caps.get(1) else { + return caps[0].to_vec(); + }; + + let Ok(key) = std::str::from_utf8(name.as_bytes()) else { + return caps[0].to_vec(); + }; + if let Some(replacement) = context.get(key) { + return OsString::from(replacement.to_string()).into_encoded_bytes(); + } + return caps[0].to_vec(); + }); + + // SAFETY: The original source is valid encoded bytes, and our replacement is + // valid encoded bytes. This upholds the safety requirements of `from_encoded_bytes_unchecked`. + new_path.push(unsafe { OsStr::from_encoded_bytes_unchecked(&replaced.as_ref()) }) + } + _ => new_path.push(component), + } + } + + // If no wildcards are found within the path, or the path after replacing the wildcards does not exist on disk, the path returned will be unaffected. + if let Ok(true) = new_path.try_exists() { + *path = new_path; + } +} diff --git a/librashader-presets/src/parse/mod.rs b/librashader-presets/src/parse/mod.rs index 88afc9f..7246ef4 100644 --- a/librashader-presets/src/parse/mod.rs +++ b/librashader-presets/src/parse/mod.rs @@ -11,6 +11,7 @@ pub(crate) type Span<'a> = LocatedSpan<&'a str>; pub(crate) use token::Token; use crate::error::ParsePresetError; +use crate::context::{VideoDriver, WildcardContext}; use crate::parse::preset::resolve_values; use crate::parse::value::parse_preset; use crate::ShaderPreset; @@ -21,8 +22,38 @@ pub(crate) fn remove_if(values: &mut Vec, f: impl FnMut(&T) -> bool) -> Op impl ShaderPreset { /// Try to parse the shader preset at the given path. + /// + /// This will add path defaults to the wildcard resolution context. pub fn try_parse(path: impl AsRef) -> Result { - let values = parse_preset(path)?; + let mut context = WildcardContext::new(); + context.add_path_defaults(path.as_ref()); + let values = parse_preset(path, WildcardContext::new())?; + Ok(resolve_values(values)) + } + + /// Try to parse the shader preset at the given path. + /// + /// This will add path and driver defaults to the wildcard resolution context. + pub fn try_parse_with_driver_context( + path: impl AsRef, + driver: VideoDriver, + ) -> Result { + let mut context = WildcardContext::new(); + context.add_path_defaults(path.as_ref()); + context.add_video_driver_defaults(driver); + let values = parse_preset(path, context)?; + Ok(resolve_values(values)) + } + + /// Try to parse the shader preset at the given path, with the exact provided context. + /// + /// This function does not change any of the values in the provided context, except calculating `VID-FINAL-ROT` + /// if `CORE-REQ-ROT` and `VID-USER-ROT` is present. + pub fn try_parse_with_context( + path: impl AsRef, + context: WildcardContext, + ) -> Result { + let values = parse_preset(path, context)?; Ok(resolve_values(values)) } } diff --git a/librashader-presets/src/parse/token.rs b/librashader-presets/src/parse/token.rs index 039ae82..a237710 100644 --- a/librashader-presets/src/parse/token.rs +++ b/librashader-presets/src/parse/token.rs @@ -171,7 +171,7 @@ pub fn do_lex(input: &str) -> Result, ParsePresetError> { #[cfg(test)] mod test { - use crate::parse::token::{do_lex, single_comment}; + use crate::parse::token::{single_comment}; #[test] fn parses_single_line_comment() { diff --git a/librashader-presets/src/parse/value.rs b/librashader-presets/src/parse/value.rs index 0e17d15..dd97307 100644 --- a/librashader-presets/src/parse/value.rs +++ b/librashader-presets/src/parse/value.rs @@ -11,12 +11,14 @@ use num_traits::cast::ToPrimitive; use crate::parse::token::do_lex; use librashader_common::{FilterMode, WrapMode}; +use rustc_hash::FxHashMap; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; use std::str::FromStr; use crate::extract_if::MakeExtractIf; +use crate::context::{apply_context, WildcardContext}; #[derive(Debug)] pub enum Value { @@ -150,9 +152,11 @@ fn parse_indexed_key<'a>(key: &'static str, input: Span<'a>) -> IResult pub const SHADER_MAX_REFERENCE_DEPTH: usize = 16; +// prereq: root_path must be contextualized fn load_child_reference_strings( root_references: Vec, root_path: impl AsRef, + context: &FxHashMap, ) -> Result, ParsePresetError> { let root_path = root_path.as_ref(); @@ -161,13 +165,14 @@ fn load_child_reference_strings( let root_references = vec![(root_path.to_path_buf(), root_references)]; let mut root_references = VecDeque::from(root_references); // search needs to be depth first to allow for overrides. - while let Some((reference_root, referenced_paths)) = root_references.pop_front() { + while let Some((mut reference_root, referenced_paths)) = root_references.pop_front() { if reference_depth > SHADER_MAX_REFERENCE_DEPTH { return Err(ParsePresetError::ExceededReferenceDepth); } // enter the current root reference_depth += 1; // canonicalize current root + apply_context(&mut reference_root, context); let reference_root = reference_root .canonicalize() .map_err(|e| ParsePresetError::IOError(reference_root.to_path_buf(), e))?; @@ -176,8 +181,10 @@ fn load_child_reference_strings( // println!("Resolving {referenced_paths:?} against {reference_root:?}."); for path in referenced_paths { - let mut path = reference_root - .join(path.clone()) + let mut path = reference_root.join(path.clone()); + apply_context(&mut path, context); + + let mut path = path .canonicalize() .map_err(|e| ParsePresetError::IOError(path.clone(), e))?; // println!("Opening {:?}", path); @@ -204,8 +211,16 @@ fn load_child_reference_strings( Ok(reference_strings.into()) } -pub fn parse_preset(path: impl AsRef) -> Result, ParsePresetError> { +pub(crate) fn parse_preset( + path: impl AsRef, + context: WildcardContext, +) -> Result, ParsePresetError> { let path = path.as_ref(); + let mut path = path.to_path_buf(); + let context = context.to_hashmap(); + + apply_context(&mut path, &context); + let path = path .canonicalize() .map_err(|e| ParsePresetError::IOError(path.to_path_buf(), e))?; @@ -216,12 +231,14 @@ pub fn parse_preset(path: impl AsRef) -> Result, ParsePresetErr .map_err(|e| ParsePresetError::IOError(path.to_path_buf(), e))?; let tokens = super::token::do_lex(&contents)?; - parse_values(tokens, path) + parse_values(tokens, path, context) } +// prereq: root_path must be contextualized pub fn parse_values( mut tokens: Vec, root_path: impl AsRef, + context: FxHashMap, ) -> Result, ParsePresetError> { let mut root_path = root_path.as_ref().to_path_buf(); if root_path.is_relative() { @@ -239,7 +256,9 @@ pub fn parse_values( .collect(); // unfortunately we need to lex twice because there's no way to know the references ahead of time. - let child_strings = load_child_reference_strings(references, &root_path)?; + // the returned references should have context applied + + let child_strings = load_child_reference_strings(references, &root_path, &context)?; let mut all_tokens: Vec<(&Path, Vec)> = Vec::new(); for (path, string) in child_strings.iter() { @@ -597,12 +616,13 @@ pub fn parse_values( mod test { use crate::parse::value::parse_preset; use std::path::PathBuf; + use crate::WildcardContext; #[test] pub fn parse_basic() { let root = PathBuf::from("../test/slang-shaders/bezel/Mega_Bezel/Presets/Base_CRT_Presets/MBZ__3__STD__MEGATRON-NTSC.slangp"); - let basic = parse_preset(root); + let basic = parse_preset(root, WildcardContext::new()); eprintln!("{basic:?}"); assert!(basic.is_ok()); } diff --git a/librashader-presets/tests/parse_all.rs b/librashader-presets/tests/parse_all.rs index 01375be..8a65be9 100644 --- a/librashader-presets/tests/parse_all.rs +++ b/librashader-presets/tests/parse_all.rs @@ -1,4 +1,5 @@ use glob::glob; +use librashader_presets::context::{ContextItem, VideoDriver, WildcardContext}; use librashader_presets::ShaderPreset; #[test] @@ -17,3 +18,17 @@ fn parses_problematic() { let path = "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_NDS_DREZ/NDS-[DREZ]-[Native]-[ADV]-[Guest]-[Night].slangp"; ShaderPreset::try_parse(path).expect(&format!("Failed to parse {}", path)); } + +#[test] +fn parses_wildcard() { + let path = + "../test/shaders_slang/bezel/Mega_Bezel/resource/wildcard-examples/Preset-01-Core.slangp"; + let mut context = WildcardContext::new(); + + context.add_video_driver_defaults(VideoDriver::Vulkan); + + context.append_item(ContextItem::CoreName(String::from("image display"))); + + ShaderPreset::try_parse_with_context(path, context) + .expect(&format!("Failed to parse {}", path)); +} diff --git a/librashader-reflect/Cargo.toml b/librashader-reflect/Cargo.toml index 5f8a630..45be105 100644 --- a/librashader-reflect/Cargo.toml +++ b/librashader-reflect/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-reflect" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -19,15 +19,15 @@ thiserror = "1.0.37" bitflags = "2.4.2" rustc-hash = "1.1.0" -librashader-common = { path = "../librashader-common", version = "0.2.0-beta.7" } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } -librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.7" } +librashader-common = { path = "../librashader-common", version = "0.2.0-beta.8" } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } +librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.8" } spirv_cross = { package = "librashader-spirv-cross", version = "0.23", optional = true } naga = { version = "0.19.0", features = ["spv-in", "wgsl-out"], optional = true } -rspirv = { version = "0.12.0+sdk-1.3.268.0", optional = true } -spirv = { version = "0.3.0+sdk-1.3.268.0", optional = true} +rspirv = { version = "0.12.0", optional = true } +spirv = { version = "0.3.0", optional = true} serde = { version = "1.0", features = ["derive"], optional = true } diff --git a/librashader-reflect/src/front/glslang.rs b/librashader-reflect/src/front/glslang.rs index 4527b5a..fd3fa90 100644 --- a/librashader-reflect/src/front/glslang.rs +++ b/librashader-reflect/src/front/glslang.rs @@ -1,5 +1,5 @@ -use glslang::{CompilerOptions, ShaderInput}; use crate::error::ShaderCompileError; +use glslang::{CompilerOptions, ShaderInput}; use librashader_preprocess::ShaderSource; #[cfg(feature = "serialize")] @@ -37,27 +37,17 @@ pub(crate) fn compile_spirv( source_language: glslang::SourceLanguage::GLSL, target: glslang::Target::Vulkan { version: glslang::VulkanVersion::Vulkan1_0, - spirv_version: glslang::SpirvVersion::SPIRV1_0 + spirv_version: glslang::SpirvVersion::SPIRV1_0, }, version_profile: None, }; let vertex = glslang::ShaderSource::from(source.vertex.as_str()); - let vertex = ShaderInput::new( - &vertex, - glslang::ShaderStage::Vertex, - &options, - None, - )?; + let vertex = ShaderInput::new(&vertex, glslang::ShaderStage::Vertex, &options, None)?; let vertex = compiler.create_shader(vertex)?; let fragment = glslang::ShaderSource::from(source.fragment.as_str()); - let fragment = ShaderInput::new( - &fragment, - glslang::ShaderStage::Fragment, - &options, - None, - )?; + let fragment = ShaderInput::new(&fragment, glslang::ShaderStage::Fragment, &options, None)?; let fragment = compiler.create_shader(fragment)?; let vertex = Vec::from(vertex.compile()?); diff --git a/librashader-runtime-d3d11/Cargo.toml b/librashader-runtime-d3d11/Cargo.toml index 7700ffd..4e4a52d 100644 --- a/librashader-runtime-d3d11/Cargo.toml +++ b/librashader-runtime-d3d11/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-runtime-d3d11" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -12,13 +12,13 @@ keywords = ["shader", "retroarch", "SPIR-V"] description = "RetroArch shaders for all." [dependencies] -librashader-common = { path = "../librashader-common", features = ["d3d11"], version = "0.2.0-beta.7" } -librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.7" } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } -librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.7" } -librashader-runtime = { path = "../librashader-runtime", version = "0.2.0-beta.7" } +librashader-common = { path = "../librashader-common", features = ["d3d11"], version = "0.2.0-beta.8" } +librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.8" } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } +librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.8" } +librashader-runtime = { path = "../librashader-runtime", version = "0.2.0-beta.8" } spirv_cross = { package = "librashader-spirv-cross", version = "0.23" } -librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.7", features = ["d3d"] } +librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.8", features = ["d3d"] } thiserror = "1.0.37" rustc-hash = "1.1.0" diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index 0978632..fb3de17 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -24,6 +24,7 @@ use crate::util::d3d11_compile_bound_shader; use crate::{error, util, D3D11OutputView}; use librashader_cache::cache_shader_object; use librashader_cache::CachedCompilation; +use librashader_presets::context::VideoDriver; use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; use librashader_runtime::binding::{BindingUtil, TextureInput}; use librashader_runtime::framebuffer::FramebufferInit; @@ -98,7 +99,7 @@ impl FilterChainD3D11 { options: Option<&FilterChainOptionsD3D11>, ) -> error::Result { // load passes from preset - let preset = ShaderPreset::try_parse(path)?; + let preset = ShaderPreset::try_parse_with_driver_context(path, VideoDriver::Direct3D11)?; unsafe { Self::load_from_preset(preset, device, options) } } diff --git a/librashader-runtime-d3d12/Cargo.toml b/librashader-runtime-d3d12/Cargo.toml index e875a5d..399fd1d 100644 --- a/librashader-runtime-d3d12/Cargo.toml +++ b/librashader-runtime-d3d12/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-runtime-d3d12" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -12,12 +12,12 @@ keywords = ["shader", "retroarch", "SPIR-V"] description = "RetroArch shaders for all." [dependencies] -librashader-common = { path = "../librashader-common", features = ["d3d12"], version = "0.2.0-beta.7" } -librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.7" } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } -librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.7", features = ["dxil"] } -librashader-runtime = { path = "../librashader-runtime", version = "0.2.0-beta.7" } -librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.7", features = ["d3d"] } +librashader-common = { path = "../librashader-common", features = ["d3d12"], version = "0.2.0-beta.8" } +librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.8" } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } +librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.8", features = ["dxil"] } +librashader-runtime = { path = "../librashader-runtime", version = "0.2.0-beta.8" } +librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.8", features = ["d3d"] } thiserror = "1.0.37" spirv_cross = { package = "librashader-spirv-cross", version = "0.23" } diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index 79ec6da..aee5848 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -47,6 +47,7 @@ use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_UNKNOWN; use windows::Win32::System::Threading::{CreateEventA, WaitForSingleObject, INFINITE}; use librashader_cache::CachedCompilation; +use librashader_presets::context::VideoDriver; use librashader_runtime::framebuffer::FramebufferInit; use librashader_runtime::render_target::RenderTarget; use librashader_runtime::scaling::ScaleFramebuffer; @@ -186,7 +187,7 @@ impl FilterChainD3D12 { options: Option<&FilterChainOptionsD3D12>, ) -> error::Result { // load passes from preset - let preset = ShaderPreset::try_parse(path)?; + let preset = ShaderPreset::try_parse_with_driver_context(path, VideoDriver::Direct3D12)?; unsafe { Self::load_from_preset(preset, device, options) } } diff --git a/librashader-runtime-gl/Cargo.toml b/librashader-runtime-gl/Cargo.toml index ceb421f..708cd53 100644 --- a/librashader-runtime-gl/Cargo.toml +++ b/librashader-runtime-gl/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-runtime-gl" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -12,12 +12,12 @@ keywords = ["shader", "retroarch", "SPIR-V"] description = "RetroArch shaders for all." [dependencies] -librashader-common = { path = "../librashader-common", features = ["opengl"], version = "0.2.0-beta.7" } -librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.7" } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } -librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.7" } -librashader-runtime = { path = "../librashader-runtime" , version = "0.2.0-beta.7" } -librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.7" } +librashader-common = { path = "../librashader-common", features = ["opengl"], version = "0.2.0-beta.8" } +librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.8" } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } +librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.8" } +librashader-runtime = { path = "../librashader-runtime" , version = "0.2.0-beta.8" } +librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.8" } spirv_cross = { package = "librashader-spirv-cross", version = "0.23" } rustc-hash = "1.1.0" diff --git a/librashader-runtime-gl/src/filter_chain/mod.rs b/librashader-runtime-gl/src/filter_chain/mod.rs index fce73f0..bfa7407 100644 --- a/librashader-runtime-gl/src/filter_chain/mod.rs +++ b/librashader-runtime-gl/src/filter_chain/mod.rs @@ -14,6 +14,7 @@ mod parameters; pub(crate) use filter_impl::FilterCommon; use librashader_common::Viewport; +use librashader_presets::context::VideoDriver; /// An OpenGL filter chain. pub struct FilterChainGL { @@ -42,10 +43,7 @@ impl FilterChainGL { }), }) }); - match result { - Err(_) => Err(FilterChainError::GLLoadError), - Ok(res) => res, - } + result.unwrap_or_else(|_| Err(FilterChainError::GLLoadError)) } /// Load the shader preset at the given path into a filter chain. @@ -54,7 +52,7 @@ impl FilterChainGL { options: Option<&FilterChainOptionsGL>, ) -> Result { // load passes from preset - let preset = ShaderPreset::try_parse(path)?; + let preset = ShaderPreset::try_parse_with_driver_context(path, VideoDriver::GlCore)?; unsafe { Self::load_from_preset(preset, options) } } diff --git a/librashader-runtime-vk/Cargo.toml b/librashader-runtime-vk/Cargo.toml index c1ff74e..0697944 100644 --- a/librashader-runtime-vk/Cargo.toml +++ b/librashader-runtime-vk/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-runtime-vk" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -14,18 +14,18 @@ description = "RetroArch shaders for all." # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -librashader-common = { path = "../librashader-common", features = ["vulkan"], version = "0.2.0-beta.7" } -librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.7" } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } -librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.7" } -librashader-runtime = { path = "../librashader-runtime" , version = "0.2.0-beta.7" } -librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.7" } +librashader-common = { path = "../librashader-common", features = ["vulkan"], version = "0.2.0-beta.8" } +librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.8" } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } +librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.8" } +librashader-runtime = { path = "../librashader-runtime" , version = "0.2.0-beta.8" } +librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.8" } spirv_cross = { package = "librashader-spirv-cross", version = "0.23" } rustc-hash = "1.1.0" bytemuck = "1.12.3" thiserror = "1.0.37" -ash = { version = "0.37.1+1.3.235", features = ["debug"] } +ash = { version = "0.37", features = ["debug"] } gpu-allocator = { version = "0.22.0", default-features = false, features = ["vulkan"] } parking_lot = "0.12.1" rayon = "1.6.1" diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index ac77cad..c6e751a 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -33,6 +33,7 @@ use std::path::Path; use std::sync::Arc; use librashader_cache::CachedCompilation; +use librashader_presets::context::VideoDriver; use librashader_runtime::framebuffer::FramebufferInit; use librashader_runtime::render_target::RenderTarget; use librashader_runtime::scaling::ScaleFramebuffer; @@ -236,7 +237,7 @@ impl FilterChainVulkan { FilterChainError: From, { // load passes from preset - let preset = ShaderPreset::try_parse(path)?; + let preset = ShaderPreset::try_parse_with_driver_context(path, VideoDriver::Vulkan)?; unsafe { Self::load_from_preset(preset, vulkan, options) } } diff --git a/librashader-runtime-wgpu/Cargo.toml b/librashader-runtime-wgpu/Cargo.toml index b552d48..137b4c2 100644 --- a/librashader-runtime-wgpu/Cargo.toml +++ b/librashader-runtime-wgpu/Cargo.toml @@ -2,7 +2,7 @@ name = "librashader-runtime-wgpu" edition = "2021" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" license = "MPL-2.0 OR GPL-3.0-only" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" @@ -14,11 +14,11 @@ description = "RetroArch shaders for all." # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -librashader-common = { path = "../librashader-common", features = ["wgpu"], version = "0.2.0-beta.7" } -librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.7" } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } -librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.7", features = ["wgsl"], default-features = false } -librashader-runtime = { path = "../librashader-runtime" , version = "0.2.0-beta.7" } +librashader-common = { path = "../librashader-common", features = ["wgpu"], version = "0.2.0-beta.8" } +librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.8" } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } +librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.8", features = ["wgsl"], default-features = false } +librashader-runtime = { path = "../librashader-runtime" , version = "0.2.0-beta.8" } wgpu = { version = "0.19.0", features = ["spirv"] } rustc-hash = "1.1.0" diff --git a/librashader-runtime/Cargo.toml b/librashader-runtime/Cargo.toml index e9112f8..902c24a 100644 --- a/librashader-runtime/Cargo.toml +++ b/librashader-runtime/Cargo.toml @@ -3,7 +3,7 @@ name = "librashader-runtime" edition = "2021" license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -12,10 +12,10 @@ keywords = ["shader", "retroarch", "SPIR-V"] description = "RetroArch shaders for all." [dependencies] -librashader-common = { path = "../librashader-common", version = "0.2.0-beta.7" } -librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.7" } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } -librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.7" } +librashader-common = { path = "../librashader-common", version = "0.2.0-beta.8" } +librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.8" } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } +librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.8" } bytemuck = "1.12.3" rustc-hash = "1.1.0" num-traits = "0.2.15" diff --git a/librashader/Cargo.toml b/librashader/Cargo.toml index 294ca06..d47841b 100644 --- a/librashader/Cargo.toml +++ b/librashader/Cargo.toml @@ -4,7 +4,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html license = "MPL-2.0 OR GPL-3.0-only" -version = "0.2.0-beta.7" +version = "0.2.0-beta.8" authors = ["Ronny Chan "] repository = "https://github.com/SnowflakePowered/librashader" readme = "../README.md" @@ -13,18 +13,18 @@ keywords = ["shader", "retroarch", "SPIR-V"] description = "RetroArch shaders for all." [dependencies] -librashader-common = { path = "../librashader-common", version = "0.2.0-beta.7" } -librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.7" } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.7" } -librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.7" } -librashader-runtime = { path = "../librashader-runtime", version = "0.2.0-beta.7" } -librashader-runtime-d3d11 = { path = "../librashader-runtime-d3d11", version = "0.2.0-beta.7", optional = true } -librashader-runtime-d3d12 = { path = "../librashader-runtime-d3d12", version = "0.2.0-beta.7", optional = true } -librashader-runtime-gl = { path = "../librashader-runtime-gl", version = "0.2.0-beta.7", optional = true } -librashader-runtime-vk = { path = "../librashader-runtime-vk", version = "0.2.0-beta.7", optional = true } -librashader-runtime-wgpu = { path = "../librashader-runtime-wgpu", version = "0.2.0-beta.7", optional = true } +librashader-common = { path = "../librashader-common", version = "0.2.0-beta.8" } +librashader-presets = { path = "../librashader-presets", version = "0.2.0-beta.8" } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-beta.8" } +librashader-reflect = { path = "../librashader-reflect", version = "0.2.0-beta.8" } +librashader-runtime = { path = "../librashader-runtime", version = "0.2.0-beta.8" } +librashader-runtime-d3d11 = { path = "../librashader-runtime-d3d11", version = "0.2.0-beta.8", optional = true } +librashader-runtime-d3d12 = { path = "../librashader-runtime-d3d12", version = "0.2.0-beta.8", optional = true } +librashader-runtime-gl = { path = "../librashader-runtime-gl", version = "0.2.0-beta.8", optional = true } +librashader-runtime-vk = { path = "../librashader-runtime-vk", version = "0.2.0-beta.8", optional = true } +librashader-runtime-wgpu = { path = "../librashader-runtime-wgpu", version = "0.2.0-beta.8", optional = true } -librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.7" } +librashader-cache = { path = "../librashader-cache", version = "0.2.0-beta.8" } ash = { version = "0.37", optional = true } wgpu = { version = "0.19", optional = true } diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index 32ecbdc..431c180 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -228,15 +228,6 @@ pub mod runtime { options::{FilterChainOptionsGL as FilterChainOptions, FrameOptionsGL as FrameOptions}, FilterChainGL as FilterChain, GLFramebuffer, GLImage, }; - - #[doc(hidden)] - #[cfg(feature = "internal")] - /// Re-exports names to deal with C API conflicts. - /// - /// This is internal to librashader-capi and is exempt from semantic versioning. - pub mod capi { - pub use librashader_runtime_gl::*; - } } #[cfg(all(target_os = "windows", feature = "runtime-d3d11"))] @@ -250,15 +241,6 @@ pub mod runtime { }, D3D11InputView, D3D11OutputView, FilterChainD3D11 as FilterChain, }; - - #[doc(hidden)] - #[cfg(feature = "internal")] - /// Re-exports names to deal with C API conflicts. - /// - /// This is internal to librashader-capi and is exempt from semantic versioning. - pub mod capi { - pub use librashader_runtime_d3d11::*; - } } #[cfg(all(target_os = "windows", feature = "runtime-d3d12"))] @@ -272,15 +254,6 @@ pub mod runtime { }, D3D12InputImage, D3D12OutputView, FilterChainD3D12 as FilterChain, }; - - #[doc(hidden)] - #[cfg(feature = "internal")] - /// Re-exports names to deal with C API conflicts. - /// - /// This is internal to librashader-capi and is exempt from semantic versioning. - pub mod capi { - pub use librashader_runtime_d3d12::*; - } } #[cfg(feature = "runtime-vk")] @@ -294,15 +267,6 @@ pub mod runtime { }, FilterChainVulkan as FilterChain, VulkanImage, VulkanInstance, VulkanObjects, }; - - #[doc(hidden)] - #[cfg(feature = "internal")] - /// Re-exports names to deal with C API conflicts. - /// - /// This is internal to librashader-capi and is exempt from semantic versioning. - pub mod capi { - pub use librashader_runtime_vk::*; - } } #[cfg(feature = "runtime-wgpu")] diff --git a/test/capi-tests/librashader-capi-tests/librashader-capi-tests/librashader-capi-tests.cpp b/test/capi-tests/librashader-capi-tests/librashader-capi-tests/librashader-capi-tests.cpp index 044a228..2d09f78 100644 --- a/test/capi-tests/librashader-capi-tests/librashader-capi-tests/librashader-capi-tests.cpp +++ b/test/capi-tests/librashader-capi-tests/librashader-capi-tests/librashader-capi-tests.cpp @@ -15,10 +15,17 @@ int main() std::cout << "Hello World!\n"; std::cout << std::filesystem::current_path() << std::endl; auto instance = librashader_load_instance(); + + libra_preset_ctx_t context; + + instance.preset_ctx_create(&context); + instance.preset_ctx_set_core_name(&context, "Hello"); + libra_shader_preset_t preset; - auto error = instance.preset_create( + auto error = instance.preset_create_with_context( "../../../shaders_slang/border/gameboy-player/" "gameboy-player-crt-royale.slangp", + &context, &preset); /* libra_shader_preset_t preset2; diff --git a/test/shaders_slang b/test/shaders_slang index e04aa57..a4e7902 160000 --- a/test/shaders_slang +++ b/test/shaders_slang @@ -1 +1 @@ -Subproject commit e04aa575febae5927db6b445a3c47b8f4221df78 +Subproject commit a4e79022bb020294f8b155718829e18340364439