1use wasdk::webgpu::{
4 GpuBlendComponent, GpuBlendFactor, GpuBlendOperation, GpuBlendState, GpuColorTargetState,
5 GpuCompareFunction, GpuCullMode, GpuDepthStencilState, GpuFrontFace, GpuLoadOp,
6 GpuMultisampleState, GpuPrimitiveState, GpuPrimitiveTopology, GpuStencilFaceState,
7 GpuStencilOperation, GpuStoreOp, GpuVertexAttribute, GpuVertexBufferLayout, GpuVertexStepMode,
8};
9use wgpu::{
10 BlendComponent, BlendFactor, BlendOperation, BlendState, ColorTargetState, CompareFunction,
11 DepthStencilState, Face, Features, FrontFace, LoadOp, MultisampleState, Operations,
12 PolygonMode, PrimitiveState, PrimitiveTopology, StencilFaceState, StencilOperation, StoreOp,
13 VertexAttribute, VertexBufferLayout, VertexStepMode,
14};
15
16use super::{
17 color_writes_to_wasi, index_format_to_wasi, texture_format_to_wasi, vertex_format_to_wasi,
18};
19use crate::gap::feature_gap;
20
21pub fn compare_function_to_wasi(function: CompareFunction) -> GpuCompareFunction {
22 match function {
23 CompareFunction::Never => GpuCompareFunction::Never,
24 CompareFunction::Less => GpuCompareFunction::Less,
25 CompareFunction::Equal => GpuCompareFunction::Equal,
26 CompareFunction::LessEqual => GpuCompareFunction::LessEqual,
27 CompareFunction::Greater => GpuCompareFunction::Greater,
28 CompareFunction::NotEqual => GpuCompareFunction::NotEqual,
29 CompareFunction::GreaterEqual => GpuCompareFunction::GreaterEqual,
30 CompareFunction::Always => GpuCompareFunction::Always,
31 }
32}
33
34pub fn stencil_operation_to_wasi(operation: StencilOperation) -> GpuStencilOperation {
35 match operation {
36 StencilOperation::Keep => GpuStencilOperation::Keep,
37 StencilOperation::Zero => GpuStencilOperation::Zero,
38 StencilOperation::Replace => GpuStencilOperation::Replace,
39 StencilOperation::Invert => GpuStencilOperation::Invert,
40 StencilOperation::IncrementClamp => GpuStencilOperation::IncrementClamp,
41 StencilOperation::DecrementClamp => GpuStencilOperation::DecrementClamp,
42 StencilOperation::IncrementWrap => GpuStencilOperation::IncrementWrap,
43 StencilOperation::DecrementWrap => GpuStencilOperation::DecrementWrap,
44 }
45}
46
47pub fn stencil_face_to_wasi(face: &StencilFaceState) -> GpuStencilFaceState {
48 GpuStencilFaceState {
49 compare: Some(compare_function_to_wasi(face.compare)),
50 fail_op: Some(stencil_operation_to_wasi(face.fail_op)),
51 depth_fail_op: Some(stencil_operation_to_wasi(face.depth_fail_op)),
52 pass_op: Some(stencil_operation_to_wasi(face.pass_op)),
53 }
54}
55
56pub fn depth_stencil_state_to_wasi(state: &DepthStencilState) -> GpuDepthStencilState {
57 GpuDepthStencilState {
58 format: texture_format_to_wasi(state.format),
59 depth_write_enabled: state.depth_write_enabled,
60 depth_compare: state.depth_compare.map(compare_function_to_wasi),
61 stencil_front: Some(stencil_face_to_wasi(&state.stencil.front)),
62 stencil_back: Some(stencil_face_to_wasi(&state.stencil.back)),
63 stencil_read_mask: Some(state.stencil.read_mask),
64 stencil_write_mask: Some(state.stencil.write_mask),
65 depth_bias: Some(state.bias.constant),
66 depth_bias_slope_scale: Some(state.bias.slope_scale),
67 depth_bias_clamp: Some(state.bias.clamp),
68 }
69}
70
71pub fn blend_factor_to_wasi(factor: BlendFactor) -> GpuBlendFactor {
72 match factor {
73 BlendFactor::Zero => GpuBlendFactor::Zero,
74 BlendFactor::One => GpuBlendFactor::One,
75 BlendFactor::Src => GpuBlendFactor::Src,
76 BlendFactor::OneMinusSrc => GpuBlendFactor::OneMinusSrc,
77 BlendFactor::SrcAlpha => GpuBlendFactor::SrcAlpha,
78 BlendFactor::OneMinusSrcAlpha => GpuBlendFactor::OneMinusSrcAlpha,
79 BlendFactor::Dst => GpuBlendFactor::Dst,
80 BlendFactor::OneMinusDst => GpuBlendFactor::OneMinusDst,
81 BlendFactor::DstAlpha => GpuBlendFactor::DstAlpha,
82 BlendFactor::OneMinusDstAlpha => GpuBlendFactor::OneMinusDstAlpha,
83 BlendFactor::SrcAlphaSaturated => GpuBlendFactor::SrcAlphaSaturated,
84 BlendFactor::Constant => GpuBlendFactor::Constant,
85 BlendFactor::OneMinusConstant => GpuBlendFactor::OneMinusConstant,
86 BlendFactor::Src1 => GpuBlendFactor::Src1,
87 BlendFactor::OneMinusSrc1 => GpuBlendFactor::OneMinusSrc1,
88 BlendFactor::Src1Alpha => GpuBlendFactor::Src1Alpha,
89 BlendFactor::OneMinusSrc1Alpha => GpuBlendFactor::OneMinusSrc1Alpha,
90 }
91}
92
93pub fn blend_operation_to_wasi(operation: BlendOperation) -> GpuBlendOperation {
94 match operation {
95 BlendOperation::Add => GpuBlendOperation::Add,
96 BlendOperation::Subtract => GpuBlendOperation::Subtract,
97 BlendOperation::ReverseSubtract => GpuBlendOperation::ReverseSubtract,
98 BlendOperation::Min => GpuBlendOperation::Min,
99 BlendOperation::Max => GpuBlendOperation::Max,
100 }
101}
102
103pub fn blend_component_to_wasi(component: &BlendComponent) -> GpuBlendComponent {
104 GpuBlendComponent {
105 operation: Some(blend_operation_to_wasi(component.operation)),
106 src_factor: Some(blend_factor_to_wasi(component.src_factor)),
107 dst_factor: Some(blend_factor_to_wasi(component.dst_factor)),
108 }
109}
110
111pub fn blend_state_to_wasi(state: &BlendState) -> GpuBlendState {
112 GpuBlendState {
113 color: blend_component_to_wasi(&state.color),
114 alpha: blend_component_to_wasi(&state.alpha),
115 }
116}
117
118pub fn color_target_to_wasi(target: &ColorTargetState) -> GpuColorTargetState {
119 GpuColorTargetState {
120 format: texture_format_to_wasi(target.format),
121 blend: target.blend.as_ref().map(blend_state_to_wasi),
122 write_mask: Some(color_writes_to_wasi(target.write_mask)),
123 }
124}
125
126pub fn primitive_topology_to_wasi(topology: PrimitiveTopology) -> GpuPrimitiveTopology {
127 match topology {
128 PrimitiveTopology::PointList => GpuPrimitiveTopology::PointList,
129 PrimitiveTopology::LineList => GpuPrimitiveTopology::LineList,
130 PrimitiveTopology::LineStrip => GpuPrimitiveTopology::LineStrip,
131 PrimitiveTopology::TriangleList => GpuPrimitiveTopology::TriangleList,
132 PrimitiveTopology::TriangleStrip => GpuPrimitiveTopology::TriangleStrip,
133 }
134}
135
136pub fn front_face_to_wasi(front_face: FrontFace) -> GpuFrontFace {
137 match front_face {
138 FrontFace::Ccw => GpuFrontFace::Ccw,
139 FrontFace::Cw => GpuFrontFace::Cw,
140 }
141}
142
143pub fn cull_mode_to_wasi(cull_mode: Option<Face>) -> GpuCullMode {
144 match cull_mode {
145 None => GpuCullMode::None,
146 Some(Face::Front) => GpuCullMode::Front,
147 Some(Face::Back) => GpuCullMode::Back,
148 }
149}
150
151pub fn primitive_state_to_wasi(state: &PrimitiveState) -> GpuPrimitiveState {
152 match state.polygon_mode {
153 PolygonMode::Fill => {}
154 PolygonMode::Line => feature_gap(Features::POLYGON_MODE_LINE, "PolygonMode::Line"),
155 PolygonMode::Point => feature_gap(Features::POLYGON_MODE_POINT, "PolygonMode::Point"),
156 }
157 if state.conservative {
158 feature_gap(
159 Features::CONSERVATIVE_RASTERIZATION,
160 "PrimitiveState::conservative",
161 );
162 }
163 GpuPrimitiveState {
164 topology: Some(primitive_topology_to_wasi(state.topology)),
165 strip_index_format: state.strip_index_format.map(index_format_to_wasi),
166 front_face: Some(front_face_to_wasi(state.front_face)),
167 cull_mode: Some(cull_mode_to_wasi(state.cull_mode)),
168 unclipped_depth: Some(state.unclipped_depth),
169 }
170}
171
172pub fn multisample_state_to_wasi(state: &MultisampleState) -> GpuMultisampleState {
173 GpuMultisampleState {
174 count: Some(state.count),
175 mask: Some(sample_mask_to_wasi(state.mask)),
176 alpha_to_coverage_enabled: Some(state.alpha_to_coverage_enabled),
177 }
178}
179
180fn sample_mask_to_wasi(mask: u64) -> u32 {
183 mask as u32
184}
185
186pub fn vertex_step_mode_to_wasi(mode: VertexStepMode) -> GpuVertexStepMode {
187 match mode {
188 VertexStepMode::Vertex => GpuVertexStepMode::Vertex,
189 VertexStepMode::Instance => GpuVertexStepMode::Instance,
190 }
191}
192
193pub fn vertex_attribute_to_wasi(attribute: &VertexAttribute) -> GpuVertexAttribute {
194 GpuVertexAttribute {
195 format: vertex_format_to_wasi(attribute.format),
196 offset: attribute.offset,
197 shader_location: attribute.shader_location,
198 }
199}
200
201pub fn vertex_buffer_layout_to_wasi(layout: &VertexBufferLayout<'_>) -> GpuVertexBufferLayout {
202 GpuVertexBufferLayout {
203 array_stride: layout.array_stride,
204 step_mode: Some(vertex_step_mode_to_wasi(layout.step_mode)),
205 attributes: layout
206 .attributes
207 .iter()
208 .map(vertex_attribute_to_wasi)
209 .collect(),
210 }
211}
212
213pub fn store_op_to_wasi(op: StoreOp) -> GpuStoreOp {
214 match op {
215 StoreOp::Store => GpuStoreOp::Store,
216 StoreOp::Discard => GpuStoreOp::Discard,
217 }
218}
219
220#[derive(Debug, Clone, Copy)]
222pub struct AttachmentOps<V> {
223 pub load: GpuLoadOp,
224 pub clear_value: Option<V>,
225 pub store: GpuStoreOp,
226}
227
228pub fn operations_to_wasi<V: Clone>(ops: &Operations<V>, undefined_value: V) -> AttachmentOps<V> {
231 let (load, clear_value) = match &ops.load {
232 LoadOp::Clear(value) => (GpuLoadOp::Clear, Some(value.clone())),
233 LoadOp::Load => (GpuLoadOp::Load, None),
234 LoadOp::DontCare(_) => (GpuLoadOp::Clear, Some(undefined_value)),
235 };
236 AttachmentOps {
237 load,
238 clear_value,
239 store: store_op_to_wasi(ops.store),
240 }
241}