blob: 94c1b38e0ec6928d6bbc75b2dccdde356aee0285 [file]
<script>
globalThis.testRunner?.waitUntilDone();
const log = globalThis.$vm?.print ?? console.log;
const format = 'bgra8unorm';
/*
Shader Validation report on iOS is:
Invalid device load at offset 18446638520593285128, executing vertex function: "vsUintIndexClamp"
buffer: , length:8, resident:Read Write
pipeline: "(null)", UID: "..." encoder: "", draw: 1
* frame #0: vsUintIndexClamp() - /program_source:17:33
On CrystalE 22E219a it says:
Invalid device load at offset 4, executing vertex function: "vsUintIndexClamp" encoder: "", draw: 1
* frame #0: vsUintIndexClamp() - /program_source:17:33
buffer: <nil>
*/
async function doStuff() {
let adapter = await navigator.gpu.requestAdapter();
let device = await adapter.requestDevice({});
device.pushErrorScope('validation');
let module = device.createShaderModule({
code: `
@vertex
fn vertex0(@location(0) a0: f32) -> @builtin(position) vec4f {
return vec4();
}
@fragment
fn fragment0() -> @location(0) vec4f {
return vec4();
}
`,
});
let renderPipeline0 = device.createRenderPipeline({
layout: 'auto',
// not necessary
// primitive: {topology: 'point-list'},
fragment: {module, targets: [{format}]},
vertex: {
module,
buffers: [
{
arrayStride: 4,
// this would also work:
// stepMode: 'instance',
attributes: [{format: 'float32', offset: 0, shaderLocation: 0}],
},
],
},
});
let vertexBuffer0 = device.createBuffer({size: 16, usage: GPUBufferUsage.VERTEX});
let indexBuffer0 = device.createBuffer({size: 8, usage: GPUBufferUsage.INDEX});
let indirectBuffer0 = device.createBuffer({size: 20, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.INDIRECT});
/*
for the draw indirect from offset 0 the values are:
vertex count: 3 <-- this fits in vertex buffer
instance count: 1
first vertex: 0
first instance: 0
for the draw indexed indirect at offset 0 the values are:
index count: 3 <-- the index buffer can only fit two indices
instance count: 1
first index: 0
base vertex: 0
first instance: 0
*/
device.queue.writeBuffer(indirectBuffer0, 0, new Uint32Array([30, 1, 0, 0, 0]), 0, 5);
await device.queue.onSubmittedWorkDone();
let texture0 = device.createTexture({size: [1], format, usage: GPUTextureUsage.RENDER_ATTACHMENT});
let textureView0 = texture0.createView({});
let commandEncoder0 = device.createCommandEncoder({});
let renderPassEncoder0 = commandEncoder0.beginRenderPass({
colorAttachments: [{
view: textureView0,
loadOp: 'load',
storeOp: 'discard',
}],
});
renderPassEncoder0.setPipeline(renderPipeline0);
renderPassEncoder0.setVertexBuffer(0, vertexBuffer0);
renderPassEncoder0.drawIndirect(indirectBuffer0, 0);
renderPassEncoder0.end();
let commandBuffer0 = commandEncoder0.finish();
let commandEncoder1 = device.createCommandEncoder({});
let renderPassEncoder1 = commandEncoder1.beginRenderPass({
colorAttachments: [{
view: textureView0,
loadOp: 'load',
storeOp: 'store',
}],
});
renderPassEncoder1.setPipeline(renderPipeline0);
renderPassEncoder1.setVertexBuffer(0, vertexBuffer0);
// uint16 also works, if you make the index buffer size four, i.e. two indices.
renderPassEncoder1.setIndexBuffer(indexBuffer0, 'uint32');
renderPassEncoder1.drawIndexedIndirect(indirectBuffer0, 0);
renderPassEncoder1.end();
let commandBuffer1 = commandEncoder1.finish();
// this works the same the commented lines below:
device.queue.submit([commandBuffer0, commandBuffer1]);
/*
await device.queue.onSubmittedWorkDone();
device.queue.submit([commandBuffer0]);
await device.queue.onSubmittedWorkDone();
device.queue.submit([commandBuffer1]);
*/
await device.queue.onSubmittedWorkDone();
let error = await device.popErrorScope();
if (error) {
log(error.message);
} else {
log('no validation error');
}
globalThis.testRunner?.dumpAsText();
globalThis.testRunner?.notifyDone();
}
onload = async () => {
await doStuff();
};
</script>
Pass