diff --git a/include/librashader.h b/include/librashader.h index d421c32..ce10e8a 100644 --- a/include/librashader.h +++ b/include/librashader.h @@ -207,20 +207,6 @@ typedef struct libra_source_image_gl_t { } libra_source_image_gl_t; #endif -/// Defines the output origin 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 extent of the viewport framebuffer to end rendering, relative to - /// the origin specified by x. - uint32_t width; - /// The height extent of the viewport framebuffer to end rendering, relative to - /// the origin specified by y. - uint32_t height; -} libra_viewport_t; - #if defined(LIBRA_RUNTIME_OPENGL) /// OpenGL parameters for the output framebuffer. typedef struct libra_output_framebuffer_gl_t { @@ -237,6 +223,20 @@ typedef struct libra_output_framebuffer_gl_t { } libra_output_framebuffer_gl_t; #endif +/// Defines the output origin 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 extent of the viewport framebuffer to end rendering, relative to + /// the origin specified by x. + uint32_t width; + /// The height extent of the viewport framebuffer to end rendering, relative to + /// the origin specified by y. + uint32_t height; +} libra_viewport_t; + #if defined(LIBRA_RUNTIME_OPENGL) /// Options for each OpenGL shader frame. typedef struct frame_gl_opt_t { @@ -298,31 +298,17 @@ typedef struct _filter_chain_vk *libra_vk_filter_chain_t; #endif #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. +/// Vulkan parameters for an image. +typedef struct libra_image_vk_t { + /// A raw `VkImage` handle. VkImage handle; - /// The `VkFormat` of the source image. + /// The `VkFormat` of the `VkImage`. VkFormat format; - /// The width of the source image. + /// The width of the `VkImage`. uint32_t width; - /// The height of the source image. + /// The height of the `VkImage`. 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; - /// The width of the output image. - uint32_t width; - /// The height of the output image. - uint32_t height; -} libra_output_image_vk_t; +} libra_image_vk_t; #endif #if defined(LIBRA_RUNTIME_VULKAN) @@ -654,8 +640,8 @@ typedef libra_error_t (*PFN_libra_gl_filter_chain_create)(libra_shader_preset_t 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 struct libra_viewport_t *viewport, const float *mvp, const struct frame_gl_opt_t *opt); #endif @@ -721,9 +707,9 @@ typedef libra_error_t (*PFN_libra_vk_filter_chain_create_deferred)(libra_shader_ 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, + struct libra_image_vk_t image, + struct libra_image_vk_t out, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_vk_opt_t *opt); #endif @@ -790,8 +776,8 @@ typedef libra_error_t (*PFN_libra_d3d11_filter_chain_frame)(libra_d3d11_filter_c ID3D11DeviceContext * device_context, size_t frame_count, ID3D11ShaderResourceView * image, - struct libra_viewport_t viewport, ID3D11RenderTargetView * out, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_d3d11_opt_t *options); #endif @@ -847,8 +833,8 @@ typedef libra_error_t (*PFN_libra_d3d9_filter_chain_create)(libra_shader_preset_ typedef libra_error_t (*PFN_libra_d3d9_filter_chain_frame)(libra_d3d9_filter_chain_t *chain, size_t frame_count, IDirect3DTexture9 * image, - struct libra_viewport_t viewport, IDirect3DSurface9 * out, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_d3d9_opt_t *options); #endif @@ -915,8 +901,8 @@ typedef libra_error_t (*PFN_libra_d3d12_filter_chain_frame)(libra_d3d12_filter_c 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 struct libra_viewport_t *viewport, const float *mvp, const struct frame_d3d12_opt_t *options); #endif @@ -983,8 +969,8 @@ typedef libra_error_t (*PFN_libra_mtl_filter_chain_frame)(libra_mtl_filter_chain id command_buffer, size_t frame_count, id image, - struct libra_viewport_t viewport, id output, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_mtl_opt_t *opt); #endif @@ -1207,6 +1193,23 @@ libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t *preset, #if defined(LIBRA_RUNTIME_OPENGL) /// Draw a frame with the given parameters for the given filter chain. /// +/// ## Parameters +/// +/// - `chain` is a handle to the filter chain. +/// - `frame_count` is the number of frames passed to the shader +/// - `image` is a `libra_source_image_gl_t`, containing the name of a Texture, format, and size information to +/// to an image that will serve as the source image for the frame. +/// - `out` is a `libra_output_framebuffer_gl_t`, containing the name of a Framebuffer, the name of a Texture, format, +/// and size information for the render target of the frame. +/// +/// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport +/// will be applied to the render target. It may be null, in which case a default viewport spanning the +/// entire render target will be used. +/// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to +/// be passed to the shader. +/// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` +/// passed in. It may be null, in which case default options for the filter chain are used. +/// /// ## Safety /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// function will return an error. @@ -1221,8 +1224,8 @@ libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t *preset, 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 struct libra_viewport_t *viewport, const float *mvp, const struct frame_gl_opt_t *opt); #endif @@ -1326,13 +1329,31 @@ libra_error_t libra_vk_filter_chain_create_deferred(libra_shader_preset_t *prese /// 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 +/// librashader **will not** create a pipeline barrier for the final pass. The output image must be +/// in `VK_COLOR_ATTACHMENT_OPTIMAL`, and will remain so after all shader passes. The caller must transition /// the output image to the final layout. /// +/// ## Parameters +/// +/// - `chain` is a handle to the filter chain. +/// - `command_buffer` is a `VkCommandBuffer` handle to record draw commands to. +/// The provided command buffer must be ready for recording and contain no prior commands +/// - `frame_count` is the number of frames passed to the shader +/// - `image` is a `libra_image_vk_t`, containing a `VkImage` handle, it's format and size information, +/// to an image that will serve as the source image for the frame. The input image must be in +/// the `VK_SHADER_READ_ONLY_OPTIMAL` layout. +/// - `out` is a `libra_image_vk_t`, containing a `VkImage` handle, it's format and size information, +/// for the render target of the frame. The output image must be in `VK_COLOR_ATTACHMENT_OPTIMAL` layout. +/// The output image will remain in `VK_COLOR_ATTACHMENT_OPTIMAL` after all shader passes. +/// +/// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport +/// will be applied to the render target. It may be null, in which case a default viewport spanning the +/// entire render target will be used. +/// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to +/// be passed to the shader. +/// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` +/// passed in. It may be null, in which case default options for the filter chain are used. +/// /// ## 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. @@ -1347,9 +1368,9 @@ libra_error_t libra_vk_filter_chain_create_deferred(libra_shader_preset_t *prese 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, + struct libra_image_vk_t image, + struct libra_image_vk_t out, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_vk_opt_t *opt); #endif @@ -1457,9 +1478,26 @@ libra_error_t libra_d3d11_filter_chain_create_deferred(libra_shader_preset_t *pr #if (defined(_WIN32) && 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` +/// ## Parameters +/// +/// - `chain` is a handle to the filter chain. +/// - `device_context` is the ID3D11DeviceContext used to record draw commands to. +/// 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` +/// the filter chain was created with. +/// +/// - `frame_count` is the number of frames passed to the shader +/// - `image` is a pointer to a `ID3D11ShaderResourceView` that will serve as the source image for the frame. +/// - `out` is a pointer to a `ID3D11RenderTargetView` that will serve as the render target for the frame. +/// +/// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport +/// will be applied to the render target. It may be null, in which case a default viewport spanning the +/// entire render target will be used. +/// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to +/// be passed to the shader. +/// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` +/// passed in. It may be null, in which case default options for the filter chain are used. /// /// ## Safety /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this @@ -1479,8 +1517,8 @@ libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain, ID3D11DeviceContext * device_context, size_t frame_count, ID3D11ShaderResourceView * image, - struct libra_viewport_t viewport, ID3D11RenderTargetView * out, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_d3d11_opt_t *options); #endif @@ -1556,10 +1594,24 @@ libra_error_t libra_d3d9_filter_chain_create(libra_shader_preset_t *preset, #if (defined(_WIN32) && defined(LIBRA_RUNTIME_D3D9)) /// Draw a frame with the given parameters for the given filter chain. /// +/// ## Parameters +/// - `chain` is a handle to the filter chain. +/// - `frame_count` is the number of frames passed to the shader +/// - `image` is a pointer to a `IDirect3DTexture9` that will serve as the source image for the frame. +/// - `out` is a pointer to a `IDirect3DSurface9` that will serve as the render target for the frame. +/// +/// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport +/// will be applied to the render target. It may be null, in which case a default viewport spanning the +/// entire render target will be used. +/// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to +/// be passed to the shader. +/// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` +/// passed in. It may be null, in which case default options for the filter chain are used. /// /// ## Safety /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// function will return an error. +/// - `viewport` may be null, or if it is not null, must be an aligned pointer to an instance of `libra_viewport_t`. /// - `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_d3d9_opt_t` @@ -1571,8 +1623,8 @@ libra_error_t libra_d3d9_filter_chain_create(libra_shader_preset_t *preset, libra_error_t libra_d3d9_filter_chain_frame(libra_d3d9_filter_chain_t *chain, size_t frame_count, IDirect3DTexture9 * image, - struct libra_viewport_t viewport, IDirect3DSurface9 * out, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_d3d9_opt_t *options); #endif @@ -1673,13 +1725,31 @@ libra_error_t libra_d3d12_filter_chain_create_deferred(libra_shader_preset_t *pr /// 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. -/// /// 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. /// +/// ## Parameters +/// +/// - `chain` is a handle to the filter chain. +/// - `command_list` is a `ID3D12GraphicsCommandList` to record draw commands to. +/// The provided command list must be open and associated with the `ID3D12Device` this filter chain was created with. +/// - `frame_count` is the number of frames passed to the shader +/// - `image` is a `libra_source_image_d3d12_t`, containing a `ID3D12Resource` pointer and CPU descriptor +/// to an image that will serve as the source image for the frame. The input image must be in the +/// `D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE` resource state or equivalent barrier layout. +/// - `out` is a `libra_output_image_d3d12_t`, containing a CPU descriptor handle, format, and size information +/// for the render target of the frame. The output image must be in +/// `D3D12_RESOURCE_STATE_RENDER_TARGET` resource state or equivalent barrier layout. +/// +/// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport +/// will be applied to the render target. It may be null, in which case a default viewport spanning the +/// entire render target will be used. +/// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to +/// be passed to the shader. +/// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` +/// passed in. It may be null, in which case default options for the filter chain are used. +/// /// ## Safety /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// function will return an error. @@ -1697,8 +1767,8 @@ 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 struct libra_viewport_t *viewport, const float *mvp, const struct frame_d3d12_opt_t *options); #endif @@ -1802,6 +1872,22 @@ libra_error_t libra_mtl_filter_chain_create_deferred(libra_shader_preset_t *pres #if (defined(__APPLE__) && defined(LIBRA_RUNTIME_METAL) && defined(__OBJC__)) /// Records rendering commands for a frame with the given parameters for the given filter chain /// to the input command buffer. +/// ## Parameters +/// +/// - `chain` is a handle to the filter chain. +/// - `command_buffer` is a `MTLCommandBuffer` handle to record draw commands to. +/// The provided command buffer must be ready for encoding and contain no prior commands +/// - `frame_count` is the number of frames passed to the shader +/// - `image` is a `id` that will serve as the source image for the frame. +/// - `out` is a `id` that is the render target of the frame. +/// +/// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport +/// will be applied to the render target. It may be null, in which case a default viewport spanning the +/// entire render target will be used. +/// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to +/// be passed to the shader. +/// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` +/// passed in. It may be null, in which case default options for the filter chain are used. /// /// ## Safety /// - `command_buffer` must be a valid reference to a `MTLCommandBuffer` that is not already encoding. @@ -1817,8 +1903,8 @@ libra_error_t libra_mtl_filter_chain_frame(libra_mtl_filter_chain_t *chain, id command_buffer, size_t frame_count, id image, - struct libra_viewport_t viewport, id output, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_mtl_opt_t *opt); #endif diff --git a/include/librashader_ld.h b/include/librashader_ld.h index 9f9cd68..f9b1f4e 100644 --- a/include/librashader_ld.h +++ b/include/librashader_ld.h @@ -204,8 +204,8 @@ libra_error_t __librashader__noop_gl_filter_chain_create( libra_error_t __librashader__noop_gl_filter_chain_frame( libra_gl_filter_chain_t *chain, size_t frame_count, - struct libra_source_image_gl_t image, struct libra_viewport_t viewport, - struct libra_output_framebuffer_gl_t out, const float *mvp, + struct libra_source_image_gl_t image, struct libra_output_framebuffer_gl_t out, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_gl_opt_t *opt) { return NULL; } @@ -254,9 +254,9 @@ libra_error_t __librashader__noop_vk_filter_chain_create_deferred( libra_error_t __librashader__noop_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) { + size_t frame_count, struct libra_image_vk_t image, struct libra_image_vk_t out, + const struct libra_viewport_t *viewport, const float *mvp, + const struct frame_vk_opt_t *opt) { return NULL; } @@ -306,9 +306,9 @@ 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, ID3D11ShaderResourceView *image, - struct libra_viewport_t viewport, ID3D11RenderTargetView *out, - const float *mvp, const struct frame_d3d11_opt_t *opt) { + size_t frame_count, ID3D11ShaderResourceView *image, ID3D11RenderTargetView *out, + const struct libra_viewport_t *viewport, const float *mvp, + const struct frame_d3d11_opt_t *opt) { return NULL; } @@ -358,9 +358,9 @@ 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) { + size_t frame_count, struct libra_source_image_d3d12_t image, struct libra_output_image_d3d12_t out, + const struct libra_viewport_t *viewport, const float *mvp, + const struct frame_d3d12_opt_t *opt) { return NULL; } @@ -401,8 +401,8 @@ libra_error_t __librashader__noop_d3d9_filter_chain_create( libra_error_t __librashader__noop_d3d9_filter_chain_frame( libra_d3d9_filter_chain_t *chain, size_t frame_count, - IDirect3DTexture9 *image, struct libra_viewport_t viewport, - IDirect3DSurface9 * out, const float *mvp, + IDirect3DTexture9 *image, IDirect3DSurface9 * out, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_d3d9_opt_t *opt) { return NULL; } @@ -453,8 +453,8 @@ libra_error_t __librashader__noop_mtl_filter_chain_create_deferred( libra_error_t __librashader__noop_mtl_filter_chain_frame( libra_mtl_filter_chain_t *chain, id command_buffer, - size_t frame_count, id image, struct libra_viewport_t viewport, - id output, const float *mvp, + size_t frame_count, id image, id output, + const struct libra_viewport_t *viewport, const float *mvp, const struct frame_mtl_opt_t *opt) { return NULL; } diff --git a/librashader-capi/src/error.rs b/librashader-capi/src/error.rs index 542eb46..3177bb7 100644 --- a/librashader-capi/src/error.rs +++ b/librashader-capi/src/error.rs @@ -89,6 +89,8 @@ pub enum LibrashaderError { #[cfg(all(target_vendor = "apple", feature = "runtime-metal"))] #[error("There was an error in the Metal filter chain.")] MetalFilterError(#[from] librashader::runtime::mtl::error::FilterChainError), + #[error("This error is not reachable")] + Infallible(#[from] std::convert::Infallible), } /// Error codes for librashader error types. @@ -254,6 +256,7 @@ impl LibrashaderError { LibrashaderError::VulkanFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, #[cfg(all(target_vendor = "apple", feature = "runtime-metal"))] LibrashaderError::MetalFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, + LibrashaderError::Infallible(_) => LIBRA_ERRNO::UNKNOWN_ERROR, } } pub(crate) const fn ok() -> libra_error_t { diff --git a/librashader-capi/src/runtime/d3d11/filter_chain.rs b/librashader-capi/src/runtime/d3d11/filter_chain.rs index 9b92ace..d6c3be3 100644 --- a/librashader-capi/src/runtime/d3d11/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d11/filter_chain.rs @@ -15,6 +15,7 @@ use windows::Win32::Graphics::Direct3D11::{ }; use crate::LIBRASHADER_API_VERSION; +use librashader::runtime::d3d11::error::FilterChainError; use librashader::runtime::{FilterChainParameters, Size, Viewport}; /// Options for Direct3D 11 filter chain creation. @@ -178,10 +179,26 @@ const _: () = assert!( extern_fn! { /// 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` - // the filter chain was created with. + /// ## Parameters + /// + /// - `chain` is a handle to the filter chain. + /// - `device_context` is the ID3D11DeviceContext used to record draw commands to. + /// 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` + /// the filter chain was created with. + /// + /// - `frame_count` is the number of frames passed to the shader + /// - `image` is a pointer to a `ID3D11ShaderResourceView` that will serve as the source image for the frame. + /// - `out` is a pointer to a `ID3D11RenderTargetView` that will serve as the render target for the frame. + /// + /// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport + /// will be applied to the render target. It may be null, in which case a default viewport spanning the + /// entire render target will be used. + /// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to + /// be passed to the shader. + /// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` + /// passed in. It may be null, in which case default options for the filter chain are used. /// /// ## Safety /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this @@ -204,8 +221,8 @@ extern_fn! { device_context: Option>, frame_count: usize, image: ManuallyDrop, - viewport: libra_viewport_t, out: ManuallyDrop, + viewport: *const libra_viewport_t, mvp: *const f32, options: *const MaybeUninit ) mut |chain| { @@ -223,15 +240,21 @@ extern_fn! { Some(unsafe { options.read() }) }; - let viewport = Viewport { - x: viewport.x, - y: viewport.y, - output: ManuallyDrop::into_inner(out.clone()), - size: Size { - height: viewport.height, - width: viewport.width - }, - mvp, + let viewport = if viewport.is_null() { + Viewport::new_render_target_sized_origin(ManuallyDrop::into_inner(out.clone()), mvp) + .map_err(|e| LibrashaderError::D3D11FilterError(FilterChainError::Direct3DError(e)))? + } else { + let viewport = unsafe { viewport.read() }; + Viewport { + x: viewport.x, + y: viewport.y, + output: ManuallyDrop::into_inner(out.clone()), + size: Size { + height: viewport.height, + width: viewport.width + }, + mvp, + } }; let options = options.map(FromUninit::from_uninit); diff --git a/librashader-capi/src/runtime/d3d12/filter_chain.rs b/librashader-capi/src/runtime/d3d12/filter_chain.rs index bfe0bb1..4f2194a 100644 --- a/librashader-capi/src/runtime/d3d12/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d12/filter_chain.rs @@ -208,13 +208,31 @@ extern_fn! { /// 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. - /// /// 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. /// + /// ## Parameters + /// + /// - `chain` is a handle to the filter chain. + /// - `command_list` is a `ID3D12GraphicsCommandList` to record draw commands to. + /// The provided command list must be open and associated with the `ID3D12Device` this filter chain was created with. + /// - `frame_count` is the number of frames passed to the shader + /// - `image` is a `libra_source_image_d3d12_t`, containing a `ID3D12Resource` pointer and CPU descriptor + /// to an image that will serve as the source image for the frame. The input image must be in the + /// `D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE` resource state or equivalent barrier layout. + /// - `out` is a `libra_output_image_d3d12_t`, containing a CPU descriptor handle, format, and size information + /// for the render target of the frame. The output image must be in + /// `D3D12_RESOURCE_STATE_RENDER_TARGET` resource state or equivalent barrier layout. + /// + /// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport + /// will be applied to the render target. It may be null, in which case a default viewport spanning the + /// entire render target will be used. + /// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to + /// be passed to the shader. + /// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` + /// passed in. It may be null, in which case default options for the filter chain are used. + /// /// ## Safety /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// function will return an error. @@ -233,8 +251,8 @@ extern_fn! { command_list: ManuallyDrop, frame_count: usize, image: libra_source_image_d3d12_t, - viewport: libra_viewport_t, out: libra_output_image_d3d12_t, + viewport: *const libra_viewport_t, mvp: *const f32, options: *const MaybeUninit ) mut |chain| { @@ -253,17 +271,28 @@ extern_fn! { }; let options = options.map(FromUninit::from_uninit); - let viewport = Viewport { - x: viewport.x, - y: viewport.y, - size: Size { - height: viewport.height, - width: viewport.width - }, - output: unsafe { - D3D12OutputView::new_from_raw(out.descriptor, - Size::new(out.width, out.height), out.format) }, - mvp, + + let output = unsafe { + D3D12OutputView::new_from_raw( + out.descriptor, + Size::new(out.width, out.height), + out.format) + }; + + let viewport = if viewport.is_null() { + Viewport::new_render_target_sized_origin(output, mvp)? + } else { + let viewport = unsafe { viewport.read() }; + Viewport { + x: viewport.x, + y: viewport.y, + output, + size: Size { + height: viewport.height, + width: viewport.width + }, + mvp, + } }; let image = image.try_into()?; diff --git a/librashader-capi/src/runtime/d3d9/filter_chain.rs b/librashader-capi/src/runtime/d3d9/filter_chain.rs index e3d7ff2..47db2db 100644 --- a/librashader-capi/src/runtime/d3d9/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d9/filter_chain.rs @@ -12,6 +12,7 @@ use std::slice; use windows::Win32::Graphics::Direct3D9::{IDirect3DDevice9, IDirect3DSurface9, IDirect3DTexture9}; use crate::LIBRASHADER_API_VERSION; +use librashader::runtime::d3d9::error::FilterChainError; use librashader::runtime::{FilterChainParameters, Size, Viewport}; /// Options for Direct3D 11 filter chain creation. @@ -108,10 +109,24 @@ extern_fn! { extern_fn! { /// Draw a frame with the given parameters for the given filter chain. /// + /// ## Parameters + /// - `chain` is a handle to the filter chain. + /// - `frame_count` is the number of frames passed to the shader + /// - `image` is a pointer to a `IDirect3DTexture9` that will serve as the source image for the frame. + /// - `out` is a pointer to a `IDirect3DSurface9` that will serve as the render target for the frame. + /// + /// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport + /// will be applied to the render target. It may be null, in which case a default viewport spanning the + /// entire render target will be used. + /// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to + /// be passed to the shader. + /// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` + /// passed in. It may be null, in which case default options for the filter chain are used. /// /// ## Safety /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// function will return an error. + /// - `viewport` may be null, or if it is not null, must be an aligned pointer to an instance of `libra_viewport_t`. /// - `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_d3d9_opt_t` @@ -124,8 +139,8 @@ extern_fn! { chain: *mut libra_d3d9_filter_chain_t, frame_count: usize, image: ManuallyDrop, - viewport: libra_viewport_t, out: ManuallyDrop, + viewport: *const libra_viewport_t, mvp: *const f32, options: *const MaybeUninit ) mut |chain| { @@ -143,15 +158,21 @@ extern_fn! { Some(unsafe { options.read() }) }; - let viewport = Viewport { - x: viewport.x, - y: viewport.y, - output: ManuallyDrop::into_inner(out.clone()), - size: Size { - height: viewport.height, - width: viewport.width - }, - mvp, + let viewport = if viewport.is_null() { + Viewport::new_render_target_sized_origin(ManuallyDrop::into_inner(out.clone()), mvp) + .map_err(|e| LibrashaderError::D3D9FilterError(FilterChainError::Direct3DError(e)))? + } else { + let viewport = unsafe { viewport.read() }; + Viewport { + x: viewport.x, + y: viewport.y, + output: ManuallyDrop::into_inner(out.clone()), + size: Size { + height: viewport.height, + width: viewport.width + }, + mvp, + } }; let options = options.map(FromUninit::from_uninit); diff --git a/librashader-capi/src/runtime/gl/filter_chain.rs b/librashader-capi/src/runtime/gl/filter_chain.rs index e26369b..1905c12 100644 --- a/librashader-capi/src/runtime/gl/filter_chain.rs +++ b/librashader-capi/src/runtime/gl/filter_chain.rs @@ -162,6 +162,23 @@ extern_fn! { extern_fn! { /// Draw a frame with the given parameters for the given filter chain. /// + /// ## Parameters + /// + /// - `chain` is a handle to the filter chain. + /// - `frame_count` is the number of frames passed to the shader + /// - `image` is a `libra_source_image_gl_t`, containing the name of a Texture, format, and size information to + /// to an image that will serve as the source image for the frame. + /// - `out` is a `libra_output_framebuffer_gl_t`, containing the name of a Framebuffer, the name of a Texture, format, + /// and size information for the render target of the frame. + /// + /// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport + /// will be applied to the render target. It may be null, in which case a default viewport spanning the + /// entire render target will be used. + /// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to + /// be passed to the shader. + /// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` + /// passed in. It may be null, in which case default options for the filter chain are used. + /// /// ## Safety /// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this /// function will return an error. @@ -177,8 +194,8 @@ extern_fn! { chain: *mut libra_gl_filter_chain_t, frame_count: usize, image: libra_source_image_gl_t, - viewport: libra_viewport_t, out: libra_output_framebuffer_gl_t, + viewport: *const libra_viewport_t, mvp: *const f32, opt: *const MaybeUninit, ) mut |chain| { @@ -209,15 +226,20 @@ extern_fn! { let framebuffer = GLFramebuffer::new_from_raw(Arc::clone(chain.get_context()), texture, fbo, out.format, Size::new(out.width, out.height), 1); - let viewport = Viewport { - x: viewport.x, - y: viewport.y, - output: &framebuffer, - size: Size { - height: viewport.height, - width: viewport.width - }, - mvp, + let viewport = if viewport.is_null() { + Viewport::new_render_target_sized_origin(&framebuffer, mvp)? + } else { + let viewport = unsafe { viewport.read() }; + Viewport { + x: viewport.x, + y: viewport.y, + output: &framebuffer, + size: Size { + height: viewport.height, + width: viewport.width + }, + mvp, + } }; unsafe { diff --git a/librashader-capi/src/runtime/mtl/filter_chain.rs b/librashader-capi/src/runtime/mtl/filter_chain.rs index a8ac8e9..a54c664 100644 --- a/librashader-capi/src/runtime/mtl/filter_chain.rs +++ b/librashader-capi/src/runtime/mtl/filter_chain.rs @@ -173,6 +173,22 @@ extern_fn! { extern_fn! { /// Records rendering commands for a frame with the given parameters for the given filter chain /// to the input command buffer. + /// ## Parameters + /// + /// - `chain` is a handle to the filter chain. + /// - `command_buffer` is a `MTLCommandBuffer` handle to record draw commands to. + /// The provided command buffer must be ready for encoding and contain no prior commands + /// - `frame_count` is the number of frames passed to the shader + /// - `image` is a `id` that will serve as the source image for the frame. + /// - `out` is a `id` that is the render target of the frame. + /// + /// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport + /// will be applied to the render target. It may be null, in which case a default viewport spanning the + /// entire render target will be used. + /// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to + /// be passed to the shader. + /// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` + /// passed in. It may be null, in which case default options for the filter chain are used. /// /// ## Safety /// - `command_buffer` must be a valid reference to a `MTLCommandBuffer` that is not already encoding. @@ -189,8 +205,8 @@ extern_fn! { command_buffer: PMTLCommandBuffer, frame_count: usize, image: PMTLTexture, - viewport: libra_viewport_t, output: PMTLTexture, + viewport: *const libra_viewport_t, mvp: *const f32, opt: *const MaybeUninit ) |command_buffer, image, output|; mut |chain| { @@ -207,15 +223,21 @@ extern_fn! { Some(unsafe { opt.read() }) }; let opt = opt.map(FromUninit::from_uninit); - let viewport = Viewport { - x: viewport.x, - y: viewport.y, - size: Size { - height: viewport.height, - width: viewport.width - }, - output, - mvp, + + let viewport = if viewport.is_null() { + Viewport::new_render_target_sized_origin(output, mvp)? + } else { + let viewport = unsafe { viewport.read() }; + Viewport { + x: viewport.x, + y: viewport.y, + output, + size: Size { + height: viewport.height, + width: viewport.width + }, + mvp, + } }; chain.frame(&image, &viewport, command_buffer, frame_count, opt.as_ref())?; diff --git a/librashader-capi/src/runtime/vk/filter_chain.rs b/librashader-capi/src/runtime/vk/filter_chain.rs index 853ef53..83df49d 100644 --- a/librashader-capi/src/runtime/vk/filter_chain.rs +++ b/librashader-capi/src/runtime/vk/filter_chain.rs @@ -24,29 +24,16 @@ pub use ash::vk::PFN_vkGetInstanceProcAddr; pub type libra_PFN_vkGetInstanceProcAddr = unsafe extern "system" fn(instance: *mut c_void, p_name: *const c_char); -/// Vulkan parameters for the source image. +/// Vulkan parameters for an image. #[repr(C)] -pub struct libra_source_image_vk_t { - /// A raw `VkImage` handle to the source image. +pub struct libra_image_vk_t { + /// A raw `VkImage` handle. pub handle: vk::Image, - /// The `VkFormat` of the source image. + /// The `VkFormat` of the `VkImage`. pub format: vk::Format, - /// The width of the source image. + /// The width of the `VkImage`. pub width: u32, - /// The height of the source image. - pub height: u32, -} - -/// Vulkan parameters for the output image. -#[repr(C)] -pub struct libra_output_image_vk_t { - /// A raw `VkImage` handle to the output image. - pub handle: vk::Image, - /// The `VkFormat` of the output image. - pub format: vk::Format, - /// The width of the output image. - pub width: u32, - /// The height of the output image. + /// The height of the `VkImage`. pub height: u32, } @@ -66,8 +53,8 @@ pub struct libra_device_vk_t { pub entry: vk::PFN_vkGetInstanceProcAddr, } -impl From for VulkanImage { - fn from(value: libra_source_image_vk_t) -> Self { +impl From for VulkanImage { + fn from(value: libra_image_vk_t) -> Self { VulkanImage { size: Size::new(value.width, value.height), image: value.handle, @@ -240,13 +227,31 @@ extern_fn! { /// 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 + /// librashader **will not** create a pipeline barrier for the final pass. The output image must be + /// in `VK_COLOR_ATTACHMENT_OPTIMAL`, and will remain so after all shader passes. The caller must transition /// the output image to the final layout. /// + /// ## Parameters + /// + /// - `chain` is a handle to the filter chain. + /// - `command_buffer` is a `VkCommandBuffer` handle to record draw commands to. + /// The provided command buffer must be ready for recording and contain no prior commands + /// - `frame_count` is the number of frames passed to the shader + /// - `image` is a `libra_image_vk_t`, containing a `VkImage` handle, it's format and size information, + /// to an image that will serve as the source image for the frame. The input image must be in + /// the `VK_SHADER_READ_ONLY_OPTIMAL` layout. + /// - `out` is a `libra_image_vk_t`, containing a `VkImage` handle, it's format and size information, + /// for the render target of the frame. The output image must be in `VK_COLOR_ATTACHMENT_OPTIMAL` layout. + /// The output image will remain in `VK_COLOR_ATTACHMENT_OPTIMAL` after all shader passes. + /// + /// - `viewport` is a pointer to a `libra_viewport_t` that specifies the area onto which scissor and viewport + /// will be applied to the render target. It may be null, in which case a default viewport spanning the + /// entire render target will be used. + /// - `mvp` is a pointer to an array of 16 `float` values to specify the model view projection matrix to + /// be passed to the shader. + /// - `options` is a pointer to options for the frame. Valid options are dependent on the `LIBRASHADER_API_VERSION` + /// passed in. It may be null, in which case default options for the filter chain are used. + /// /// ## 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. @@ -262,9 +267,9 @@ extern_fn! { chain: *mut libra_vk_filter_chain_t, command_buffer: vk::CommandBuffer, frame_count: usize, - image: libra_source_image_vk_t, - viewport: libra_viewport_t, - out: libra_output_image_vk_t, + image: libra_image_vk_t, + out: libra_image_vk_t, + viewport: *const libra_viewport_t, mvp: *const f32, opt: *const MaybeUninit ) mut |chain| { @@ -286,15 +291,21 @@ extern_fn! { Some(unsafe { opt.read() }) }; let opt = opt.map(FromUninit::from_uninit); - let viewport = Viewport { - x: viewport.x, - y: viewport.y, - size: Size { - height: viewport.height, - width: viewport.width - }, - output, - mvp, + + let viewport = if viewport.is_null() { + Viewport::new_render_target_sized_origin(output, mvp)? + } else { + let viewport = unsafe { viewport.read() }; + Viewport { + x: viewport.x, + y: viewport.y, + output, + size: Size { + height: viewport.height, + width: viewport.width + }, + mvp, + } }; unsafe { diff --git a/librashader-common/src/lib.rs b/librashader-common/src/lib.rs index efd2caa..2a5593f 100644 --- a/librashader-common/src/lib.rs +++ b/librashader-common/src/lib.rs @@ -201,47 +201,46 @@ impl Size { } } -impl> Sub for Size { +impl> Sub for Size { type Output = Size; fn sub(self, rhs: Self) -> Self::Output { Self { width: self.width - rhs.width, - height: self.height - rhs.height + height: self.height - rhs.height, } } } -impl + Copy> Sub for Size { +impl + Copy> Sub for Size { type Output = Size; fn sub(self, rhs: T) -> Self::Output { Self { width: self.width - rhs, - height: self.height - rhs + height: self.height - rhs, } } } - -impl> Add for Size { +impl> Add for Size { type Output = Size; fn add(self, rhs: Self) -> Self::Output { Self { width: self.width + rhs.width, - height: self.height + rhs.height + height: self.height + rhs.height, } } } -impl + Copy> Add for Size { +impl + Copy> Add for Size { type Output = Size; fn add(self, rhs: T) -> Self::Output { Self { width: self.width + rhs, - height: self.height + rhs + height: self.height + rhs, } } } diff --git a/librashader-common/src/metal.rs b/librashader-common/src/metal.rs index 34d9c25..efade7d 100644 --- a/librashader-common/src/metal.rs +++ b/librashader-common/src/metal.rs @@ -107,3 +107,16 @@ impl GetSize for ProtocolObject { }) } } + +impl GetSize for &ProtocolObject { + type Error = std::convert::Infallible; + + fn size(&self) -> Result, Self::Error> { + let height = self.height(); + let width = self.width(); + Ok(Size { + height: height as u32, + width: width as u32, + }) + } +} diff --git a/librashader-common/src/viewport.rs b/librashader-common/src/viewport.rs index 84b7bbf..2b3720a 100644 --- a/librashader-common/src/viewport.rs +++ b/librashader-common/src/viewport.rs @@ -1,4 +1,4 @@ -use crate::Size; +use crate::{GetSize, Size}; /// The rendering output of a filter chain. /// @@ -23,3 +23,24 @@ pub struct Viewport<'a, T> { /// by x and y. pub size: Size, } + +impl<'a, T: GetSize> Viewport<'a, T> { + /// Create a new viewport from an output that can be sized. + /// + /// This will create a viewport that spans the entire output texture, + /// which will give correct results in the general case. + #[inline(always)] + pub fn new_render_target_sized_origin( + output: T, + mvp: Option<&'a [f32; 16]>, + ) -> Result, T::Error> { + let size = output.size()?; + Ok(Self { + x: 0.0, + y: 0.0, + mvp, + output, + size, + }) + } +} diff --git a/librashader-runtime-d3d11/src/filter_pass.rs b/librashader-runtime-d3d11/src/filter_pass.rs index f11b2e2..ad19757 100644 --- a/librashader-runtime-d3d11/src/filter_pass.rs +++ b/librashader-runtime-d3d11/src/filter_pass.rs @@ -1,7 +1,7 @@ -use windows::Win32::Foundation::RECT; use crate::filter_chain::FilterCommon; use crate::options::FrameOptionsD3D11; use crate::texture::InputTexture; +use windows::Win32::Foundation::RECT; use librashader_common::map::FastHashMap; use librashader_common::{ImageFormat, Size, Viewport}; diff --git a/librashader-runtime-gl/src/gl/framebuffer.rs b/librashader-runtime-gl/src/gl/framebuffer.rs index 1fd9adf..d1ac97f 100644 --- a/librashader-runtime-gl/src/gl/framebuffer.rs +++ b/librashader-runtime-gl/src/gl/framebuffer.rs @@ -136,3 +136,11 @@ impl GetSize for GLFramebuffer { Ok(self.size) } } + +impl GetSize for &GLFramebuffer { + type Error = std::convert::Infallible; + + fn size(&self) -> std::result::Result, Self::Error> { + Ok(self.size) + } +} diff --git a/librashader-runtime-mtl/src/graphics_pipeline.rs b/librashader-runtime-mtl/src/graphics_pipeline.rs index 4920ed8..9d33591 100644 --- a/librashader-runtime-mtl/src/graphics_pipeline.rs +++ b/librashader-runtime-mtl/src/graphics_pipeline.rs @@ -208,7 +208,7 @@ impl MetalGraphicsPipeline { x: output.x as usize, y: output.y as usize, width: output.size.width as usize, - height: output.size.height as usize + height: output.size.height as usize, }); rpass.setViewport(MTLViewport { diff --git a/librashader-runtime-vk/src/texture.rs b/librashader-runtime-vk/src/texture.rs index 7f6cc77..e617fd8 100644 --- a/librashader-runtime-vk/src/texture.rs +++ b/librashader-runtime-vk/src/texture.rs @@ -7,7 +7,7 @@ use parking_lot::Mutex; use std::sync::Arc; use crate::error::FilterChainError; -use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; +use librashader_common::{FilterMode, GetSize, ImageFormat, Size, WrapMode}; use librashader_presets::Scale2D; use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize}; @@ -535,3 +535,11 @@ impl ScaleFramebuffer for OwnedImage { ) } } + +impl GetSize for VulkanImage { + type Error = std::convert::Infallible; + + fn size(&self) -> Result, Self::Error> { + Ok(self.size) + } +}