diff --git a/README.md b/README.md index a81de24..003f547 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,13 @@ The librashader C API is best used by linking statically with `librashader_ld`, loads the librashader (`librashader.so` or `librashader.dll`) implementation in the search path. ### Building +Some downstream dependencies require some Python dependencies to build. -For Rust projects, simply add the crate to your `Cargo.toml`. Python may also be required to build some dependent libraries. +``` +pip install meson ninja mako +``` + +For Rust projects, simply add the crate to your `Cargo.toml`. ``` cargo add librashader @@ -106,7 +111,7 @@ Please report an issue if you run into a shader that works in RetroArch, but not * All caveats from the OpenGL 3.3+ section should be considered. * Should work on OpenGL 4.5 but this is not guaranteed. The OpenGL 4.6 runtime may eventually switch to using `ARB_spirv_extensions` for loading shaders, and this will not be marked as a breaking change. * The OpenGL 4.6 runtime uses Direct State Access to minimize changes to the OpenGL state. For GPUs released within the last 5 years, this may improve performance. - * Vulkan 1.3+ + * Vulkan * The Vulkan runtime uses [`VK_KHR_dynamic_rendering`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_dynamic_rendering.html) by default. This extension must be enabled at device creation. Explicit render passes can be used by configuring filter chain options, but may have reduced performance compared to dynamic rendering. diff --git a/include/librashader.h b/include/librashader.h index 5becfe3..da05007 100644 --- a/include/librashader.h +++ b/include/librashader.h @@ -50,6 +50,14 @@ typedef void* VkPhysicalDevice; typedef void* VkInstance; typedef void* VkCommandBuffer; #endif +#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D12) +#include +#else +typedef void ID3D12GraphicsCommandList; +typedef void ID3D12Device; +typedef void ID3D12Resource; +typedef void D3D12_CPU_DESCRIPTOR_HANDLE; +#endif /// Error codes for librashader error types. @@ -74,6 +82,9 @@ typedef int32_t LIBRA_ERRNO; /// A Direct3D 11 filter chain. typedef struct _filter_chain_d3d11 _filter_chain_d3d11; +/// A Direct3D 12 filter chain. +typedef struct _filter_chain_d3d12 _filter_chain_d3d12; + /// An OpenGL filter chain. typedef struct _filter_chain_gl _filter_chain_gl; @@ -184,47 +195,11 @@ typedef struct libra_draw_framebuffer_gl_t { typedef struct frame_gl_opt_t { /// Whether or not to clear the history buffers. bool clear_history; - /// The direction of the frame. 1 should be vertical. + /// The direction of rendering. + /// -1 indicates that the frames are played in reverse order. int32_t frame_direction; } frame_gl_opt_t; -/// Options for Direct3D11 filter chain creation. -typedef struct filter_chain_d3d11_opt_t { - /// Use a deferred context to record shader rendering state. - /// - /// The deferred context will be executed on the immediate context - /// with `RenderContextState = true`. - bool use_deferred_context; - /// Whether or not to explicitly disable mipmap - /// generation regardless of shader preset settings. - bool force_no_mipmaps; -} filter_chain_d3d11_opt_t; - -#if defined(LIBRA_RUNTIME_D3D11) -/// A handle to a Direct3D11 filter chain. -typedef struct _filter_chain_d3d11 *libra_d3d11_filter_chain_t; -#endif - -#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 - const 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 - -/// Options for each Direct3D11 shader frame. -typedef struct frame_d3d11_opt_t { - /// Whether or not to clear the history buffers. - bool clear_history; - /// The direction of the frame. 1 should be vertical. - int32_t frame_direction; -} frame_d3d11_opt_t; - #if defined(LIBRA_RUNTIME_VULKAN) /// Handles required to instantiate vulkan typedef struct libra_device_vk_t { @@ -276,10 +251,89 @@ typedef struct libra_image_vk_t { typedef struct frame_vk_opt_t { /// Whether or not to clear the history buffers. bool clear_history; - /// The direction of the frame. 1 should be vertical. + /// The direction of rendering. + /// -1 indicates that the frames are played in reverse order. int32_t frame_direction; } frame_vk_opt_t; +/// Options for Direct3D11 filter chain creation. +typedef struct filter_chain_d3d11_opt_t { + /// Use a deferred context to record shader rendering state. + /// + /// The deferred context will be executed on the immediate context + /// with `RenderContextState = true`. + bool use_deferred_context; + /// Whether or not to explicitly disable mipmap + /// generation regardless of shader preset settings. + bool force_no_mipmaps; +} filter_chain_d3d11_opt_t; + +#if defined(LIBRA_RUNTIME_D3D11) +/// A handle to a Direct3D 11 filter chain. +typedef struct _filter_chain_d3d11 *libra_d3d11_filter_chain_t; +#endif + +#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 + const 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 + +/// Options for each Direct3D11 shader frame. +typedef struct frame_d3d11_opt_t { + /// 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; + +/// Options for Direct3D11 filter chain creation. +typedef struct filter_chain_d3d12_opt_t { + /// 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; +} filter_chain_d3d12_opt_t; + +#if defined(LIBRA_RUNTIME_D3D12) +/// A handle to a Direct3D 12 filter chain. +typedef struct _filter_chain_d3d12 *libra_d3d12_filter_chain_t; +#endif + +#if defined(LIBRA_RUNTIME_D3D12) +/// Direct3D 11 parameters for the source image. +typedef struct libra_source_image_d3d12_t { + /// The resource containing the image. + const 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 + +/// Options for each Direct3D11 shader frame. +typedef struct frame_d3d12_opt_t { + /// 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; + /// Function pointer definition for ///libra_preset_create typedef libra_error_t (*PFN_libra_preset_create)(const char *filename, libra_shader_preset_t *out); @@ -390,6 +444,64 @@ typedef libra_error_t (*PFN_libra_gl_filter_chain_get_active_pass_count)(libra_g 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)(struct libra_device_vk_t vulkan, + libra_shader_preset_t *preset, + const struct filter_chain_vk_opt_t *options, + libra_vk_filter_chain_t *out); +#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_image_vk_t image, + struct libra_viewport_t viewport, + struct libra_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); +#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); +#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); +#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); +#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); +#endif + #if defined(LIBRA_RUNTIME_D3D11) /// Function pointer definition for ///libra_d3d11_filter_chain_create @@ -447,62 +559,62 @@ typedef libra_error_t (*PFN_libra_d3d11_filter_chain_get_active_pass_count)(libr typedef libra_error_t (*PFN_libra_d3d11_filter_chain_free)(libra_d3d11_filter_chain_t *chain); #endif -#if defined(LIBRA_RUNTIME_VULKAN) +#if defined(LIBRA_RUNTIME_D3D12) /// Function pointer definition for -///libra_vk_filter_chain_create -typedef libra_error_t (*PFN_libra_vk_filter_chain_create)(struct libra_device_vk_t vulkan, - libra_shader_preset_t *preset, - const struct filter_chain_vk_opt_t *options, - libra_vk_filter_chain_t *out); +///libra_d3d12_filter_chain_create +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_create)(libra_shader_preset_t *preset, + const struct filter_chain_d3d12_opt_t *options, + const ID3D12Device * device, + libra_d3d12_filter_chain_t *out); #endif -#if defined(LIBRA_RUNTIME_VULKAN) +#if defined(LIBRA_RUNTIME_D3D12) /// 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_image_vk_t image, - struct libra_viewport_t viewport, - struct libra_image_vk_t out, - const float *mvp, - const struct frame_vk_opt_t *opt); +///libra_d3d12_filter_chain_frame +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_frame)(libra_d3d12_filter_chain_t *chain, + const ID3D12GraphicsCommandList * command_list, + size_t frame_count, + struct libra_source_image_d3d12_t image, + struct libra_viewport_t viewport, + D3D12_CPU_DESCRIPTOR_HANDLE out, + const float *mvp, + const struct frame_d3d12_opt_t *opt); #endif -#if defined(LIBRA_RUNTIME_VULKAN) +#if defined(LIBRA_RUNTIME_D3D12) /// 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_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_VULKAN) +#if defined(LIBRA_RUNTIME_D3D12) /// 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_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_VULKAN) +#if defined(LIBRA_RUNTIME_D3D12) /// 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_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_VULKAN) +#if defined(LIBRA_RUNTIME_D3D12) /// 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_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_VULKAN) +#if defined(LIBRA_RUNTIME_D3D12) /// 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_d3d12_filter_chain_free +typedef libra_error_t (*PFN_libra_d3d12_filter_chain_free)(libra_d3d12_filter_chain_t *chain); #endif #ifdef __cplusplus @@ -721,95 +833,6 @@ libra_error_t libra_gl_filter_chain_get_active_pass_count(libra_gl_filter_chain_ libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t *chain); #endif -#if defined(LIBRA_RUNTIME_D3D11) -/// Create the filter chain given the shader preset. -/// -/// The shader preset is immediately invalidated and must be recreated after -/// the filter chain is created. -/// -/// ## Safety: -/// - `preset` must be either null, or valid and aligned. -/// - `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, - const struct filter_chain_d3d11_opt_t *options, - const ID3D11Device * device, - libra_d3d11_filter_chain_t *out); -#endif - -#if defined(LIBRA_RUNTIME_D3D11) -/// 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 -/// function will return an error. -/// - `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` -/// struct. -/// - `out` must not be null. -/// - `image.handle` must not be null. -libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain, - size_t frame_count, - struct libra_source_image_d3d11_t image, - struct libra_viewport_t viewport, - const ID3D11RenderTargetView * out, - const float *mvp, - const struct frame_d3d11_opt_t *opt); -#endif - -#if defined(LIBRA_RUNTIME_D3D11) -/// Sets a parameter for the filter 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`. -/// - `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); -#endif - -#if defined(LIBRA_RUNTIME_D3D11) -/// Gets a parameter for the filter 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`. -/// - `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); -#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); -#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); -#endif - -#if defined(LIBRA_RUNTIME_D3D11) -/// Free a D3D11 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_d3d11_filter_chain_t`. -libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain); -#endif - #if defined(LIBRA_RUNTIME_VULKAN) /// Create the filter chain given the shader preset. /// @@ -905,6 +928,187 @@ libra_error_t libra_vk_filter_chain_get_active_pass_count(libra_vk_filter_chain_ libra_error_t libra_vk_filter_chain_free(libra_vk_filter_chain_t *chain); #endif +#if defined(LIBRA_RUNTIME_D3D11) +/// Create the filter chain given the shader preset. +/// +/// The shader preset is immediately invalidated and must be recreated after +/// the filter chain is created. +/// +/// ## Safety: +/// - `preset` must be either null, or valid and aligned. +/// - `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, + const struct filter_chain_d3d11_opt_t *options, + const ID3D11Device * device, + libra_d3d11_filter_chain_t *out); +#endif + +#if defined(LIBRA_RUNTIME_D3D11) +/// 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 +/// function will return an error. +/// - `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` +/// struct. +/// - `out` must not be null. +/// - `image.handle` must not be null. +libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain, + size_t frame_count, + struct libra_source_image_d3d11_t image, + struct libra_viewport_t viewport, + const ID3D11RenderTargetView * out, + const float *mvp, + const struct frame_d3d11_opt_t *opt); +#endif + +#if defined(LIBRA_RUNTIME_D3D11) +/// Sets a parameter for the filter 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`. +/// - `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); +#endif + +#if defined(LIBRA_RUNTIME_D3D11) +/// Gets a parameter for the filter 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`. +/// - `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); +#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); +#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); +#endif + +#if defined(LIBRA_RUNTIME_D3D11) +/// Free a D3D11 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_d3d11_filter_chain_t`. +libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain); +#endif + +#if defined(LIBRA_RUNTIME_D3D12) +/// Create the filter chain given the shader preset. +/// +/// The shader preset is immediately invalidated and must be recreated after +/// the filter chain is created. +/// +/// ## Safety: +/// - `preset` must be either null, or valid and aligned. +/// - `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, + const struct filter_chain_d3d12_opt_t *options, + const ID3D12Device * device, + 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. +/// +/// ## Safety +/// - `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` +/// 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` +/// struct. +/// - `out` must be a descriptor handle to a render target view. +/// - `image.resource` must not be null. +/// - `command_list` must not be null. +libra_error_t libra_d3d12_filter_chain_frame(libra_d3d12_filter_chain_t *chain, + const ID3D12GraphicsCommandList * command_list, + size_t frame_count, + struct libra_source_image_d3d12_t image, + struct libra_viewport_t viewport, + D3D12_CPU_DESCRIPTOR_HANDLE out, + const float *mvp, + const struct frame_d3d12_opt_t *opt); +#endif + +#if defined(LIBRA_RUNTIME_D3D12) +/// Sets a parameter for the filter 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`. +/// - `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); +#endif + +#if defined(LIBRA_RUNTIME_D3D12) +/// Gets a parameter for the filter 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`. +/// - `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); +#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); +#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); +#endif + +#if defined(LIBRA_RUNTIME_D3D12) +/// Free a D3D12 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_d3d12_filter_chain_t`. +libra_error_t libra_d3d12_filter_chain_free(libra_d3d12_filter_chain_t *chain); +#endif + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/include/librashader_ld.h b/include/librashader_ld.h index 49bd9c9..c3ea955 100644 --- a/include/librashader_ld.h +++ b/include/librashader_ld.h @@ -151,6 +151,47 @@ libra_error_t __librashader__noop_gl_filter_chain_get_active_pass_count( } #endif +#if defined(LIBRA_RUNTIME_VULKAN) +libra_error_t __librashader__noop_vk_filter_chain_create( + struct libra_device_vk_t vulkan, libra_shader_preset_t *preset, + const struct filter_chain_vk_opt_t *options, libra_vk_filter_chain_t *out) { + return NULL; +} + +libra_error_t __librashader__noop_vk_filter_chain_frame( + libra_vk_filter_chain_t *chain, VkCommandBuffer command_buffer, + size_t frame_count, struct libra_image_vk_t image, + struct libra_viewport_t viewport, struct libra_image_vk_t out, + const float *mvp, const struct frame_vk_opt_t *opt) { + return NULL; +} + +libra_error_t __librashader__noop_vk_filter_chain_free( + libra_vk_filter_chain_t *chain) { + return NULL; +} + +libra_error_t __librashader__noop_vk_filter_chain_set_param( + libra_vk_filter_chain_t *chain, const char *param_name, float value) { + return NULL; +} + +libra_error_t __librashader__noop_vk_filter_chain_get_param( + libra_vk_filter_chain_t *chain, const char *param_name, float *out) { + return NULL; +} + +libra_error_t __librashader__noop_vk_filter_chain_set_active_pass_count( + libra_vk_filter_chain_t *chain, uint32_t value) { + return NULL; +} + +libra_error_t __librashader__noop_vk_filter_chain_get_active_pass_count( + libra_vk_filter_chain_t *chain, uint32_t *out) { + return NULL; +} +#endif + #if defined(LIBRA_RUNTIME_D3D11) libra_error_t __librashader__noop_d3d11_filter_chain_create( libra_shader_preset_t *preset, @@ -191,51 +232,51 @@ libra_error_t __librashader__noop_d3d11_filter_chain_get_active_pass_count( libra_d3d11_filter_chain_t *chain, uint32_t *out) { return NULL; } - #endif -#if defined(LIBRA_RUNTIME_VULKAN) -libra_error_t __librashader__noop_vk_filter_chain_create( - struct libra_device_vk_t vulkan, libra_shader_preset_t *preset, - const struct filter_chain_vk_opt_t *options, libra_vk_filter_chain_t *out) { + +#if defined(LIBRA_RUNTIME_D3D12) +libra_error_t __librashader__noop_d3d12_filter_chain_create( + libra_shader_preset_t *preset, + const struct filter_chain_d3d12_opt_t *options, const ID3D12Device *device, + libra_d3d12_filter_chain_t *out) { return NULL; } -libra_error_t __librashader__noop_vk_filter_chain_frame( - libra_vk_filter_chain_t *chain, VkCommandBuffer command_buffer, - size_t frame_count, struct libra_image_vk_t image, - struct libra_viewport_t viewport, struct libra_image_vk_t out, - const float *mvp, const struct frame_vk_opt_t *opt) { +libra_error_t __librashader__noop_d3d12_filter_chain_frame( + libra_d3d12_filter_chain_t *chain, + const ID3D12GraphicsCommandList *command_list, size_t frame_count, + struct libra_source_image_d3d12_t image, struct libra_viewport_t viewport, + D3D12_CPU_DESCRIPTOR_HANDLE out, const float *mvp, + const struct frame_d3d12_opt_t *opt) { return NULL; } -libra_error_t __librashader__noop_vk_filter_chain_free( - libra_vk_filter_chain_t *chain) { +libra_error_t __librashader__noop_d3d12_filter_chain_free( + libra_d3d12_filter_chain_t *chain) { return NULL; } -libra_error_t __librashader__noop_vk_filter_chain_set_param( - libra_vk_filter_chain_t *chain, const char *param_name, float value) { +libra_error_t __librashader__noop_d3d12_filter_chain_set_param( + libra_d3d12_filter_chain_t *chain, const char *param_name, float value) { return NULL; } -libra_error_t __librashader__noop_vk_filter_chain_get_param( - libra_vk_filter_chain_t *chain, const char *param_name, float *out) { +libra_error_t __librashader__noop_d3d12_filter_chain_get_param( + libra_d3d12_filter_chain_t *chain, const char *param_name, float *out) { return NULL; } -libra_error_t __librashader__noop_vk_filter_chain_set_active_pass_count( - libra_vk_filter_chain_t *chain, uint32_t value) { +libra_error_t __librashader__noop_d3d12_filter_chain_set_active_pass_count( + libra_d3d12_filter_chain_t *chain, uint32_t value) { return NULL; } -libra_error_t __librashader__noop_vk_filter_chain_get_active_pass_count( - libra_vk_filter_chain_t *chain, uint32_t *out) { +libra_error_t __librashader__noop_d3d12_filter_chain_get_active_pass_count( + libra_d3d12_filter_chain_t *chain, uint32_t *out) { return NULL; } - #endif - typedef struct libra_instance_t { /// Load a preset. /// @@ -446,76 +487,6 @@ typedef struct libra_instance_t { PFN_libra_gl_filter_chain_set_param gl_filter_chain_set_param; #endif -#if defined(LIBRA_RUNTIME_D3D11) - /// Create the filter chain given the shader preset. - /// - /// The shader preset is immediately invalidated and must be recreated after - /// the filter chain is created. - /// - /// ## Safety: - /// - `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. - PFN_libra_d3d11_filter_chain_create d3d11_filter_chain_create; - - /// 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 - /// function will return an error. - /// - `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` - /// struct. - PFN_libra_d3d11_filter_chain_frame d3d11_filter_chain_frame; - - - /// Free a D3D11 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_d3d11_filter_chain_t`. - PFN_libra_d3d11_filter_chain_free d3d11_filter_chain_free; - - /// 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`. - PFN_libra_d3d11_filter_chain_get_active_pass_count - d3d11_filter_chain_get_active_pass_count; - - /// 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`. - PFN_libra_d3d11_filter_chain_set_active_pass_count - d3d11_filter_chain_set_active_pass_count; - - /// Gets a parameter for the filter 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`. - /// - `param_name` must be either null or a null terminated string. - PFN_libra_d3d11_filter_chain_get_param d3d11_filter_chain_get_param; - - /// Sets a parameter for the filter 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`. - /// - `param_name` must be either null or a null terminated string. - PFN_libra_d3d11_filter_chain_set_param d3d11_filter_chain_set_param; -#endif - #if defined(LIBRA_RUNTIME_VULKAN) /// Create the filter chain given the shader preset. /// @@ -597,8 +568,149 @@ typedef struct libra_instance_t { /// - `param_name` must be either null or a null terminated string. PFN_libra_vk_filter_chain_set_param vk_filter_chain_set_param; #endif + +#if defined(LIBRA_RUNTIME_D3D11) + /// Create the filter chain given the shader preset. + /// + /// The shader preset is immediately invalidated and must be recreated after + /// the filter chain is created. + /// + /// ## Safety: + /// - `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. + PFN_libra_d3d11_filter_chain_create d3d11_filter_chain_create; + + /// 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 + /// function will return an error. + /// - `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` + /// struct. + PFN_libra_d3d11_filter_chain_frame d3d11_filter_chain_frame; + + /// Free a D3D11 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_d3d11_filter_chain_t`. + PFN_libra_d3d11_filter_chain_free d3d11_filter_chain_free; + + /// 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`. + PFN_libra_d3d11_filter_chain_get_active_pass_count + d3d11_filter_chain_get_active_pass_count; + + /// 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`. + PFN_libra_d3d11_filter_chain_set_active_pass_count + d3d11_filter_chain_set_active_pass_count; + + /// Gets a parameter for the filter 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`. + /// - `param_name` must be either null or a null terminated string. + PFN_libra_d3d11_filter_chain_get_param d3d11_filter_chain_get_param; + + /// Sets a parameter for the filter 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`. + /// - `param_name` must be either null or a null terminated string. + 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. + /// + /// The shader preset is immediately invalidated and must be recreated after + /// the filter chain is created. + /// + /// ## Safety: + /// - `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. + PFN_libra_d3d12_filter_chain_create d3d12_filter_chain_create; + + /// 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 + /// function will return an error. + /// - `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` + /// struct. + PFN_libra_d3d12_filter_chain_frame d3d12_filter_chain_frame; + + /// Free a D3D11 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_d3d12_filter_chain_t`. + PFN_libra_d3d12_filter_chain_free d3d12_filter_chain_free; + + /// 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`. + PFN_libra_d3d12_filter_chain_get_active_pass_count + d3d12_filter_chain_get_active_pass_count; + + /// 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`. + PFN_libra_d3d12_filter_chain_set_active_pass_count + d3d12_filter_chain_set_active_pass_count; + + /// Gets a parameter for the filter 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`. + /// - `param_name` must be either null or a null terminated string. + PFN_libra_d3d12_filter_chain_get_param d3d12_filter_chain_get_param; + + /// Sets a parameter for the filter 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`. + /// - `param_name` must be either null or a null terminated string. + PFN_libra_d3d12_filter_chain_set_param d3d12_filter_chain_set_param; +#endif } libra_instance_t; + + libra_instance_t __librashader_make_null_instance() { return libra_instance_t { .preset_create = __librashader__noop_preset_create, @@ -632,6 +744,20 @@ libra_instance_t __librashader_make_null_instance() { __librashader__noop_gl_filter_chain_set_param, #endif +#if defined(LIBRA_RUNTIME_VULKAN) + .vk_filter_chain_create = __librashader__noop_vk_filter_chain_create, + .vk_filter_chain_frame = __librashader__noop_vk_filter_chain_frame, + .vk_filter_chain_free = __librashader__noop_vk_filter_chain_free, + .vk_filter_chain_get_active_pass_count = + __librashader__noop_vk_filter_chain_get_active_pass_count, + .vk_filter_chain_set_active_pass_count = + __librashader__noop_vk_filter_chain_set_active_pass_count, + .vk_filter_chain_get_param = + __librashader__noop_vk_filter_chain_get_param, + .vk_filter_chain_set_param = + __librashader__noop_vk_filter_chain_set_param, +#endif + #if defined(LIBRA_RUNTIME_D3D11) .d3d11_filter_chain_create = __librashader__noop_d3d11_filter_chain_create, @@ -648,19 +774,21 @@ libra_instance_t __librashader_make_null_instance() { __librashader__noop_d3d11_filter_chain_set_param, #endif -#if defined(LIBRA_RUNTIME_VULKAN) - .vk_filter_chain_create = __librashader__noop_vk_filter_chain_create, - .vk_filter_chain_frame = __librashader__noop_vk_filter_chain_frame, - .vk_filter_chain_free = __librashader__noop_vk_filter_chain_free, - .vk_filter_chain_get_active_pass_count = - __librashader__noop_vk_filter_chain_get_active_pass_count, - .vk_filter_chain_set_active_pass_count = - __librashader__noop_vk_filter_chain_set_active_pass_count, - .vk_filter_chain_get_param = - __librashader__noop_vk_filter_chain_get_param, - .vk_filter_chain_set_param = - __librashader__noop_vk_filter_chain_set_param, -#endif +#if defined(LIBRA_RUNTIME_D3D12) + .d3d12_filter_chain_create = + __librashader__noop_d3d12_filter_chain_create, + .d3d12_filter_chain_frame = + __librashader__noop_d3d12_filter_chain_frame, + .d3d12_filter_chain_free = __librashader__noop_d3d12_filter_chain_free, + .d3d12_filter_chain_get_active_pass_count = + __librashader__noop_d3d12_filter_chain_get_active_pass_count, + .d3d12_filter_chain_set_active_pass_count = + __librashader__noop_d3d12_filter_chain_set_active_pass_count, + .d3d12_filter_chain_get_param = + __librashader__noop_d3d12_filter_chain_get_param, + .d3d12_filter_chain_set_param = + __librashader__noop_d3d12_filter_chain_set_param, +#endif }; } @@ -718,22 +846,6 @@ libra_instance_t librashader_load_instance() { #endif -#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D11) - _LIBRASHADER_ASSIGN(librashader, instance, - d3d11_filter_chain_create); - _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); - _LIBRASHADER_ASSIGN(librashader, instance, - d3d11_filter_chain_set_param); - _LIBRASHADER_ASSIGN(librashader, instance, - d3d11_filter_chain_get_active_pass_count); - _LIBRASHADER_ASSIGN(librashader, instance, - d3d11_filter_chain_set_active_pass_count); -#endif - #if defined(LIBRA_RUNTIME_VULKAN) _LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_create); _LIBRASHADER_ASSIGN(librashader, instance, vk_filter_chain_frame); @@ -748,6 +860,29 @@ libra_instance_t librashader_load_instance() { 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_frame); + _LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_free); + _LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_get_param); + _LIBRASHADER_ASSIGN(librashader, instance, d3d11_filter_chain_set_param); + _LIBRASHADER_ASSIGN(librashader, instance, + d3d11_filter_chain_get_active_pass_count); + _LIBRASHADER_ASSIGN(librashader, instance, + d3d11_filter_chain_set_active_pass_count); +#endif + +#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D12) + _LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_create); + _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); + _LIBRASHADER_ASSIGN(librashader, instance, d3d12_filter_chain_set_param); + _LIBRASHADER_ASSIGN(librashader, instance, + d3d12_filter_chain_get_active_pass_count); + _LIBRASHADER_ASSIGN(librashader, instance, + d3d12_filter_chain_set_active_pass_count); +#endif return instance; } #else diff --git a/librashader-capi/Cargo.toml b/librashader-capi/Cargo.toml index 787cdc8..1e12061 100644 --- a/librashader-capi/Cargo.toml +++ b/librashader-capi/Cargo.toml @@ -15,9 +15,10 @@ description = "RetroArch shaders for all." crate-type = [ "cdylib", "staticlib" ] [features] -default = ["runtime-opengl", "runtime-d3d11", "runtime-vulkan"] +default = ["runtime-opengl", "runtime-d3d11", "runtime-d3d12", "runtime-vulkan"] runtime-opengl = ["gl", "librashader/gl"] -runtime-d3d11 = ["windows", "librashader/d3d11"] +runtime-d3d11 = ["windows", "librashader/d3d11", "windows/Win32_Graphics_Direct3D11"] +runtime-d3d12 = ["windows", "librashader/d3d12", "windows/Win32_Graphics_Direct3D12"] runtime-vulkan = ["ash", "librashader/vk"] [dependencies] @@ -31,9 +32,6 @@ spirv_cross = { package = "librashader-spirv-cross", version = "0.23" } [target.'cfg(windows)'.dependencies.windows] version = "0.44.0" -features = [ - "Win32_Graphics_Direct3D11", -] optional = true [package.metadata.cargo-post.dependencies] diff --git a/librashader-capi/cbindgen.toml b/librashader-capi/cbindgen.toml index eb1d15e..2c994be 100644 --- a/librashader-capi/cbindgen.toml +++ b/librashader-capi/cbindgen.toml @@ -48,12 +48,21 @@ typedef void* VkPhysicalDevice; typedef void* VkInstance; typedef void* VkCommandBuffer; #endif +#if defined(_WIN32) && defined(LIBRA_RUNTIME_D3D12) +#include +#else +typedef void ID3D12GraphicsCommandList; +typedef void ID3D12Device; +typedef void ID3D12Resource; +typedef void D3D12_CPU_DESCRIPTOR_HANDLE; +#endif """ [defines] "feature = runtime-opengl" = "LIBRA_RUNTIME_OPENGL" -"feature = runtime-d3d11" = "LIBRA_RUNTIME_D3D11" "feature = runtime-vulkan" = "LIBRA_RUNTIME_VULKAN" +"feature = runtime-d3d11" = "LIBRA_RUNTIME_D3D11" +"feature = runtime-d3d12" = "LIBRA_RUNTIME_D3D12" [parse] parse_deps = true @@ -62,8 +71,9 @@ include = ["librashader", "librashader-preprocess", "librashader-reflect", "librashader-runtime-gl", - "librashader-runtime-d3d11", "librashader-runtime-vk", + "librashader-runtime-d3d11", + "librashader-runtime-d3d12", ] expand = ["librashader-capi"] @@ -101,6 +111,15 @@ include = [ "PFN_libra_gl_filter_chain_get_active_pass_count", "PFN_libra_gl_filter_chain_free", + # vulkan + "PFN_libra_vk_filter_chain_create", + "PFN_libra_vk_filter_chain_frame", + "PFN_libra_vk_filter_chain_set_param", + "PFN_libra_vk_filter_chain_get_param", + "PFN_libra_vk_filter_chain_set_active_pass_count", + "PFN_libra_vk_filter_chain_get_active_pass_count", + "PFN_libra_vk_filter_chain_free", + # d3d11 "PFN_libra_d3d11_filter_chain_create", "PFN_libra_d3d11_filter_chain_frame", @@ -110,14 +129,15 @@ include = [ "PFN_libra_d3d11_filter_chain_get_active_pass_count", "PFN_libra_d3d11_filter_chain_free", - # vulkan - "PFN_libra_vk_filter_chain_create", - "PFN_libra_vk_filter_chain_frame", - "PFN_libra_vk_filter_chain_set_param", - "PFN_libra_vk_filter_chain_get_param", - "PFN_libra_vk_filter_chain_set_active_pass_count", - "PFN_libra_vk_filter_chain_get_active_pass_count", - "PFN_libra_vk_filter_chain_free", + + # d3d11 + "PFN_libra_d3d12_filter_chain_create", + "PFN_libra_d3d12_filter_chain_frame", + "PFN_libra_d3d12_filter_chain_set_param", + "PFN_libra_d3d12_filter_chain_get_param", + "PFN_libra_d3d12_filter_chain_set_active_pass_count", + "PFN_libra_d3d12_filter_chain_get_active_pass_count", + "PFN_libra_d3d12_filter_chain_free", ] [export.rename] @@ -126,12 +146,15 @@ include = [ "FilterChainGL" = "_filter_chain_gl" "FilterChainOptionsGL" = "filter_chain_gl_opt_t" "FrameOptionsGL" = "frame_gl_opt_t" -"FilterChainD3D11" = "_filter_chain_d3d11" -"FilterChainOptionsD3D11" = "filter_chain_d3d11_opt_t" -"FrameOptionsD3D11" = "frame_d3d11_opt_t" "FilterChainVulkan" = "_filter_chain_vk" "FilterChainOptionsVulkan" = "filter_chain_vk_opt_t" "FrameOptionsVulkan" = "frame_vk_opt_t" +"FilterChainD3D11" = "_filter_chain_d3d11" +"FilterChainOptionsD3D11" = "filter_chain_d3d11_opt_t" +"FrameOptionsD3D11" = "frame_d3d11_opt_t" +"FilterChainD3D12" = "_filter_chain_d3d12" +"FilterChainOptionsD3D12" = "filter_chain_d3d12_opt_t" +"FrameOptionsD3D12" = "frame_d3d12_opt_t" # vulkan renames "PhysicalDevice" = "VkPhysicalDevice" @@ -144,4 +167,9 @@ include = [ #hack to get proper pointer indirection for COM pointers "ID3D11Device" = "const ID3D11Device *" "ID3D11RenderTargetView" = "const ID3D11RenderTargetView *" -"ID3D11ShaderResourceView" = "const ID3D11ShaderResourceView *" \ No newline at end of file +"ID3D11ShaderResourceView" = "const ID3D11ShaderResourceView *" + +#hack to get proper pointer indirection for COM pointers +"ID3D12Device" = "const ID3D12Device *" +"ID3D12Resource" = "const ID3D12Resource *" +"ID3D12GraphicsCommandList" = "const ID3D12GraphicsCommandList *" \ No newline at end of file diff --git a/librashader-capi/src/ctypes.rs b/librashader-capi/src/ctypes.rs index 9c82a45..dad8b62 100644 --- a/librashader-capi/src/ctypes.rs +++ b/librashader-capi/src/ctypes.rs @@ -14,12 +14,19 @@ pub type libra_error_t = Option>; #[doc(cfg(feature = "runtime-opengl"))] pub type libra_gl_filter_chain_t = Option>; -/// A handle to a Direct3D11 filter chain. +/// 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>; +/// 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>; + + /// A handle to a Vulkan filter chain. #[cfg(feature = "runtime-vulkan")] #[doc(cfg(feature = "runtime-vulkan"))] diff --git a/librashader-capi/src/error.rs b/librashader-capi/src/error.rs index 78971e5..9f04b52 100644 --- a/librashader-capi/src/error.rs +++ b/librashader-capi/src/error.rs @@ -33,6 +33,10 @@ pub enum LibrashaderError { #[doc(cfg(all(target_os = "windows", feature = "runtime-d3d11")))] #[error("There was an error in the D3D11 filter chain.")] D3D11FilterError(#[from] librashader::runtime::d3d11::error::FilterChainError), + #[cfg(all(target_os = "windows", feature = "runtime-d3d12"))] + #[doc(cfg(all(target_os = "windows", feature = "runtime-d3d12")))] + #[error("There was an error in the D3D12 filter chain.")] + D3D12FilterError(#[from] librashader::runtime::d3d12::error::FilterChainError), #[cfg(feature = "runtime-vulkan")] #[doc(cfg(feature = "runtime-vulkan"))] #[error("There was an error in the Vulkan filter chain.")] @@ -183,6 +187,8 @@ impl LibrashaderError { LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, #[cfg(all(target_os = "windows", feature = "runtime-d3d11"))] LibrashaderError::D3D11FilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, + #[cfg(all(target_os = "windows", feature = "runtime-d3d12"))] + LibrashaderError::D3D12FilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, #[cfg(feature = "runtime-vulkan")] LibrashaderError::VulkanFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, } @@ -211,14 +217,6 @@ macro_rules! assert_non_null { }; } -// macro_rules! assert_some { -// ($value:ident) => { -// if $value.is_none() { -// return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export(); -// } -// }; -// } - macro_rules! assert_some_ptr { ($value:ident) => { if $value.is_none() { diff --git a/librashader-capi/src/runtime/d3d11/mod.rs b/librashader-capi/src/runtime/d3d11/mod.rs index da14d61..7db6582 100644 --- a/librashader-capi/src/runtime/d3d11/mod.rs +++ b/librashader-capi/src/runtime/d3d11/mod.rs @@ -1,4 +1,4 @@ -//! C API for the librashader OpenGL Runtime (`libra_d3d11_*`) +//! C API for the librashader D3D12 Runtime (`libra_d3d11_*`) mod filter_chain; pub use filter_chain::*; diff --git a/librashader-capi/src/runtime/d3d12/filter_chain.rs b/librashader-capi/src/runtime/d3d12/filter_chain.rs new file mode 100644 index 0000000..a8b86b2 --- /dev/null +++ b/librashader-capi/src/runtime/d3d12/filter_chain.rs @@ -0,0 +1,239 @@ +use crate::ctypes::{libra_d3d12_filter_chain_t, libra_shader_preset_t, libra_viewport_t}; +use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError}; +use crate::ffi::extern_fn; +use std::ffi::c_char; +use std::ffi::CStr; +use std::mem::{ManuallyDrop, MaybeUninit}; +use std::ptr::NonNull; +use std::slice; +use windows::Win32::Graphics::Direct3D12::{D3D12_CPU_DESCRIPTOR_HANDLE, ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource}; +use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT; + +pub use librashader::runtime::d3d12::capi::options::FilterChainOptionsD3D12; +pub use librashader::runtime::d3d12::capi::options::FrameOptionsD3D12; + +use librashader::runtime::{FilterChainParameters, Size, Viewport}; +use librashader::runtime::d3d12::{D3D12InputImage, D3D12OutputView}; + +/// Direct3D 11 parameters for the source image. +#[repr(C)] +pub struct libra_source_image_d3d12_t { + /// The resource containing the image. + pub resource: ManuallyDrop, + /// A CPU descriptor handle to a shader resource view of the image. + pub descriptor: D3D12_CPU_DESCRIPTOR_HANDLE, + /// The format of the image. + pub format: DXGI_FORMAT, + /// The width of the source image. + pub width: u32, + /// The height of the source image. + pub height: u32, +} + +impl TryFrom for D3D12InputImage { + type Error = LibrashaderError; + + fn try_from(value: libra_source_image_d3d12_t) -> Result { + let resource = value.resource.clone(); + + Ok(D3D12InputImage { + resource: ManuallyDrop::into_inner(resource), + descriptor: value.descriptor, + size: Size::new(value.width, value.height), + format: value.format, + }) + } +} + +extern_fn! { + /// Create the filter chain given the shader preset. + /// + /// The shader preset is immediately invalidated and must be recreated after + /// the filter chain is created. + /// + /// ## Safety: + /// - `preset` must be either null, or valid and aligned. + /// - `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. + fn libra_d3d12_filter_chain_create( + preset: *mut libra_shader_preset_t, + options: *const FilterChainOptionsD3D12, + device: ManuallyDrop, + out: *mut MaybeUninit + ) { + assert_non_null!(preset); + let preset = unsafe { + let preset_ptr = &mut *preset; + let preset = preset_ptr.take(); + Box::from_raw(preset.unwrap().as_ptr()) + }; + + let options = if options.is_null() { + None + } else { + Some(unsafe { &*options }) + }; + + let chain = librashader::runtime::d3d12::capi::FilterChainD3D12::load_from_preset( + &device, + *preset, + options, + )?; + + unsafe { + out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( + chain, + ))))) + } + } +} + +extern_fn! { + /// Records rendering commands for a frame with the given parameters for the given filter chain + /// to the input command list. + /// + /// ## Safety + /// - `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` + /// 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` + /// struct. + /// - `out` must be a descriptor handle to a render target view. + /// - `image.resource` must not be null. + /// - `command_list` must not be null. + fn libra_d3d12_filter_chain_frame( + chain: *mut libra_d3d12_filter_chain_t, + command_list: ManuallyDrop, + frame_count: usize, + image: libra_source_image_d3d12_t, + viewport: libra_viewport_t, + out: D3D12_CPU_DESCRIPTOR_HANDLE, + mvp: *const f32, + opt: *const FrameOptionsD3D12 + ) mut |chain| { + assert_some_ptr!(mut chain); + + let mvp = if mvp.is_null() { + None + } else { + Some(<&[f32; 16]>::try_from(unsafe { slice::from_raw_parts(mvp, 16) }).unwrap()) + }; + + let opt = if opt.is_null() { + None + } else { + Some(unsafe { opt.read() }) + }; + + let viewport = Viewport { + x: viewport.x, + y: viewport.y, + output: unsafe { D3D12OutputView::new_from_raw(out, Size::new(viewport.width, viewport.height)) }, + mvp, + }; + + let image = image.try_into()?; + chain.frame(&command_list, image, &viewport, frame_count, opt.as_ref())?; + } +} + +extern_fn! { + /// Sets a parameter for the filter 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`. + /// - `param_name` must be either null or a null terminated string. + fn libra_d3d12_filter_chain_set_param( + chain: *mut libra_d3d12_filter_chain_t, + param_name: *const c_char, + value: f32 + ) mut |chain| { + assert_some_ptr!(mut chain); + assert_non_null!(param_name); + unsafe { + let name = CStr::from_ptr(param_name); + let name = name.to_str()?; + + if chain.set_parameter(name, value).is_none() { + return LibrashaderError::UnknownShaderParameter(param_name).export() + } + } + } +} + +extern_fn! { + /// Gets a parameter for the filter 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`. + /// - `param_name` must be either null or a null terminated string. + fn libra_d3d12_filter_chain_get_param( + chain: *mut libra_d3d12_filter_chain_t, + param_name: *const c_char, + out: *mut MaybeUninit + ) mut |chain| { + assert_some_ptr!(mut chain); + assert_non_null!(param_name); + unsafe { + let name = CStr::from_ptr(param_name); + let name = name.to_str()?; + + let Some(value) = chain.get_parameter(name) else { + return LibrashaderError::UnknownShaderParameter(param_name).export() + }; + + out.write(MaybeUninit::new(value)); + } + } +} + +extern_fn! { + /// 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`. + fn libra_d3d12_filter_chain_set_active_pass_count( + chain: *mut libra_d3d12_filter_chain_t, + value: u32 + ) mut |chain| { + assert_some_ptr!(mut chain); + chain.set_enabled_pass_count(value as usize); + } +} + +extern_fn! { + /// 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`. + fn libra_d3d12_filter_chain_get_active_pass_count( + chain: *mut libra_d3d12_filter_chain_t, + out: *mut MaybeUninit + ) mut |chain| { + assert_some_ptr!(mut chain); + unsafe { + let value = chain.get_enabled_pass_count(); + out.write(MaybeUninit::new(value as u32)) + } + } +} + +extern_fn! { + /// Free a D3D12 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_d3d12_filter_chain_t`. + fn libra_d3d12_filter_chain_free(chain: *mut libra_d3d12_filter_chain_t) { + assert_non_null!(chain); + unsafe { + let chain_ptr = &mut *chain; + let chain = chain_ptr.take(); + drop(Box::from_raw(chain.unwrap().as_ptr())) + }; + } +} diff --git a/librashader-capi/src/runtime/d3d12/mod.rs b/librashader-capi/src/runtime/d3d12/mod.rs new file mode 100644 index 0000000..2201178 --- /dev/null +++ b/librashader-capi/src/runtime/d3d12/mod.rs @@ -0,0 +1,4 @@ +//! C API for the librashader D3D12 Runtime (`libra_d3d12_*`) + +mod filter_chain; +pub use filter_chain::*; diff --git a/librashader-capi/src/runtime/mod.rs b/librashader-capi/src/runtime/mod.rs index 4c36f21..90a0be6 100644 --- a/librashader-capi/src/runtime/mod.rs +++ b/librashader-capi/src/runtime/mod.rs @@ -3,10 +3,14 @@ #[cfg(feature = "runtime-opengl")] pub mod gl; +#[doc(cfg(feature = "runtime-vulkan"))] +#[cfg(feature = "runtime-vulkan")] +pub mod vk; + #[doc(cfg(all(target_os = "windows", feature = "runtime-d3d11")))] #[cfg(all(target_os = "windows", feature = "runtime-d3d11"))] pub mod d3d11; -#[doc(cfg(feature = "runtime-vulkan"))] -#[cfg(feature = "runtime-vulkan")] -pub mod vk; +#[doc(cfg(all(target_os = "windows", feature = "runtime-d3d12")))] +#[cfg(all(target_os = "windows", feature = "runtime-d3d12"))] +pub mod d3d12; \ No newline at end of file diff --git a/librashader-runtime-d3d12/src/lib.rs b/librashader-runtime-d3d12/src/lib.rs index 24040aa..6aa4767 100644 --- a/librashader-runtime-d3d12/src/lib.rs +++ b/librashader-runtime-d3d12/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg(target_os = "windows")] + #![feature(const_trait_impl)] #![feature(let_chains)] #![feature(type_alias_impl_trait)] diff --git a/test/capi-tests/librashader-capi-tests/dx11-example/main.cpp b/test/capi-tests/librashader-capi-tests/dx11-example/main.cpp index 5177d0f..1ba34bc 100644 --- a/test/capi-tests/librashader-capi-tests/dx11-example/main.cpp +++ b/test/capi-tests/librashader-capi-tests/dx11-example/main.cpp @@ -14,6 +14,7 @@ #include #define LIBRA_RUNTIME_D3D11 +#define LIBRA_RUNTIME_D3D12 #include "../../../../include/librashader.h" #include "../../../../include/librashader_ld.h"