diff options
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.ts')
-rw-r--r-- | dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.ts | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.ts new file mode 100644 index 0000000000..b004293579 --- /dev/null +++ b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/encoding/cmds/render/state_tracking.spec.ts @@ -0,0 +1,184 @@ +export const description = ` +Validation tests for setVertexBuffer/setIndexBuffer state (not validation). See also operation tests. +`; + +import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; +import { range } from '../../../../../../common/util/util.js'; +import { ValidationTest } from '../../../validation_test.js'; + +class F extends ValidationTest { + getVertexBuffer(): GPUBuffer { + return this.device.createBuffer({ + size: 256, + usage: GPUBufferUsage.VERTEX, + }); + } + + createRenderPipeline(bufferCount: number): GPURenderPipeline { + return this.device.createRenderPipeline({ + layout: 'auto', + vertex: { + module: this.device.createShaderModule({ + code: ` + struct Inputs { + ${range(bufferCount, i => `\n@location(${i}) a_position${i} : vec3<f32>,`).join('')} + }; + @vertex fn main(input : Inputs + ) -> @builtin(position) vec4<f32> { + return vec4<f32>(0.0, 0.0, 0.0, 1.0); + }`, + }), + entryPoint: 'main', + buffers: [ + { + arrayStride: 3 * 4, + attributes: range(bufferCount, i => ({ + format: 'float32x3', + offset: 0, + shaderLocation: i, + })), + }, + ], + }, + fragment: { + module: this.device.createShaderModule({ + code: ` + @fragment fn main() -> @location(0) vec4<f32> { + return vec4<f32>(0.0, 1.0, 0.0, 1.0); + }`, + }), + entryPoint: 'main', + targets: [{ format: 'rgba8unorm' }], + }, + primitive: { topology: 'triangle-list' }, + }); + } + + beginRenderPass(commandEncoder: GPUCommandEncoder): GPURenderPassEncoder { + const attachmentTexture = this.device.createTexture({ + format: 'rgba8unorm', + size: { width: 16, height: 16, depthOrArrayLayers: 1 }, + usage: GPUTextureUsage.RENDER_ATTACHMENT, + }); + + return commandEncoder.beginRenderPass({ + colorAttachments: [ + { + view: attachmentTexture.createView(), + clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 }, + loadOp: 'clear', + storeOp: 'store', + }, + ], + }); + } +} + +export const g = makeTestGroup(F); + +g.test(`all_needed_vertex_buffer_should_be_bound`) + .desc( + ` +In this test we test that any missing vertex buffer for a used slot will cause validation errors when drawing. +- All (non/indexed, in/direct) draw commands + - A needed vertex buffer is not bound + - Was bound in another render pass but not the current one +` + ) + .unimplemented(); + +g.test(`all_needed_index_buffer_should_be_bound`) + .desc( + ` +In this test we test that missing index buffer for a used slot will cause validation errors when drawing. +- All indexed in/direct draw commands + - No index buffer is bound +` + ) + .unimplemented(); + +g.test('vertex_buffers_inherit_from_previous_pipeline').fn(t => { + const pipeline1 = t.createRenderPipeline(1); + const pipeline2 = t.createRenderPipeline(2); + + const vertexBuffer1 = t.getVertexBuffer(); + const vertexBuffer2 = t.getVertexBuffer(); + + { + // Check failure when vertex buffer is not set + const commandEncoder = t.device.createCommandEncoder(); + const renderPass = t.beginRenderPass(commandEncoder); + renderPass.setPipeline(pipeline1); + renderPass.draw(3); + renderPass.end(); + + t.expectValidationError(() => { + commandEncoder.finish(); + }); + } + { + // Check success when vertex buffer is inherited from previous pipeline + const commandEncoder = t.device.createCommandEncoder(); + const renderPass = t.beginRenderPass(commandEncoder); + renderPass.setPipeline(pipeline2); + renderPass.setVertexBuffer(0, vertexBuffer1); + renderPass.setVertexBuffer(1, vertexBuffer2); + renderPass.draw(3); + renderPass.setPipeline(pipeline1); + renderPass.draw(3); + renderPass.end(); + + commandEncoder.finish(); + } +}); + +g.test('vertex_buffers_do_not_inherit_between_render_passes').fn(t => { + const pipeline1 = t.createRenderPipeline(1); + const pipeline2 = t.createRenderPipeline(2); + + const vertexBuffer1 = t.getVertexBuffer(); + const vertexBuffer2 = t.getVertexBuffer(); + + { + // Check success when vertex buffer is set for each render pass + const commandEncoder = t.device.createCommandEncoder(); + { + const renderPass = t.beginRenderPass(commandEncoder); + renderPass.setPipeline(pipeline2); + renderPass.setVertexBuffer(0, vertexBuffer1); + renderPass.setVertexBuffer(1, vertexBuffer2); + renderPass.draw(3); + renderPass.end(); + } + { + const renderPass = t.beginRenderPass(commandEncoder); + renderPass.setPipeline(pipeline1); + renderPass.setVertexBuffer(0, vertexBuffer1); + renderPass.draw(3); + renderPass.end(); + } + commandEncoder.finish(); + } + { + // Check failure because vertex buffer is not inherited in second subpass + const commandEncoder = t.device.createCommandEncoder(); + { + const renderPass = t.beginRenderPass(commandEncoder); + renderPass.setPipeline(pipeline2); + renderPass.setVertexBuffer(0, vertexBuffer1); + renderPass.setVertexBuffer(1, vertexBuffer2); + renderPass.draw(3); + renderPass.end(); + } + { + const renderPass = t.beginRenderPass(commandEncoder); + renderPass.setPipeline(pipeline1); + renderPass.draw(3); + renderPass.end(); + } + + t.expectValidationError(() => { + commandEncoder.finish(); + }); + } +}); |