// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// ComputePipelineDescriptor builder.
///
/// The builder is MoonBit-managed. If you call `finish_descriptor_ptr`, it
/// transfers the underlying descriptor out of the builder, and you must free
/// the returned pointer via `@c.compute_pipeline_descriptor_free(desc)`.
/// `create_pipeline(device)` is the consuming high-level path and frees the
/// builder automatically.
pub fn ComputePipelineDescBuilder::new(
shader_module : ShaderModule,
layout? : PipelineLayout = { raw: @c.null_pipeline_layout() },
) -> ComputePipelineDescBuilder raise ComputePipelineDescError {
let raw = @c.compute_pipeline_desc_builder_new(layout.raw, shader_module.raw)
if @c.compute_pipeline_desc_builder_is_null(raw) {
raise ComputePipelineDescError(COMPUTE_PIPELINE_DESC_ERR_OOM, 0U, 0U)
}
{ raw, }
}
///|
pub fn ComputePipelineDescBuilder::set_entry_point(
self : ComputePipelineDescBuilder,
entry_point : String,
) -> Unit raise ComputePipelineDescError {
let entry_bytes = utf8_bytes(entry_point)
let err = @c.compute_pipeline_desc_builder_set_entry_point_utf8(
self.raw,
entry_bytes,
entry_bytes.length().to_uint64(),
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn ComputePipelineDescBuilder::finish_descriptor_ptr(
self : ComputePipelineDescBuilder,
) -> @c.WGPUComputePipelineDescriptorPtr raise ComputePipelineDescError {
let desc = @c.compute_pipeline_desc_builder_take_descriptor(self.raw)
if @c.compute_pipeline_descriptor_ptr_is_null(desc) {
raise ComputePipelineDescError(
COMPUTE_PIPELINE_DESC_ERR_NULL_DESCRIPTOR,
0U,
0U,
)
}
desc
}
///|
pub fn ComputePipelineDescBuilder::create_pipeline(
self : ComputePipelineDescBuilder,
device : Device,
) -> ComputePipeline raise ComputePipelineDescError {
try {
let desc = self.finish_descriptor_ptr()
let pipeline = device.create_compute_pipeline_ptr(desc)
@c.compute_pipeline_descriptor_free(desc)
self.free()
pipeline
} catch {
e => {
self.free()
raise e
}
}
}
///|
pub fn ComputePipelineDescBuilder::free(
self : ComputePipelineDescBuilder,
) -> Unit {
@c.compute_pipeline_desc_builder_free(self.raw)
}
///|
pub fn ComputePipelineDescBuilder::last_error(
self : ComputePipelineDescBuilder,
) -> ComputePipelineDescError {
let code = @c.compute_pipeline_desc_builder_last_error_u32(self.raw)
let args = @c.compute_pipeline_desc_builder_last_error_args_u64(self.raw)
let a = (args >> 32).to_uint()
let b = (args & 0xFFFFFFFFUL).to_uint()
ComputePipelineDescError(code, a, b)
}
///|
pub fn ComputePipelineDescError::message(
self : ComputePipelineDescError,
) -> String {
let ComputePipelineDescError(code, _, _) = self
if code == COMPUTE_PIPELINE_DESC_ERR_NULL_DESCRIPTOR {
"descriptor is NULL"
} else if code == COMPUTE_PIPELINE_DESC_ERR_ENTRY_EMPTY {
"entry point is empty"
} else if code == COMPUTE_PIPELINE_DESC_ERR_ENTRY_TOO_LONG {
"entry point too long"
} else if code == COMPUTE_PIPELINE_DESC_ERR_OOM {
"allocation failed"
} else {
"unknown error"
}
}
///|
pub const COMPUTE_PIPELINE_DESC_ERR_NULL_DESCRIPTOR : UInt = 1U
///|
pub const COMPUTE_PIPELINE_DESC_ERR_ENTRY_EMPTY : UInt = 2U
///|
pub const COMPUTE_PIPELINE_DESC_ERR_ENTRY_TOO_LONG : UInt = 3U
///|
pub const COMPUTE_PIPELINE_DESC_ERR_OOM : UInt = 4U
///|
/// RenderPipelineDescriptor arena builder (MVP).
///
/// The builder is MoonBit-managed. If you call `finish_descriptor_ptr`, it
/// transfers the underlying descriptor allocation out of the builder, and you
/// must free the returned pointer via `@c.render_pipeline_descriptor_free(desc)`.
/// `create_pipeline(device)` is the consuming high-level path and frees the
/// builder automatically.
pub fn RenderPipelineDescBuilder::new(
shader_module : ShaderModule,
layout? : PipelineLayout = { raw: @c.null_pipeline_layout() },
) -> RenderPipelineDescBuilder raise RenderPipelineDescError {
let raw = @c.render_pipeline_desc_builder_new(layout.raw, shader_module.raw)
if @c.render_pipeline_desc_builder_is_null(raw) {
raise RenderPipelineDescError(RENDER_PIPELINE_DESC_ERR_OOM, 0U, 0U)
}
{ raw, }
}
///|
pub fn RenderPipelineDescBuilder::set_entry_points(
self : RenderPipelineDescBuilder,
vs_entry : String,
fs_entry : String,
) -> Unit raise RenderPipelineDescError {
let vs_bytes = utf8_bytes(vs_entry)
let fs_bytes = utf8_bytes(fs_entry)
let err = @c.render_pipeline_desc_builder_set_entry_points_utf8(
self.raw,
vs_bytes,
vs_bytes.length().to_uint64(),
fs_bytes,
fs_bytes.length().to_uint64(),
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_color_target_format(
self : RenderPipelineDescBuilder,
format : TextureFormat,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_color_target_format(
self.raw,
format.raw,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_color_target_count(
self : RenderPipelineDescBuilder,
count_u32 : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_color_target_count(
self.raw,
count_u32,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_color_target_format_at(
self : RenderPipelineDescBuilder,
index_u32 : UInt,
format : TextureFormat,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_color_target_format_at(
self.raw,
index_u32,
format.raw,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_color_target_unused_at(
self : RenderPipelineDescBuilder,
index_u32 : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_color_target_unused_at(
self.raw,
index_u32,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_color_target_write_mask(
self : RenderPipelineDescBuilder,
write_mask_u64 : UInt64,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_color_target_write_mask(
self.raw,
write_mask_u64,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_color_target_write_mask_at(
self : RenderPipelineDescBuilder,
index_u32 : UInt,
write_mask_u64 : UInt64,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_color_target_write_mask_at(
self.raw,
index_u32,
write_mask_u64,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_blend_components(
self : RenderPipelineDescBuilder,
color_src_factor_u32 : UInt,
color_dst_factor_u32 : UInt,
color_operation_u32 : UInt,
alpha_src_factor_u32 : UInt,
alpha_dst_factor_u32 : UInt,
alpha_operation_u32 : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_blend_components(
self.raw,
color_src_factor_u32,
color_dst_factor_u32,
color_operation_u32,
alpha_src_factor_u32,
alpha_dst_factor_u32,
alpha_operation_u32,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::enable_alpha_blend(
self : RenderPipelineDescBuilder,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_enable_alpha_blend(self.raw)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::disable_blend(
self : RenderPipelineDescBuilder,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_disable_blend(self.raw)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_vertex_buffer_layout(
self : RenderPipelineDescBuilder,
array_stride : UInt64,
step_mode_u32 : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_vertex_buffer_layout(
self.raw,
array_stride,
step_mode_u32,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::add_vertex_buffer_layout(
self : RenderPipelineDescBuilder,
array_stride : UInt64,
step_mode_u32 : UInt,
) -> UInt raise RenderPipelineDescError {
let idx = @c.render_pipeline_desc_builder_add_vertex_buffer_layout(
self.raw,
array_stride,
step_mode_u32,
)
let err = @c.render_pipeline_desc_builder_last_error_u32(self.raw)
if err != 0U {
raise self.last_error()
}
idx
}
///|
pub fn RenderPipelineDescBuilder::add_vertex_attribute(
self : RenderPipelineDescBuilder,
format_u32 : UInt,
offset : UInt64,
shader_location : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_add_vertex_attribute(
self.raw,
format_u32,
offset,
shader_location,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_topology_u32(
self : RenderPipelineDescBuilder,
topology_u32 : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_topology(self.raw, topology_u32)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_strip_index_format_u32(
self : RenderPipelineDescBuilder,
index_format_u32 : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_strip_index_format(
self.raw,
index_format_u32,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_cull_mode_u32(
self : RenderPipelineDescBuilder,
cull_mode_u32 : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_cull_mode(
self.raw,
cull_mode_u32,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_unclipped_depth(
self : RenderPipelineDescBuilder,
unclipped_depth : Bool,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_unclipped_depth(
self.raw,
unclipped_depth,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_vertex_module(
self : RenderPipelineDescBuilder,
shader_module : ShaderModule,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_vertex_module(
self.raw,
shader_module.raw,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_fragment_module(
self : RenderPipelineDescBuilder,
shader_module : ShaderModule,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_fragment_module(
self.raw,
shader_module.raw,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::clear_fragment(
self : RenderPipelineDescBuilder,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_clear_fragment(self.raw)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_polygon_mode_u32(
self : RenderPipelineDescBuilder,
polygon_mode_u32 : UInt,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_polygon_mode(
self.raw,
polygon_mode_u32,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_conservative_rasterization(
self : RenderPipelineDescBuilder,
conservative : Bool,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_conservative(
self.raw,
conservative,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::clear_primitive_extras(
self : RenderPipelineDescBuilder,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_clear_primitive_extras(self.raw)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_depth_stencil(
self : RenderPipelineDescBuilder,
depth_format : TextureFormat,
depth_write_enabled? : Bool = true,
depth_compare_u32? : UInt = COMPARE_FUNCTION_LESS,
depth_bias? : Int = 0,
depth_bias_slope_scale? : Float = 0.0,
depth_bias_clamp? : Float = 0.0,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_depth_stencil(
self.raw,
depth_format.raw,
depth_write_enabled,
depth_compare_u32,
depth_bias,
depth_bias_slope_scale,
depth_bias_clamp,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::set_multisample(
self : RenderPipelineDescBuilder,
count_u32 : UInt,
mask_u32? : UInt = 0xFFFFFFFFU,
alpha_to_coverage_enabled? : Bool = false,
) -> Unit raise RenderPipelineDescError {
let err = @c.render_pipeline_desc_builder_set_multisample(
self.raw,
count_u32,
mask_u32,
alpha_to_coverage_enabled,
)
if err != 0U {
raise self.last_error()
}
()
}
///|
pub fn RenderPipelineDescBuilder::finish_descriptor_ptr(
self : RenderPipelineDescBuilder,
) -> @c.WGPURenderPipelineDescriptorPtr raise RenderPipelineDescError {
let desc = @c.render_pipeline_desc_builder_finish(self.raw)
if @c.render_pipeline_descriptor_ptr_is_null(desc) {
raise self.last_error()
}
desc
}
///|
pub fn RenderPipelineDescBuilder::create_pipeline(
self : RenderPipelineDescBuilder,
device : Device,
) -> RenderPipeline raise RenderPipelineDescError {
try {
let desc = self.finish_descriptor_ptr()
let pipeline = device.create_render_pipeline_ptr(desc)
@c.render_pipeline_descriptor_free(desc)
self.free()
pipeline
} catch {
e => {
self.free()
raise e
}
}
}
///|
pub fn RenderPipelineDescBuilder::free(
self : RenderPipelineDescBuilder,
) -> Unit {
@c.render_pipeline_desc_builder_free(self.raw)
}
///|
pub fn RenderPipelineDescBuilder::last_error(
self : RenderPipelineDescBuilder,
) -> RenderPipelineDescError {
let code = @c.render_pipeline_desc_builder_last_error_u32(self.raw)
let args = @c.render_pipeline_desc_builder_last_error_args_u64(self.raw)
let a = (args >> 32).to_uint()
let b = (args & 0xFFFFFFFFUL).to_uint()
RenderPipelineDescError(code, a, b)
}
///|
pub fn RenderPipelineDescError::message(
self : RenderPipelineDescError,
) -> String {
let RenderPipelineDescError(code, _, _) = self
if code == RENDER_PIPELINE_DESC_ERR_NULL_BUILDER {
"builder is NULL"
} else if code == RENDER_PIPELINE_DESC_ERR_ENTRY_EMPTY {
"entry point is empty"
} else if code == RENDER_PIPELINE_DESC_ERR_ENTRY_TOO_LONG {
"entry point too long"
} else if code == RENDER_PIPELINE_DESC_ERR_COLOR_TARGET_COUNT_ZERO {
"color target count must be >= 1"
} else if code == RENDER_PIPELINE_DESC_ERR_COLOR_TARGET_COUNT_EXCEEDS_MAX {
"color target count exceeds max"
} else if code == RENDER_PIPELINE_DESC_ERR_COLOR_TARGET_INDEX_OOB {
"color target index out of range"
} else if code == RENDER_PIPELINE_DESC_ERR_NO_VERTEX_BUFFER_LAYOUT {
"no vertex buffer layout is set"
} else if code == RENDER_PIPELINE_DESC_ERR_VERTEX_BUFFER_LAYOUT_EXCEEDS_MAX {
"vertex buffer layout count exceeds max"
} else if code == RENDER_PIPELINE_DESC_ERR_VERTEX_ATTRIBUTE_EXCEEDS_MAX {
"vertex attribute count exceeds max"
} else if code == RENDER_PIPELINE_DESC_ERR_INTERNAL {
"internal error"
} else if code == RENDER_PIPELINE_DESC_ERR_OOM {
"allocation failed"
} else {
"unknown error"
}
}
///|
pub const RENDER_PIPELINE_DESC_ERR_NULL_BUILDER : UInt = 1U
///|
pub const RENDER_PIPELINE_DESC_ERR_ENTRY_EMPTY : UInt = 2U
///|
pub const RENDER_PIPELINE_DESC_ERR_ENTRY_TOO_LONG : UInt = 3U
///|
pub const RENDER_PIPELINE_DESC_ERR_COLOR_TARGET_COUNT_ZERO : UInt = 4U
///|
pub const RENDER_PIPELINE_DESC_ERR_COLOR_TARGET_COUNT_EXCEEDS_MAX : UInt = 5U
///|
pub const RENDER_PIPELINE_DESC_ERR_COLOR_TARGET_INDEX_OOB : UInt = 6U
///|
pub const RENDER_PIPELINE_DESC_ERR_NO_VERTEX_BUFFER_LAYOUT : UInt = 7U
///|
pub const RENDER_PIPELINE_DESC_ERR_VERTEX_BUFFER_LAYOUT_EXCEEDS_MAX : UInt = 8U
///|
pub const RENDER_PIPELINE_DESC_ERR_VERTEX_ATTRIBUTE_EXCEEDS_MAX : UInt = 9U
///|
pub const RENDER_PIPELINE_DESC_ERR_INTERNAL : UInt = 10U
///|
pub const RENDER_PIPELINE_DESC_ERR_OOM : UInt = 11U