mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
[deno] Implement ShaderModule.getCompilationInfo (#7736)
This commit is contained in:
parent
1d4891ab5a
commit
e9af205c71
2
cts_runner/src/bootstrap.js
vendored
2
cts_runner/src/bootstrap.js
vendored
@ -204,6 +204,8 @@ const windowOrWorkerGlobalScope = {
|
||||
GPUBindGroupLayout: util.nonEnumerable(webgpu.GPUBindGroupLayout),
|
||||
GPUPipelineLayout: util.nonEnumerable(webgpu.GPUPipelineLayout),
|
||||
GPUBindGroup: util.nonEnumerable(webgpu.GPUBindGroup),
|
||||
GPUCompilationInfo: util.nonEnumerable(webgpu.GPUCompilationInfo),
|
||||
GPUCompilationMessage: util.nonEnumerable(webgpu.GPUCompilationMessage),
|
||||
GPUShaderModule: util.nonEnumerable(webgpu.GPUShaderModule),
|
||||
GPUShaderStage: util.nonEnumerable(webgpu.GPUShaderStage),
|
||||
GPUComputePipeline: util.nonEnumerable(webgpu.GPUComputePipeline),
|
||||
|
||||
@ -16,8 +16,21 @@ webgpu:api,operation,rendering,color_target_state:blending,formats:*
|
||||
webgpu:api,operation,rendering,color_target_state:blend_constant,setting:*
|
||||
webgpu:api,operation,rendering,depth:*
|
||||
webgpu:api,operation,rendering,draw:*
|
||||
webgpu:api,operation,shader_module,compilation_info:*
|
||||
webgpu:api,operation,uncapturederror:iff_uncaptured:*
|
||||
//FAIL: webgpu:api,operation,uncapturederror:onuncapturederror_order_wrt_addEventListener
|
||||
// There are also two unimplemented SKIPs in uncapturederror not enumerated here.
|
||||
webgpu:api,validation,encoding,queries,general:occlusion_query,query_type:*
|
||||
webgpu:shader,execution,flow_control,return:*
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="break"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="break_if"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="continue"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="for3"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="for4"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="for5"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="loop4"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="loop5"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="loop6"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="loop8"
|
||||
webgpu:shader,validation,statement,statement_behavior:invalid_statements:body="switch1"
|
||||
//FAIL: 9 invalid_statements subtests due to https://github.com/gfx-rs/wgpu/issues/7733
|
||||
|
||||
@ -16,6 +16,8 @@ import {
|
||||
GPUBuffer,
|
||||
GPUCommandBuffer,
|
||||
GPUCommandEncoder,
|
||||
GPUCompilationInfo,
|
||||
GPUCompilationMessage,
|
||||
GPUComputePassEncoder,
|
||||
GPUComputePipeline,
|
||||
GPUDevice,
|
||||
@ -39,6 +41,7 @@ const {
|
||||
ObjectDefineProperty,
|
||||
ObjectPrototypeIsPrototypeOf,
|
||||
ObjectSetPrototypeOf,
|
||||
ReflectGet,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
} = primordials;
|
||||
@ -510,6 +513,58 @@ ObjectDefineProperty(GPUShaderModule, customInspect, {
|
||||
});
|
||||
const GPUShaderModulePrototype = GPUShaderModule.prototype;
|
||||
|
||||
ObjectDefineProperty(GPUCompilationInfo, customInspect, {
|
||||
__proto__: null,
|
||||
value(inspect, inspectOptions) {
|
||||
return inspect(
|
||||
createFilteredInspectProxy({
|
||||
object: this,
|
||||
evaluate: ObjectPrototypeIsPrototypeOf(
|
||||
GPUCompilationInfoPrototype,
|
||||
this,
|
||||
),
|
||||
keys: [
|
||||
"messages",
|
||||
],
|
||||
}),
|
||||
inspectOptions,
|
||||
);
|
||||
},
|
||||
});
|
||||
const GPUCompilationInfoPrototype = GPUCompilationInfo.prototype;
|
||||
|
||||
ObjectDefineProperty(GPUCompilationMessage, customInspect, {
|
||||
__proto__: null,
|
||||
value(inspect, inspectOptions) {
|
||||
return inspect(
|
||||
createFilteredInspectProxy({
|
||||
object: this,
|
||||
evaluate: ObjectPrototypeIsPrototypeOf(
|
||||
GPUCompilationMessagePrototype,
|
||||
this,
|
||||
),
|
||||
keys: [
|
||||
"message",
|
||||
"type",
|
||||
"line_num",
|
||||
"line_pos",
|
||||
"offset",
|
||||
"length",
|
||||
],
|
||||
}),
|
||||
inspectOptions,
|
||||
);
|
||||
},
|
||||
});
|
||||
const GPUCompilationMessagePrototype = GPUCompilationMessage.prototype;
|
||||
// Naming it `type` or `r#type` in Rust does not work.
|
||||
// https://github.com/gfx-rs/wgpu/issues/7778
|
||||
ObjectDefineProperty(GPUCompilationMessage.prototype, "type", {
|
||||
get() {
|
||||
return this.ty;
|
||||
}
|
||||
});
|
||||
|
||||
class GPUShaderStage {
|
||||
constructor() {
|
||||
webidl.illegalConstructor();
|
||||
@ -722,6 +777,13 @@ ObjectDefineProperty(GPUQuerySet, customInspect, {
|
||||
},
|
||||
});
|
||||
const GPUQuerySetPrototype = GPUQuerySet.prototype;
|
||||
// Naming it `type` or `r#type` in Rust does not work.
|
||||
// https://github.com/gfx-rs/wgpu/issues/7778
|
||||
ObjectDefineProperty(GPUQuerySet.prototype, "type", {
|
||||
get() {
|
||||
return this.ty;
|
||||
}
|
||||
});
|
||||
|
||||
// Converters
|
||||
|
||||
@ -779,6 +841,8 @@ export {
|
||||
GPUColorWrite,
|
||||
GPUCommandBuffer,
|
||||
GPUCommandEncoder,
|
||||
GPUCompilationInfo,
|
||||
GPUCompilationMessage,
|
||||
GPUComputePassEncoder,
|
||||
GPUComputePipeline,
|
||||
GPUDevice,
|
||||
|
||||
@ -5,6 +5,7 @@ use std::cell::RefCell;
|
||||
use std::num::NonZeroU64;
|
||||
use std::rc::Rc;
|
||||
|
||||
use deno_core::cppgc::make_cppgc_object;
|
||||
use deno_core::cppgc::SameObject;
|
||||
use deno_core::op2;
|
||||
use deno_core::v8;
|
||||
@ -33,6 +34,7 @@ use crate::error::GPUError;
|
||||
use crate::query_set::GPUQuerySet;
|
||||
use crate::render_bundle::GPURenderBundleEncoder;
|
||||
use crate::render_pipeline::GPURenderPipeline;
|
||||
use crate::shader::GPUCompilationInfo;
|
||||
use crate::webidl::features_to_feature_names;
|
||||
use crate::Instance;
|
||||
|
||||
@ -409,6 +411,7 @@ impl GPUDevice {
|
||||
#[cppgc]
|
||||
fn create_shader_module(
|
||||
&self,
|
||||
scope: &mut v8::HandleScope<'_>,
|
||||
#[webidl] descriptor: super::shader::GPUShaderModuleDescriptor,
|
||||
) -> GPUShaderModule {
|
||||
let wgpu_descriptor = wgpu_core::pipeline::ShaderModuleDescriptor {
|
||||
@ -419,16 +422,20 @@ impl GPUDevice {
|
||||
let (id, err) = self.instance.device_create_shader_module(
|
||||
self.id,
|
||||
&wgpu_descriptor,
|
||||
wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::Owned(descriptor.code)),
|
||||
wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::Borrowed(&descriptor.code)),
|
||||
None,
|
||||
);
|
||||
|
||||
let compilation_info = GPUCompilationInfo::new(scope, err.iter(), &descriptor.code);
|
||||
let compilation_info = make_cppgc_object(scope, compilation_info);
|
||||
let compilation_info = v8::Global::new(scope, compilation_info);
|
||||
self.error_handler.push_error(err);
|
||||
|
||||
GPUShaderModule {
|
||||
instance: self.instance.clone(),
|
||||
id,
|
||||
label: descriptor.label,
|
||||
compilation_info,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -86,6 +86,8 @@ deno_core::extension!(
|
||||
render_pass::GPURenderPassEncoder,
|
||||
render_pipeline::GPURenderPipeline,
|
||||
sampler::GPUSampler,
|
||||
shader::GPUCompilationInfo,
|
||||
shader::GPUCompilationMessage,
|
||||
shader::GPUShaderModule,
|
||||
adapter::GPUSupportedFeatures,
|
||||
adapter::GPUSupportedLimits,
|
||||
|
||||
@ -49,9 +49,11 @@ impl GPUQuerySet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Naming this `type` or `r#type` does not work.
|
||||
// https://github.com/gfx-rs/wgpu/issues/7778
|
||||
#[getter]
|
||||
#[string]
|
||||
fn r#type(&self) -> &'static str {
|
||||
fn ty(&self) -> &'static str {
|
||||
self.r#type.as_str()
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use deno_core::cppgc::make_cppgc_object;
|
||||
use deno_core::op2;
|
||||
use deno_core::v8;
|
||||
use deno_core::webidl::WebIdlInterfaceConverter;
|
||||
use deno_core::GarbageCollected;
|
||||
use deno_core::WebIDL;
|
||||
use wgpu_core::pipeline;
|
||||
|
||||
use crate::Instance;
|
||||
|
||||
@ -11,6 +14,7 @@ pub struct GPUShaderModule {
|
||||
pub instance: Instance,
|
||||
pub id: wgpu_core::id::ShaderModuleId,
|
||||
pub label: String,
|
||||
pub compilation_info: v8::Global<v8::Object>,
|
||||
}
|
||||
|
||||
impl Drop for GPUShaderModule {
|
||||
@ -37,6 +41,16 @@ impl GPUShaderModule {
|
||||
fn label(&self, #[webidl] _label: String) {
|
||||
// TODO(@crowlKats): no-op, needs wpgu to implement changing the label
|
||||
}
|
||||
|
||||
fn get_compilation_info<'a>(
|
||||
&self,
|
||||
scope: &mut v8::HandleScope<'a>,
|
||||
) -> v8::Local<'a, v8::Promise> {
|
||||
let resolver = v8::PromiseResolver::new(scope).unwrap();
|
||||
let info = v8::Local::new(scope, self.compilation_info.clone());
|
||||
resolver.resolve(scope, info.into()).unwrap();
|
||||
resolver.get_promise(scope)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(WebIDL)]
|
||||
@ -47,3 +61,143 @@ pub(crate) struct GPUShaderModuleDescriptor {
|
||||
|
||||
pub code: String,
|
||||
}
|
||||
|
||||
pub struct GPUCompilationMessage {
|
||||
message: String,
|
||||
r#type: GPUCompilationMessageType,
|
||||
line_num: u64,
|
||||
line_pos: u64,
|
||||
offset: u64,
|
||||
length: u64,
|
||||
}
|
||||
|
||||
impl GarbageCollected for GPUCompilationMessage {}
|
||||
|
||||
#[op2]
|
||||
impl GPUCompilationMessage {
|
||||
#[getter]
|
||||
#[string]
|
||||
fn message(&self) -> String {
|
||||
self.message.clone()
|
||||
}
|
||||
|
||||
// Naming this `type` or `r#type` does not work.
|
||||
// https://github.com/gfx-rs/wgpu/issues/7778
|
||||
#[getter]
|
||||
#[string]
|
||||
fn ty(&self) -> &'static str {
|
||||
self.r#type.as_str()
|
||||
}
|
||||
|
||||
#[getter]
|
||||
#[number]
|
||||
fn line_num(&self) -> u64 {
|
||||
self.line_num
|
||||
}
|
||||
|
||||
#[getter]
|
||||
#[number]
|
||||
fn line_pos(&self) -> u64 {
|
||||
self.line_pos
|
||||
}
|
||||
|
||||
#[getter]
|
||||
#[number]
|
||||
fn offset(&self) -> u64 {
|
||||
self.offset
|
||||
}
|
||||
|
||||
#[getter]
|
||||
#[number]
|
||||
fn length(&self) -> u64 {
|
||||
self.length
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUCompilationMessage {
|
||||
fn new(error: &pipeline::CreateShaderModuleError, source: &str) -> Self {
|
||||
let message = error.to_string();
|
||||
|
||||
let loc = match error {
|
||||
pipeline::CreateShaderModuleError::Parsing(e) => e.inner.location(source),
|
||||
pipeline::CreateShaderModuleError::Validation(e) => e.inner.location(source),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
match loc {
|
||||
Some(loc) => {
|
||||
let len_utf16 = |s: &str| s.chars().map(|c| c.len_utf16() as u64).sum();
|
||||
|
||||
let start = loc.offset as usize;
|
||||
|
||||
// Naga reports a `line_pos` using UTF-8 bytes, so we cannot use it.
|
||||
let line_start = source[0..start].rfind('\n').map(|pos| pos + 1).unwrap_or(0);
|
||||
let line_pos = len_utf16(&source[line_start..start]) + 1;
|
||||
|
||||
Self {
|
||||
message,
|
||||
r#type: GPUCompilationMessageType::Error,
|
||||
line_num: loc.line_number.into(),
|
||||
line_pos,
|
||||
offset: len_utf16(&source[0..start]),
|
||||
length: len_utf16(&source[start..start + loc.length as usize]),
|
||||
}
|
||||
}
|
||||
_ => Self {
|
||||
message,
|
||||
r#type: GPUCompilationMessageType::Error,
|
||||
line_num: 0,
|
||||
line_pos: 0,
|
||||
offset: 0,
|
||||
length: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GPUCompilationInfo {
|
||||
messages: v8::Global<v8::Object>,
|
||||
}
|
||||
|
||||
impl GarbageCollected for GPUCompilationInfo {}
|
||||
|
||||
#[op2]
|
||||
impl GPUCompilationInfo {
|
||||
#[getter]
|
||||
#[global]
|
||||
fn messages(&self) -> v8::Global<v8::Object> {
|
||||
self.messages.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUCompilationInfo {
|
||||
pub fn new<'args, 'scope>(
|
||||
scope: &mut v8::HandleScope<'scope>,
|
||||
messages: impl ExactSizeIterator<Item = &'args pipeline::CreateShaderModuleError>,
|
||||
source: &'args str,
|
||||
) -> Self {
|
||||
let array = v8::Array::new(scope, messages.len().try_into().unwrap());
|
||||
for (i, message) in messages.enumerate() {
|
||||
let message_object =
|
||||
make_cppgc_object(scope, GPUCompilationMessage::new(message, source));
|
||||
array.set_index(scope, i.try_into().unwrap(), message_object.into());
|
||||
}
|
||||
|
||||
let object: v8::Local<v8::Object> = array.into();
|
||||
object
|
||||
.set_integrity_level(scope, v8::IntegrityLevel::Frozen)
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
messages: v8::Global::new(scope, object),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(WebIDL, Clone)]
|
||||
#[webidl(enum)]
|
||||
pub(crate) enum GPUCompilationMessageType {
|
||||
Error,
|
||||
Warning,
|
||||
Info,
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user