/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
ext/webgpu/lib.rs
332 строки
9 KB
Leo Kettmeir
chore: update webgpu (#34319)
08 июн 2026, 23:29
Не верифицирован
08 июн 2026, 23:29
2b313e2
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. #![cfg(not(target_arch = "wasm32"))] #![warn(unsafe_op_in_unsafe_fn)] use std::cell::RefCell; use std::rc::Rc; use std::sync::Arc; use deno_core::GarbageCollected; use deno_core::OpState; use deno_core::cppgc::SameObject; use deno_core::op2; use deno_core::v8; use serde::Deserialize as _; use serde::de::IntoDeserializer; pub use wgpu_core; pub use wgpu_types; use wgpu_types::PowerPreference; use crate::error::GPUGenericError; pub mod adapter; mod bind_group; mod bind_group_layout; pub mod buffer; pub mod canvas; mod command_buffer; mod command_encoder; mod compute_pass; mod compute_pipeline; pub mod device; pub mod error; mod pipeline_layout; mod query_set; mod queue; mod render_bundle; mod render_pass; mod render_pipeline; mod sampler; mod shader; pub mod texture; mod webidl; pub const UNSTABLE_FEATURE_NAME: &str = "webgpu"; pub const DX12_COMPILER_ENV_VAR: &str = "DENO_WEBGPU_DX12_COMPILER"; #[allow(clippy::print_stdout, reason = "prints linker flags for build scripts")] pub fn print_linker_flags(name: &str) { if cfg!(windows) { // these dls load slowly, so delay loading them let dlls = [ // webgpu "d3dcompiler_47", "OPENGL32", "gdi32", "setupapi", "oleaut32", "combase", // network related functions "iphlpapi", // restart manager (only needed on the `deno clean` locked-file path) "rstrtmgr", // timer functions "winmm", // debugging/diagnostics (only needed on panic/crash) "dbghelp", "psapi", ]; for dll in dlls { println!("cargo:rustc-link-arg-bin={name}=/delayload:{dll}.dll"); } // enable delay loading println!("cargo:rustc-link-arg-bin={name}=delayimp.lib"); } } pub type Instance = Arc<wgpu_core::global::Global>; deno_core::extension!( deno_webgpu, deps = [deno_webidl, deno_web], ops = [ op_create_gpu, device::op_webgpu_device_start_capture, device::op_webgpu_device_stop_capture, ], objects = [ GPU, WGSLLanguageFeatures, adapter::GPUAdapter, adapter::GPUAdapterInfo, bind_group::GPUBindGroup, bind_group_layout::GPUBindGroupLayout, buffer::GPUBuffer, command_buffer::GPUCommandBuffer, command_encoder::GPUCommandEncoder, compute_pass::GPUComputePassEncoder, compute_pipeline::GPUComputePipeline, device::GPUDevice, device::GPUDeviceLostInfo, pipeline_layout::GPUPipelineLayout, query_set::GPUQuerySet, queue::GPUQueue, render_bundle::GPURenderBundle, render_bundle::GPURenderBundleEncoder, render_pass::GPURenderPassEncoder, render_pipeline::GPURenderPipeline, sampler::GPUSampler, shader::GPUCompilationInfo, shader::GPUCompilationMessage, shader::GPUShaderModule, adapter::GPUSupportedFeatures, adapter::GPUSupportedLimits, texture::GPUTexture, texture::GPUTextureView, texture::GPUExternalTexture, canvas::GPUCanvasContext, ], lazy_loaded_esm = ["01_webgpu.js"], lazy_loaded_js = ["00_init.js"], ); #[op2] #[cppgc] pub fn op_create_gpu( state: &mut OpState, scope: &mut v8::PinScope<'_, '_>, webidl_brand: v8::Local<v8::Value>, set_event_target_data: v8::Local<v8::Value>, uncaptured_error_event_class: v8::Local<v8::Value>, pipeline_error_class: v8::Local<v8::Value>, ) -> GPU { state.put(EventTargetSetup { brand: v8::Global::new(scope, webidl_brand), set_event_target_data: v8::Global::new(scope, set_event_target_data), }); state.put(ErrorEventClass(v8::Global::new( scope, uncaptured_error_event_class, ))); state.put(PipelineErrorClass(v8::Global::new( scope, pipeline_error_class, ))); GPU { wgsl_language_features: SameObject::new(), } } struct EventTargetSetup { brand: v8::Global<v8::Value>, set_event_target_data: v8::Global<v8::Value>, } struct ErrorEventClass(v8::Global<v8::Value>); struct PipelineErrorClass(v8::Global<v8::Value>); pub struct GPU { pub wgsl_language_features: SameObject<WGSLLanguageFeatures>, } // SAFETY: we're sure this can be GCed unsafe impl GarbageCollected for GPU { fn trace(&self, _visitor: &mut v8::cppgc::Visitor) {} fn get_name(&self) -> &'static std::ffi::CStr { c"GPU" } } #[op2] impl GPU { #[constructor] #[cppgc] fn constructor(_: bool) -> Result<GPU, GPUGenericError> { Err(GPUGenericError::InvalidConstructor) } #[cppgc] async fn request_adapter( &self, state: Rc<RefCell<OpState>>, #[webidl] options: adapter::GPURequestAdapterOptions, ) -> Option<adapter::GPUAdapter> { let mut state = state.borrow_mut(); let (backends, instance) = get_or_init_instance(&mut state, &options)?; let descriptor = wgpu_core::instance::RequestAdapterOptions { power_preference: options .power_preference .map(|pp| match pp { adapter::GPUPowerPreference::LowPower => PowerPreference::LowPower, adapter::GPUPowerPreference::HighPerformance => { PowerPreference::HighPerformance } }) .unwrap_or_default(), force_fallback_adapter: options.force_fallback_adapter, compatible_surface: None, // windowless }; let id = instance.request_adapter(&descriptor, backends, None).ok()?; Some(adapter::GPUAdapter { instance, features: SameObject::new(), limits: SameObject::new(), info: Rc::new(SameObject::new()), id, }) } #[string] fn getPreferredCanvasFormat(&self) -> &'static str { // https://github.com/mozilla/gecko-dev/blob/b75080bb8b11844d18cb5f9ac6e68a866ef8e243/dom/webgpu/Instance.h#L42-L47 if cfg!(target_os = "android") { texture::GPUTextureFormat::Rgba8unorm.as_str() } else { texture::GPUTextureFormat::Bgra8unorm.as_str() } } #[getter] fn wgslLanguageFeatures( &self, scope: &mut v8::PinScope<'_, '_>, ) -> v8::Global<v8::Object> { self .wgsl_language_features .get(scope, WGSLLanguageFeatures::new) } } pub struct WGSLLanguageFeatures(v8::Global<v8::Value>); // SAFETY: we're sure this can be GCed unsafe impl GarbageCollected for WGSLLanguageFeatures { fn trace(&self, _visitor: &mut v8::cppgc::Visitor) {} fn get_name(&self) -> &'static std::ffi::CStr { c"WGSLLanguageFeatures" } } impl WGSLLanguageFeatures { pub fn new(scope: &mut v8::PinScope<'_, '_>) -> Self { use wgpu_core::naga::front::wgsl::ImplementedLanguageExtension; let set = v8::Set::new(scope); for ext in ImplementedLanguageExtension::all() { let key = v8::String::new(scope, ext.to_ident()).unwrap(); set.add(scope, key.into()); } Self(v8::Global::new(scope, <v8::Local<v8::Value>>::from(set))) } } #[op2] impl WGSLLanguageFeatures { #[constructor] #[cppgc] fn constructor(_: bool) -> Result<WGSLLanguageFeatures, GPUGenericError> { Err(GPUGenericError::InvalidConstructor) } #[symbol("setlike_set")] fn set(&self) -> v8::Global<v8::Value> { self.0.clone() } } fn transform_label<'a>(label: String) -> Option<std::borrow::Cow<'a, str>> { if label.is_empty() { None } else { Some(std::borrow::Cow::Owned(label)) } } pub fn get_or_init_instance( state: &mut OpState, options: &adapter::GPURequestAdapterOptions, ) -> Option<(wgpu_types::Backends, Instance)> { let dx12_compiler = std::env::var(DX12_COMPILER_ENV_VAR) .ok() .and_then(|s| s.parse().ok()); let backends = std::env::var("DENO_WEBGPU_BACKEND").map_or_else( |_| wgpu_types::Backends::all(), |s| wgpu_types::Backends::from_comma_list(&s), ); let instance = if let Some(instance) = state.try_borrow::<Instance>() { instance.clone() } else { state.put(Arc::new(wgpu_core::global::Global::new( "webgpu", wgpu_types::InstanceDescriptor { backends, flags: wgpu_types::InstanceFlags::from_build_config(), memory_budget_thresholds: wgpu_types::MemoryBudgetThresholds { for_resource_creation: Some(97), for_device_loss: Some(99), }, backend_options: wgpu_types::BackendOptions { dx12: wgpu_types::Dx12BackendOptions { shader_compiler: dx12_compiler .unwrap_or(wgpu_types::Dx12Compiler::Fxc), ..Default::default() }, gl: wgpu_types::GlBackendOptions::default(), noop: wgpu_types::NoopBackendOptions::default(), }, display: None, }, None, ))); state.borrow::<Instance>().clone() }; // Check that the feature level string is valid. // `wgpu` does not support compatibility-level adapters. As permitted // by the spec, we always return a core-level adapter. wgpu_types::FeatureLevel::deserialize(IntoDeserializer::< serde::de::value::Error, >::into_deserializer( options.feature_level.as_str() )) .ok()?; Some((backends, instance)) }