| <!-- webkit-test-runner [ enableMetalShaderValidation=true ] --> |
| <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'); |
| } |
| } |
| |
| |
| /** |
| * @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 promise0 = adapter0.requestDevice({ |
| requiredFeatures: [ |
| 'depth32float-stencil8', |
| 'texture-compression-etc2', |
| 'texture-compression-astc', |
| 'indirect-first-instance', |
| 'rg11b10ufloat-renderable', |
| 'bgra8unorm-storage', |
| 'float32-blendable', |
| 'float16-renderable', |
| 'core-features-and-limits', |
| ], |
| requiredLimits: { |
| maxDynamicStorageBuffersPerPipelineLayout: 4, |
| maxInterStageShaderVariables: 16, |
| maxStorageBufferBindingSize: 165737451, |
| maxTextureArrayLayers: 256, |
| maxUniformBufferBindingSize: 108776169, |
| minStorageBufferOffsetAlignment: 256, |
| }, |
| }); |
| let adapter1 = await navigator.gpu.requestAdapter(); |
| let device0 = await promise0; |
| // START |
| a = device0.createShaderModule({ |
| code : ` |
| struct b { |
| @location(0) c: vec4f} |
| @fragment fn d() -> b { |
| var e: b; |
| return e; |
| } |
| ` |
| }) |
| f = device0.createTexture({ |
| size : {width : 8, depthOrArrayLayers : 6}, |
| dimension : '3d', |
| format : 'bgra8unorm-srgb', |
| usage : GPUTextureUsage.RENDER_ATTACHMENT |
| }) |
| g = f.createView() |
| h = device0.createBuffer({size : 32, usage : GPUBufferUsage.INDEX}) |
| i = device0.createShaderModule({ |
| code : ` |
| struct j { |
| @builtin(position) position: vec4f} |
| struct k { |
| @location(0) c: vec4u} |
| @vertex fn l(o: k ) -> j { |
| var e: j; |
| while bool(pack4xU8(o.c)) {} |
| return e; |
| } |
| ` |
| }) |
| m = device0.createCommandEncoder() |
| n = m.beginRenderPass({ |
| colorAttachments : |
| [ {view : g, depthSlice : 1, loadOp : 'clear', storeOp : 'discard'} ] |
| }) |
| p = device0.createBuffer({size : 14, usage : GPUBufferUsage.VERTEX}) |
| q = device0.createPipelineLayout({bindGroupLayouts : []}) |
| try { |
| n.setIndexBuffer(h, 'uint32') |
| } catch { |
| } |
| r = device0.createRenderPipeline({ |
| layout : q, |
| fragment : {module : a, targets : [ {format : 'bgra8unorm-srgb'} ]}, |
| vertex : { |
| module : i, |
| buffers : [ { |
| arrayStride : 60, |
| attributes : [ {format : 'uint32x3', offset : 0, shaderLocation : 0} ] |
| } ] |
| }, |
| primitive : {topology : 'line-list'} |
| }) |
| try { |
| n.setPipeline(r) |
| n.setVertexBuffer(0, p) |
| n.drawIndexed(2, 8, 0, 5) |
| n.end() |
| } catch { |
| } |
| s = m.finish() |
| try { |
| device0.queue.submit([ s ]) |
| } catch { |
| } |
| // END |
| await device0.queue.onSubmittedWorkDone(); |
| } |
| |
| 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> |