/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ //! FFI-friendly mirrors of render pass APIs in [`wgc`]. use crate::id; /// FFI-friendly analogue of [`std::option::Option`]. /// /// In some cases, Rust's standard `Option` type is FFI-friendly, in that `T` and `Option` map /// to the same C++ type. For example, both `&U` and `Option<&U>` can be represented as `U *` in /// C++. /// /// For other types, `Option` may not be FFI-safe. For such cases, this type is a `repr(u8)` /// analog to the standard /// /// See also: #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum FfiOption { Some(T), None, } impl FfiOption { pub fn to_std(self) -> std::option::Option { match self { Self::Some(value) => Some(value), Self::None => None, } } pub fn as_ref(&self) -> std::option::Option<&T> { match *self { Self::Some(ref value) => Some(value), Self::None => None, } } } /// FFI-safe analogue of [`wgc::command::RenderPassColorAttachment`]. #[repr(C)] #[derive(Clone, Debug, PartialEq)] pub struct FfiRenderPassColorAttachment { pub view: id::TextureViewId, pub depth_slice: FfiOption, pub resolve_target: Option, pub load_op: wgc::command::LoadOp, pub store_op: wgc::command::StoreOp, } impl FfiRenderPassColorAttachment { pub(crate) fn to_wgpu(self) -> wgc::command::RenderPassColorAttachment { let Self { view, depth_slice, resolve_target, load_op, store_op, } = self; wgc::command::RenderPassColorAttachment { view, depth_slice: depth_slice.to_std(), resolve_target, load_op, store_op, } } } /// FFI-safe analogue of [`wgc::command::RenderPassDepthStencilAttachment`]. #[repr(C)] #[derive(Clone, Debug, PartialEq)] pub struct RenderPassDepthStencilAttachment { pub view: id::TextureViewId, pub depth: PassChannel>, pub stencil: PassChannel>, } impl RenderPassDepthStencilAttachment { pub(crate) fn to_wgpu( self, ) -> wgc::command::RenderPassDepthStencilAttachment { let Self { view, depth, stencil, } = self; wgc::command::RenderPassDepthStencilAttachment { view, depth: depth.to_wgpu().map_clear_value(|opt| opt.to_std()), stencil: stencil.to_wgpu().map_clear_value(|opt| opt.to_std()), } } } /// FFI-safe analogue of [`wgc::command::PassChannel`]. #[repr(C)] #[derive(Clone, Debug, PartialEq)] pub struct PassChannel { pub load_op: FfiOption>, pub store_op: FfiOption, pub read_only: bool, } impl PassChannel { pub(crate) fn to_wgpu(self) -> wgc::command::PassChannel { let Self { load_op, store_op, read_only, } = self; wgc::command::PassChannel { load_op: load_op.to_std(), store_op: store_op.to_std(), read_only, } } } trait MapClearValue { type Converted; fn map_clear_value(self, f: impl FnOnce(V1) -> V2) -> Self::Converted; } impl MapClearValue for wgc::command::PassChannel { type Converted = wgc::command::PassChannel; fn map_clear_value(self, f: impl FnOnce(V1) -> V2) -> Self::Converted { let Self { load_op, store_op, read_only, } = self; wgc::command::PassChannel { load_op: load_op.map(|o| o.map_clear_value(f)), store_op, read_only, } } } impl MapClearValue for wgc::command::LoadOp { type Converted = wgc::command::LoadOp; fn map_clear_value(self, f: impl FnOnce(V1) -> V2) -> Self::Converted { match self { Self::Clear(value) => wgc::command::LoadOp::Clear(f(value)), Self::Load => wgc::command::LoadOp::Load, Self::DontCare(token) => wgc::command::LoadOp::DontCare(token), } } }