| <style> |
| :root { background: #102030e0; color: #99ddbbcc; font-size: 15px; } |
| </style> |
| <script src="../../../resources/js-test-pre.js"></script> |
| <script id="shared"> |
| |
| const log = console.log; |
| |
| async function gc() { |
| await 0; |
| if (globalThis.GCController) { |
| globalThis.GCController.collect(); |
| } else if (globalThis.$vm) { |
| globalThis.$vm.gc(); |
| } else { |
| log('no GC available'); |
| } |
| } |
| |
| /** |
| * @param {GPUDevice} device |
| * @param {GPUComputePassEncoder} computePassEncoder |
| */ |
| function clearResourceUsages(device, computePassEncoder) { |
| let code = `@compute @workgroup_size(1) fn c() {}`; |
| let module = device.createShaderModule({code}); |
| computePassEncoder.setPipeline(device.createComputePipeline( |
| { |
| layout: 'auto', |
| compute: {module}, |
| })); |
| computePassEncoder.dispatchWorkgroups(1); |
| } |
| |
| /** |
| * @template {any} T |
| * @param {GPUDevice} device |
| * @param {string} label |
| * @param {()=>T} payload |
| * @returns {Promise<T>} |
| */ |
| async function validationWrapper(device, label, payload) { |
| device.pushErrorScope('internal'); |
| device.pushErrorScope('out-of-memory'); |
| device.pushErrorScope('validation'); |
| let result = payload(); |
| let validationError = await device.popErrorScope(); |
| let outOfMemoryError = await device.popErrorScope(); |
| let internalError = await device.popErrorScope(); |
| let error = validationError ?? outOfMemoryError ?? internalError; |
| if (error) { |
| log('*'.repeat(25)); |
| log(error[Symbol.toStringTag]); |
| log(error.message); |
| log(label); |
| if (error.stack != `_`) { |
| log(error.stack); |
| } |
| log(location); |
| log('*'.repeat(25)); |
| throw error; |
| } |
| return result; |
| } |
| |
| const videoUrls = [ |
| |
| ]; |
| |
| /** |
| * @param {number} index |
| * @returns {Promise<HTMLVideoElement>} |
| */ |
| function videoWithData(index) { |
| let video = document.createElement('video'); |
| video.src = videoUrls[index % videoUrls.length]; |
| return new Promise(resolve => { |
| video.onloadeddata = () => { |
| resolve(video); |
| }; |
| }); |
| } |
| |
| /** |
| * @returns {Promise<string>} |
| */ |
| async function makeDataUrl(width, height, color0, color1) { |
| let offscreenCanvas = new OffscreenCanvas(width, height); |
| let ctx = offscreenCanvas.getContext('2d'); |
| let gradient = ctx.createLinearGradient(0, 0, width, height); |
| gradient.addColorStop(0, color0); |
| gradient.addColorStop(0.1, color1); |
| gradient.addColorStop(0.3, color0); |
| gradient.addColorStop(0.7, color1); |
| gradient.addColorStop(0.9, color0); |
| gradient.addColorStop(1, color1); |
| ctx.fillStyle = gradient; |
| ctx.fillRect(0, 0, width, height); |
| let blob = await offscreenCanvas.convertToBlob(); |
| let fileReader = new FileReader(); |
| fileReader.readAsDataURL(blob); |
| return new Promise(resolve => { |
| fileReader.onload = () => { |
| resolve(fileReader.result); |
| }; |
| }); |
| } |
| |
| async function imageWithData(width, height, color0, color1) { |
| let dataUrl = await makeDataUrl(width, height, color0, color1); |
| let img = document.createElement('img'); |
| img.src = dataUrl; |
| await img.decode(); |
| return img; |
| } |
| |
| /** |
| * @param {string} payload |
| * @returns {string} |
| */ |
| function toBlobUrl(payload) { |
| let blob = new Blob([payload], {type: 'text/javascript'}); |
| return URL.createObjectURL(blob); |
| } |
| </script> |
| <script> |
| globalThis.testRunner?.waitUntilDone(); |
| |
| async function window0() { |
| let adapter0 = await navigator.gpu.requestAdapter({}); |
| let device0 = await adapter0.requestDevice({ |
| defaultQueue: {}, |
| requiredFeatures: [ |
| 'depth-clip-control', |
| 'depth32float-stencil8', |
| 'texture-compression-etc2', |
| 'texture-compression-astc', |
| 'indirect-first-instance', |
| 'rg11b10ufloat-renderable', |
| 'bgra8unorm-storage', |
| 'float32-blendable', |
| 'float16-renderable', |
| 'float32-renderable', |
| 'timestamp-query', |
| ], |
| }); |
| let shaderModule3 = device0.createShaderModule({ |
| code: ` |
| enable f16; |
| |
| requires packed_4x8_integer_dot_product; |
| |
| struct VertexOutput2 { |
| @builtin(position) position: vec4f, |
| } |
| |
| struct FragmentOutput2 { |
| @location(0) @interpolate(flat) location_0: vec2f, |
| } |
| |
| @vertex |
| fn vertex3() -> VertexOutput2 { |
| var out: VertexOutput2; |
| return out; |
| } |
| |
| @fragment |
| fn fragment2() -> FragmentOutput2 { |
| var out: FragmentOutput2; |
| return out; |
| } |
| |
| `, |
| }); |
| let shaderModule5 = device0.createShaderModule({ |
| code: ` |
| requires packed_4x8_integer_dot_product; |
| |
| enable f16; |
| |
| fn unconst_u32(v: u32) -> u32 { return v; } |
| fn unconst_f16(v: f16) -> f16 { return v; } |
| fn unconst_f32(v: f32) -> f32 { return v; } |
| |
| /* zero global variables used */ |
| fn fn0(a0: ptr<private, f16>) -> vec4<bool> { |
| var out: vec4<bool>; |
| vp7 = modf(f16(reverseBits(unconst_u32(1502923743)))); |
| vp7.fract = f16(dot4I8Packed(unconst_u32(990731175), pack4x8unorm(unpack4x8snorm(u32(vp7.fract))))); |
| return out; |
| _ = override24; |
| } |
| |
| var<private> vp7 = modf(f16(8654.3)); |
| |
| struct VertexOutput4 { |
| @builtin(position) position: vec4f, |
| } |
| |
| var<workgroup> vw2: atomic<u32>; |
| |
| override override24: f16; |
| |
| struct FragmentOutput3 { |
| @location(0) @interpolate(linear) location_0: vec4f, |
| @location(3) location_3: f32, |
| } |
| |
| @vertex |
| fn vertex5() -> VertexOutput4 { |
| var out: VertexOutput4; |
| var vf35 = fn0(&vp7.whole); |
| return out; |
| } |
| |
| @fragment |
| fn fragment3() -> FragmentOutput3 { |
| var out: FragmentOutput3; |
| return out; |
| }`, |
| }); |
| let pipeline16 = device0.createRenderPipeline({ |
| layout: 'auto', |
| fragment: { |
| module: shaderModule3, |
| targets: [{format: 'rg32float', writeMask: GPUColorWrite.GREEN | GPUColorWrite.RED}], |
| }, |
| vertex: { |
| module: shaderModule5, |
| entryPoint: 'vertex5', |
| constants: {override24: 1}, |
| buffers: [ |
| { |
| arrayStride: 1456, |
| stepMode: 'vertex', |
| attributes: [ |
| {format: 'sint32x3', offset: 180, shaderLocation: 1}, |
| {format: 'sint16x2', offset: 92, shaderLocation: 14}, |
| {format: 'unorm10-10-10-2', offset: 60, shaderLocation: 4}, |
| {format: 'uint8x4', offset: 80, shaderLocation: 10}, |
| {format: 'sint16x2', offset: 244, shaderLocation: 15}, |
| {format: 'snorm8x4', offset: 228, shaderLocation: 9}, |
| {format: 'unorm16x4', offset: 120, shaderLocation: 2}, |
| {format: 'snorm8x4', offset: 84, shaderLocation: 11}, |
| {format: 'uint32x2', offset: 56, shaderLocation: 6}, |
| {format: 'float16x2', offset: 244, shaderLocation: 12}, |
| {format: 'float32', offset: 400, shaderLocation: 13}, |
| {format: 'sint32', offset: 96, shaderLocation: 3}, |
| {format: 'sint8x2', offset: 1248, shaderLocation: 5}, |
| {format: 'sint32x4', offset: 400, shaderLocation: 0}, |
| ], |
| }, |
| { |
| arrayStride: 60, |
| stepMode: 'instance', |
| attributes: [{format: 'unorm8x4', offset: 4, shaderLocation: 8}, {format: 'unorm8x2', offset: 6, shaderLocation: 7}], |
| }, |
| ], |
| }, |
| primitive: { |
| topology: 'line-strip', |
| stripIndexFormat: 'uint32', |
| frontFace: 'cw', |
| cullMode: 'front', |
| unclippedDepth: true, |
| }, |
| }); |
| |
| } |
| |
| onload = async () => { |
| try { |
| let sharedScript = document.querySelector('#shared').textContent; |
| |
| let workers = [ |
| |
| ]; |
| let promises = [ window0() ]; |
| debug('promises created'); |
| let results = await Promise.allSettled(promises); |
| for (let result of results) { |
| if (result.status === 'rejected') { throw result.reason; } |
| } |
| debug('Pass'); |
| } catch (e) { |
| log('error'); |
| log(e); |
| log(e[Symbol.toStringTag]); |
| log(e.stack); |
| if (e instanceof GPUPipelineError) { |
| log(`${e} - ${e.reason}`); |
| |
| } else if (e instanceof DOMException) { |
| if (e.name === 'OperationError') { |
| log(e.message); |
| |
| } else if (e.name === 'InvalidStateError') { |
| } else { |
| log(e); |
| |
| } |
| } else if (e instanceof GPUValidationError) { |
| |
| } else if (e instanceof GPUOutOfMemoryError) { |
| |
| } else if (e instanceof TypeError) { |
| log(e); |
| |
| } else { |
| log('unexpected error type'); |
| log(e); |
| |
| } |
| } |
| globalThis.testRunner?.dumpAsText(); |
| globalThis.testRunner?.notifyDone(); |
| }; |
| </script> |