// 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.
///|
pub fn Instance::create() -> Instance raise WgpuError {
require_native()
{ raw: @c.create_instance() }
}
///|
pub fn Instance::create_ptr(
descriptor : @c.WGPUInstanceDescriptorPtr,
) -> Instance raise WgpuError {
require_native()
{ raw: @c.wgpuCreateInstance(descriptor) }
}
///|
/// Create an instance with explicit native extras.
///
/// `dxc_path` is currently reserved and behaves as a documented no-op because
/// published upstream binaries do not share a stable `WGPUInstanceExtras`
/// layout for that field yet.
pub fn Instance::create_with_extras_u32(
backends_u64? : UInt64 = INSTANCE_BACKEND_ALL,
flags_u32? : UInt = INSTANCE_FLAG_DEFAULT,
dx12_shader_compiler_u32? : UInt = DX12_COMPILER_UNDEFINED,
gles3_minor_version_u32? : UInt = GLES3_MINOR_VERSION_AUTOMATIC,
gl_fence_behaviour_u32? : UInt = GL_FENCE_BEHAVIOUR_NORMAL,
dxc_max_shader_model_u32? : UInt = DXC_MAX_SHADER_MODEL_V6_0,
dx12_presentation_system_u32? : UInt = DX12_SWAPCHAIN_KIND_UNDEFINED,
dxc_path? : String = "",
) -> Instance raise WgpuError {
require_native()
let dxc_path_utf8 = utf8_bytes(dxc_path)
{
raw: @c.create_instance_with_extras_utf8(
backends_u64,
flags_u32,
dx12_shader_compiler_u32,
dxc_path_utf8,
dxc_path_utf8.length().to_uint64(),
gles3_minor_version_u32,
gl_fence_behaviour_u32,
dxc_max_shader_model_u32,
dx12_presentation_system_u32,
),
}
}
///|
pub fn Instance::request_adapter_sync(
self : Instance,
) -> Adapter raise WgpuError {
require_native()
// Primary path: enumerate adapters (wgpu-native extra API).
// In some CI environments, requestAdapter may report "Success" but still
// return a null adapter handle.
if native_has_symbol("wgpuInstanceEnumerateAdapters") {
let raw = if platform_is_linux() {
let a0 = @c.instance_enumerate_adapter_first_vulkan(self.raw)
if !@c.adapter_is_null(a0) {
a0
} else {
@c.instance_enumerate_adapter_first_gl(self.raw)
}
} else if platform_is_windows() {
let a0 = @c.instance_enumerate_adapter_first_vulkan(self.raw)
if !@c.adapter_is_null(a0) {
a0
} else {
let a1 = @c.instance_enumerate_adapter_first_dx12(self.raw)
if !@c.adapter_is_null(a1) {
a1
} else {
let a2 = @c.instance_enumerate_adapter_first_gl(self.raw)
if !@c.adapter_is_null(a2) {
a2
} else {
@c.instance_enumerate_adapter_first_dx11(self.raw)
}
}
}
} else if platform_is_macos() {
@c.instance_enumerate_adapter_first_metal(self.raw)
} else {
@c.instance_enumerate_adapter_first_primary(self.raw)
}
if !@c.adapter_is_null(raw) {
return { raw, }
}
}
require_native_symbol("wgpuInstanceRequestAdapter")
require_native_symbol("wgpuInstanceProcessEvents")
// Best-effort strategy: the C API requires featureLevel to be specified, and
// CI environments may only expose software adapters. Try a small matrix of
// request options before giving up.
let backend = if platform_is_linux() {
BACKEND_TYPE_VULKAN
} else if platform_is_windows() {
BACKEND_TYPE_D3_D12
} else if platform_is_macos() {
BACKEND_TYPE_METAL
} else {
BACKEND_TYPE_UNDEFINED
}
fn try_request(
feature_level_u32 : UInt,
force_fallback_adapter : Bool,
backend_type_u32 : UInt,
) -> @c.Adapter {
@c.instance_request_adapter_sync_options_u32(
self.raw,
feature_level_u32,
POWER_PREFERENCE_UNDEFINED,
force_fallback_adapter,
backend_type_u32,
@c.null_surface(),
)
}
let attempts : Array[(UInt, Bool, UInt)] = [
// Prefer the default backend selection first.
(FEATURE_LEVEL_CORE, false, BACKEND_TYPE_UNDEFINED),
(FEATURE_LEVEL_CORE, false, backend),
// Then allow fallback adapters.
(FEATURE_LEVEL_CORE, true, BACKEND_TYPE_UNDEFINED),
(FEATURE_LEVEL_CORE, true, backend),
// Compatibility profile can be necessary for some software adapters.
(FEATURE_LEVEL_COMPATIBILITY, false, BACKEND_TYPE_UNDEFINED),
(FEATURE_LEVEL_COMPATIBILITY, false, backend),
(FEATURE_LEVEL_COMPATIBILITY, true, BACKEND_TYPE_UNDEFINED),
(FEATURE_LEVEL_COMPATIBILITY, true, backend),
]
for attempt in attempts {
let (feature_level_u32, force_fallback_adapter, backend_type_u32) = attempt
let raw = try_request(
feature_level_u32, force_fallback_adapter, backend_type_u32,
)
if !@c.adapter_is_null(raw) {
return { raw, }
}
}
// Preserve the last observed status from the C helper.
raise WgpuRequestAdapterFailed(
@c.instance_request_adapter_sync_last_status_u32(),
)
}
///|
pub fn Instance::request_adapter_sync_ptr(
self : Instance,
options : @c.WGPURequestAdapterOptionsPtr,
) -> Adapter raise WgpuError {
require_native_symbol("wgpuInstanceRequestAdapter")
require_native_symbol("wgpuInstanceProcessEvents")
let raw = @c.instance_request_adapter_sync_ptr(self.raw, options)
if @c.adapter_is_null(raw) {
raise WgpuRequestAdapterFailed(
@c.instance_request_adapter_sync_last_status_u32(),
)
}
{ raw, }
}
///|
pub fn Instance::request_adapter_sync_options_u32(
self : Instance,
feature_level_u32? : UInt = FEATURE_LEVEL_CORE,
power_preference_u32? : UInt = POWER_PREFERENCE_UNDEFINED,
force_fallback_adapter? : Bool = false,
backend_type_u32? : UInt = BACKEND_TYPE_UNDEFINED,
) -> Adapter raise WgpuError {
require_native()
require_native_symbol("wgpuInstanceRequestAdapter")
require_native_symbol("wgpuInstanceProcessEvents")
let raw = @c.instance_request_adapter_sync_options_u32(
self.raw,
feature_level_u32,
power_preference_u32,
force_fallback_adapter,
backend_type_u32,
@c.null_surface(),
)
if @c.adapter_is_null(raw) {
raise WgpuRequestAdapterFailed(
@c.instance_request_adapter_sync_last_status_u32(),
)
}
{ raw, }
}
///|
pub fn Instance::request_adapter_sync_options_surface_u32(
self : Instance,
surface : Surface,
feature_level_u32? : UInt = FEATURE_LEVEL_CORE,
power_preference_u32? : UInt = POWER_PREFERENCE_UNDEFINED,
force_fallback_adapter? : Bool = false,
backend_type_u32? : UInt = BACKEND_TYPE_UNDEFINED,
) -> Adapter raise WgpuError {
require_native()
require_native_symbol("wgpuInstanceRequestAdapter")
require_native_symbol("wgpuInstanceProcessEvents")
let raw = @c.instance_request_adapter_sync_options_u32(
self.raw,
feature_level_u32,
power_preference_u32,
force_fallback_adapter,
backend_type_u32,
surface.raw,
)
if @c.adapter_is_null(raw) {
raise WgpuRequestAdapterFailed(
@c.instance_request_adapter_sync_last_status_u32(),
)
}
{ raw, }
}
///|
pub fn Instance::request_adapter_future_id_u64(
self : Instance,
options? : @c.WGPURequestAdapterOptionsPtr = @c.null_request_adapter_options_ptr(),
) -> UInt64 {
if !native_available() || !native_supported() {
return 0UL
}
if !native_has_symbol("wgpuInstanceRequestAdapter") {
return 0UL
}
@c.instance_request_adapter_future_id_u64(self.raw, options)
}
///|
pub fn Instance::request_adapter_async_status_u32(
self : Instance,
future_id : UInt64,
) -> UInt {
let _ = self
@c.instance_request_adapter_async_status_u32(future_id)
}
///|
pub fn Instance::request_adapter_async_adapter(
self : Instance,
future_id : UInt64,
) -> Adapter {
let _ = self
{ raw: @c.instance_request_adapter_async_adapter(future_id) }
}
///|
pub fn Instance::request_adapter_async_message(
self : Instance,
future_id : UInt64,
) -> String {
let _ = self
let len = @c.instance_request_adapter_async_message_utf8_len(future_id)
if len == 0UL {
""
} else {
let out = Bytes::new(len.to_int())
let ok = @c.instance_request_adapter_async_message_utf8(future_id, out, len)
if ok {
@utf8.decode_lossy(out[:], ignore_bom=true)
} else {
""
}
}
}
///|
pub fn Instance::request_adapter_async_clear(
self : Instance,
future_id : UInt64,
) -> Unit {
let _ = self
@c.instance_request_adapter_async_clear(future_id)
}
///|
pub fn Instance::request_adapter_async_take_or_raise(
self : Instance,
future_id : UInt64,
) -> Adapter raise WgpuError {
let status = self.request_adapter_async_status_u32(future_id)
let adapter = self.request_adapter_async_adapter(future_id)
self.request_adapter_async_clear(future_id)
if status == REQUEST_ADAPTER_STATUS_SUCCESS &&
!@c.adapter_is_null(adapter.raw) {
adapter
} else {
raise WgpuRequestAdapterFailed(status)
}
}
///|
pub fn Instance::process_events(self : Instance) -> Unit {
@c.instance_process_events(self.raw)
}
///|
pub fn Instance::wait_any_one(
self : Instance,
future_id : UInt64,
timeout_ns? : UInt64 = 0UL,
) -> WaitAnyResult {
let packed = @c.instance_wait_any_one_packed_u64(
self.raw,
future_id,
timeout_ns,
)
let status = (packed & 0xFFFF_FFFFUL).to_int().reinterpret_as_uint()
let completed = packed >> 32 != 0UL
{ status, completed }
}
///|
pub fn Instance::wait_any_one_or_raise(
self : Instance,
future_id : UInt64,
timeout_ns? : UInt64 = 0UL,
) -> WaitAnyResult raise WaitAnyError {
let result = self.wait_any_one(future_id, timeout_ns~)
if result.status != WAIT_STATUS_SUCCESS {
raise WaitAnyError(result.status)
}
result
}
///|
pub fn Instance::enumerate_adapters_count_metal(self : Instance) -> UInt64 {
@c.instance_enumerate_adapters_count_metal(self.raw)
}
///|
pub fn Instance::enumerate_adapters_count_vulkan(self : Instance) -> UInt64 {
@c.instance_enumerate_adapters_count_vulkan(self.raw)
}
///|
pub fn Instance::wgsl_language_features_count_u64(self : Instance) -> UInt64 {
@c.instance_wgsl_language_features_count_u64(self.raw)
}
///|
pub fn Instance::generate_report(self : Instance) -> GlobalReport {
{ raw: @c.instance_generate_report_new(self.raw) }
}
///|
pub fn Instance::create_surface_metal_layer(self : Instance) -> Surface {
let layer = @c.cametallayer_new()
let surface = @c.instance_create_surface_metal_layer(self.raw, layer)
{
raw: surface,
layer,
layer_owner: @c.cametallayer_owner_new(layer),
owner_window_handle: None,
owner_display_handle: None,
}
}
///|
/// Create a macOS Metal surface from an `NSView*`.
///
/// The view remains host-owned. The returned `Surface` retains the attached
/// `CAMetalLayer` and releases that retain in `Surface::release`.
pub fn Instance::create_surface_macos_ns_view(
self : Instance,
ns_view : @c.OpaquePtr,
) -> Surface raise SurfaceCreateError {
let layer = @c.macos_ns_view_prepare_metal_layer(ns_view)
if @c.opaque_ptr_is_null(layer) {
raise SurfaceCreateError(@c.macos_surface_last_status_u32())
}
let surface = @c.instance_create_surface_metal_layer(self.raw, layer)
if @c.surface_is_null(surface) {
@c.cametallayer_release(layer)
raise SurfaceCreateError(SURFACE_CREATE_STATUS_CREATE_SURFACE_FAILED)
}
{
raw: surface,
layer,
layer_owner: @c.cametallayer_owner_new(layer),
owner_window_handle: None,
owner_display_handle: None,
}
}
///|
/// Create a macOS Metal surface from an `NSView*` address stored as `UInt64`.
///
/// This compatibility entry is intended for window packages that expose native
/// view pointers as integer handles. The value must be an `NSView*` address.
pub fn Instance::create_surface_macos_ns_view_u64(
self : Instance,
ns_view : UInt64,
) -> Surface raise SurfaceCreateError {
self.create_surface_macos_ns_view(@c.opaque_ptr_from_u64(ns_view))
}
///|
/// Create a surface from Wayland handles (`wl_display*`, `wl_surface*`).
///
/// This is intended for Linux + Vulkan setups. The pointers are passed through
/// as opaque handles (you manage their lifetime on the host side).
pub fn Instance::create_surface_wayland(
self : Instance,
display : @c.OpaquePtr,
surface : @c.OpaquePtr,
) -> Surface {
{
raw: @c.instance_create_surface_wayland(self.raw, display, surface),
layer: @c.null_opaque_ptr(),
layer_owner: @c.null_opaque_ptr(),
owner_window_handle: None,
owner_display_handle: None,
}
}
///|
/// Create a surface from XCB handles (`xcb_connection_t*`, `xcb_window_t`).
pub fn Instance::create_surface_xcb(
self : Instance,
connection : @c.OpaquePtr,
window : UInt,
) -> Surface {
{
raw: @c.instance_create_surface_xcb(self.raw, connection, window),
layer: @c.null_opaque_ptr(),
layer_owner: @c.null_opaque_ptr(),
owner_window_handle: None,
owner_display_handle: None,
}
}
///|
/// Create a surface from Xlib handles (`Display*`, `Window`).
pub fn Instance::create_surface_xlib(
self : Instance,
display : @c.OpaquePtr,
window : UInt64,
) -> Surface {
{
raw: @c.instance_create_surface_xlib(self.raw, display, window),
layer: @c.null_opaque_ptr(),
layer_owner: @c.null_opaque_ptr(),
owner_window_handle: None,
owner_display_handle: None,
}
}
///|
/// Create a surface from Android handle (`ANativeWindow*`).
pub fn Instance::create_surface_android_native_window(
self : Instance,
window : @c.OpaquePtr,
) -> Surface {
{
raw: @c.instance_create_surface_android_native_window(self.raw, window),
layer: @c.null_opaque_ptr(),
layer_owner: @c.null_opaque_ptr(),
owner_window_handle: None,
owner_display_handle: None,
}
}
///|
/// Create a surface from Windows XAML SwapChainPanel native handle.
pub fn Instance::create_surface_swap_chain_panel(
self : Instance,
panel_native : @c.OpaquePtr,
) -> Surface {
{
raw: @c.instance_create_surface_swap_chain_panel(self.raw, panel_native),
layer: @c.null_opaque_ptr(),
layer_owner: @c.null_opaque_ptr(),
owner_window_handle: None,
owner_display_handle: None,
}
}
///|
/// Create a surface from Windows handles (`HINSTANCE`, `HWND`).
///
/// The pointers are passed through as opaque handles (you manage their lifetime
/// on the host side).
pub fn Instance::create_surface_windows_hwnd(
self : Instance,
hinstance : @c.OpaquePtr,
hwnd : @c.OpaquePtr,
) -> Surface {
{
raw: @c.instance_create_surface_windows_hwnd(self.raw, hinstance, hwnd),
layer: @c.null_opaque_ptr(),
layer_owner: @c.null_opaque_ptr(),
owner_window_handle: None,
owner_display_handle: None,
}
}
///|
pub fn GlobalReport::surfaces_num_allocated(self : GlobalReport) -> UInt64 {
@c.global_report_surfaces_num_allocated(self.raw)
}
///|
pub fn GlobalReport::surfaces_num_kept_from_user(self : GlobalReport) -> UInt64 {
@c.global_report_surfaces_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::surfaces_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_surfaces_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::surfaces_element_size(self : GlobalReport) -> UInt64 {
@c.global_report_surfaces_element_size(self.raw)
}
///|
pub fn GlobalReport::hub_devices_num_allocated(self : GlobalReport) -> UInt64 {
@c.global_report_hub_devices_num_allocated(self.raw)
}
///|
pub fn GlobalReport::hub_devices_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_devices_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_devices_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_devices_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_devices_element_size(self : GlobalReport) -> UInt64 {
@c.global_report_hub_devices_element_size(self.raw)
}
///|
pub fn GlobalReport::hub_queues_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_queues_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_queues_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_queues_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_buffers_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_buffers_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_buffers_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_buffers_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_textures_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_textures_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_textures_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_textures_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_texture_views_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_texture_views_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_texture_views_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_texture_views_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_samplers_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_samplers_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_samplers_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_samplers_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_shader_modules_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_shader_modules_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_shader_modules_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_shader_modules_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_pipeline_layouts_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_pipeline_layouts_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_pipeline_layouts_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_pipeline_layouts_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_bind_group_layouts_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_bind_group_layouts_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_bind_group_layouts_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_bind_group_layouts_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_bind_groups_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_bind_groups_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_bind_groups_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_bind_groups_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_command_buffers_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_command_buffers_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_command_buffers_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_command_buffers_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_render_pipelines_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_render_pipelines_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_render_pipelines_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_render_pipelines_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_compute_pipelines_num_kept_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_compute_pipelines_num_kept_from_user(self.raw)
}
///|
pub fn GlobalReport::hub_compute_pipelines_num_released_from_user(
self : GlobalReport,
) -> UInt64 {
@c.global_report_hub_compute_pipelines_num_released_from_user(self.raw)
}
///|
pub fn GlobalReport::release(self : GlobalReport) -> Unit {
@c.global_report_free(self.raw)
}
///|
pub fn Instance::release(self : Instance) -> Unit {
@c.instance_release(self.raw)
}
///|
pub fn Instance::add_ref(self : Instance) -> Instance {
@c.wgpuInstanceAddRef(self.raw)
{ raw: self.raw }
}
///|
pub fn Instance::raw_handle(self : Instance) -> @c.Instance {
self.raw
}