blob: 8e7a02ae1938039b70360ddaaf20725e90e0cb0e [file] [edit]
<script src="../../resources/js-test.js"></script>
<script>
jsTestIsAsync = true;
description("Regression test for bugs.webkit.org/show_bug.cgi?id=325413: draws a render bundle with a " +
"dynamic offset twice on the replay path. Both frames should be green.");
async function main() {
let adapter = await navigator.gpu.requestAdapter({});
let device = await adapter.requestDevice({});
device.pushErrorScope('validation');
const format = 'rgba8unorm';
let module = device.createShaderModule({ code: `
struct U { color: vec4f, };
@group(0) @binding(0) var<uniform> u: U;
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
var p = array(vec2f(-1, -3), vec2f(-1, 1), vec2f(3, 1));
return vec4f(p[i], 0, 1);
}
@fragment fn fs() -> @location(0) vec4f { return u.color; }
` });
let bindGroupLayout = device.createBindGroupLayout({
entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform', hasDynamicOffset: true } }],
});
let pipeline = device.createRenderPipeline({
layout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),
vertex: { module, entryPoint: 'vs' },
fragment: { module, entryPoint: 'fs', targets: [{ format }] },
primitive: { topology: 'triangle-list' },
multisample: { count: 1, mask: 0x7fffffff },
});
let uniform = new Uint8Array(512);
new Uint8Array(uniform.buffer, 0, 16).set(new Uint8Array(new Float32Array([1, 0, 0, 1]).buffer));
new Uint8Array(uniform.buffer, 256, 16).set(new Uint8Array(new Float32Array([0, 1, 0, 1]).buffer));
let uniformBuffer = device.createBuffer({ size: 512, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
device.queue.writeBuffer(uniformBuffer, 0, uniform);
let bindGroup = device.createBindGroup({
layout: bindGroupLayout,
entries: [{ binding: 0, resource: { buffer: uniformBuffer, size: 16 } }],
});
let enc = device.createRenderBundleEncoder({ colorFormats: [format] });
enc.setPipeline(pipeline);
enc.setBindGroup(0, bindGroup, [256]);
enc.draw(3);
let bundle = enc.finish();
let texture = device.createTexture({ size: [1, 1], format, usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC });
let readback = device.createBuffer({ size: 256, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ });
function drawAndReadback() {
let commandEncoder = device.createCommandEncoder();
let pass = commandEncoder.beginRenderPass({
colorAttachments: [{ view: texture.createView(), loadOp: 'clear', storeOp: 'store', clearValue: { r: 0, g: 0, b: 0, a: 1 } }],
});
pass.executeBundles([bundle]);
pass.end();
commandEncoder.copyTextureToBuffer({ texture }, { buffer: readback, bytesPerRow: 256 }, [1, 1]);
device.queue.submit([commandEncoder.finish()]);
}
drawAndReadback();
await device.queue.onSubmittedWorkDone();
await readback.mapAsync(GPUMapMode.READ);
let frame0 = [...new Uint8Array(readback.getMappedRange(0, 4))];
readback.unmap();
drawAndReadback();
await device.queue.onSubmittedWorkDone();
await readback.mapAsync(GPUMapMode.READ);
let frame1 = [...new Uint8Array(readback.getMappedRange(0, 4))];
readback.unmap();
window.frame0 = frame0;
window.frame1 = frame1;
shouldBeEqualToString('frame0.join()', '0,255,0,255');
shouldBeEqualToString('frame1.join()', '0,255,0,255');
let error = await device.popErrorScope();
if (error)
testFailed(error.message);
}
main().catch(e => {
testFailed("Exception: " + e);
}).finally(() => {
finishJSTest();
});
</script>