| export const description = ` |
| Validation tests for resolveQuerySet. |
| `; |
| import { makeTestGroup } from '../../../../../common/framework/test_group.js'; |
| import { GPUConst } from '../../../../constants.js'; |
| import { kResourceStates, AllFeaturesMaxLimitsGPUTest } from '../../../../gpu_test.js'; |
| import * as vtu from '../../validation_test_utils.js'; |
| |
| export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest); |
| |
| export const kQueryCount = 2; |
| |
| g.test('queryset_and_destination_buffer_state') |
| .desc( |
| ` |
| Tests that resolve query set must be with valid query set and destination buffer. |
| - {invalid, destroyed} GPUQuerySet results in validation error. |
| - {invalid, destroyed} destination buffer results in validation error. |
| ` |
| ) |
| .params(u => |
| u // |
| .combine('querySetState', kResourceStates) |
| .combine('destinationState', kResourceStates) |
| ) |
| .fn(t => { |
| const { querySetState, destinationState } = t.params; |
| |
| const shouldBeValid = querySetState !== 'invalid' && destinationState !== 'invalid'; |
| const shouldSubmitSuccess = querySetState === 'valid' && destinationState === 'valid'; |
| |
| const querySet = vtu.createQuerySetWithState(t, querySetState); |
| |
| const destination = vtu.createBufferWithState(t, destinationState, { |
| size: kQueryCount * 8, |
| usage: GPUBufferUsage.QUERY_RESOLVE, |
| }); |
| |
| const encoder = t.createEncoder('non-pass'); |
| encoder.encoder.resolveQuerySet(querySet, 0, 1, destination, 0); |
| encoder.validateFinishAndSubmit(shouldBeValid, shouldSubmitSuccess); |
| }); |
| |
| g.test('first_query_and_query_count') |
| .desc( |
| ` |
| Tests that resolve query set with invalid firstQuery and queryCount: |
| - firstQuery and/or queryCount out of range |
| ` |
| ) |
| .paramsSubcasesOnly([ |
| { firstQuery: 0, queryCount: kQueryCount }, // control case |
| { firstQuery: 0, queryCount: kQueryCount + 1 }, |
| { firstQuery: 1, queryCount: kQueryCount }, |
| { firstQuery: kQueryCount, queryCount: 1 }, |
| ]) |
| .fn(t => { |
| const { firstQuery, queryCount } = t.params; |
| |
| const querySet = t.createQuerySetTracked({ type: 'occlusion', count: kQueryCount }); |
| const destination = t.createBufferTracked({ |
| size: kQueryCount * 8, |
| usage: GPUBufferUsage.QUERY_RESOLVE, |
| }); |
| |
| const encoder = t.createEncoder('non-pass'); |
| encoder.encoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, 0); |
| encoder.validateFinish(firstQuery + queryCount <= kQueryCount); |
| }); |
| |
| g.test('destination_buffer_usage') |
| .desc( |
| ` |
| Tests that resolve query set with invalid destinationBuffer: |
| - Buffer usage {with, without} QUERY_RESOLVE |
| ` |
| ) |
| .paramsSubcasesOnly(u => |
| u // |
| .combine('bufferUsage', [ |
| GPUConst.BufferUsage.STORAGE, |
| GPUConst.BufferUsage.QUERY_RESOLVE, // control case |
| ] as const) |
| ) |
| .fn(t => { |
| const querySet = t.createQuerySetTracked({ type: 'occlusion', count: kQueryCount }); |
| const destination = t.createBufferTracked({ |
| size: kQueryCount * 8, |
| usage: t.params.bufferUsage, |
| }); |
| |
| const encoder = t.createEncoder('non-pass'); |
| encoder.encoder.resolveQuerySet(querySet, 0, kQueryCount, destination, 0); |
| encoder.validateFinish(t.params.bufferUsage === GPUConst.BufferUsage.QUERY_RESOLVE); |
| }); |
| |
| g.test('destination_offset_alignment') |
| .desc( |
| ` |
| Tests that resolve query set with invalid destinationOffset: |
| - destinationOffset is not a multiple of 256 |
| ` |
| ) |
| .paramsSubcasesOnly(u => u.combine('destinationOffset', [0, 128, 256, 384])) |
| .fn(t => { |
| const { destinationOffset } = t.params; |
| const querySet = t.createQuerySetTracked({ type: 'occlusion', count: kQueryCount }); |
| const destination = t.createBufferTracked({ |
| size: 512, |
| usage: GPUBufferUsage.QUERY_RESOLVE, |
| }); |
| |
| const encoder = t.createEncoder('non-pass'); |
| encoder.encoder.resolveQuerySet(querySet, 0, kQueryCount, destination, destinationOffset); |
| encoder.validateFinish(destinationOffset % 256 === 0); |
| }); |
| |
| g.test('resolve_buffer_oob') |
| .desc( |
| ` |
| Tests that resolve query set with the size oob: |
| - The size of destinationBuffer - destinationOffset < queryCount * 8 |
| ` |
| ) |
| .paramsSubcasesOnly(u => |
| u.combineWithParams([ |
| { queryCount: 2, bufferSize: 16, destinationOffset: 0, _success: true }, |
| { queryCount: 3, bufferSize: 16, destinationOffset: 0, _success: false }, |
| { queryCount: 2, bufferSize: 16, destinationOffset: 256, _success: false }, |
| { queryCount: 2, bufferSize: 272, destinationOffset: 256, _success: true }, |
| { queryCount: 2, bufferSize: 264, destinationOffset: 256, _success: false }, |
| ]) |
| ) |
| .fn(t => { |
| const { queryCount, bufferSize, destinationOffset, _success } = t.params; |
| const querySet = t.createQuerySetTracked({ type: 'occlusion', count: queryCount }); |
| const destination = t.createBufferTracked({ |
| size: bufferSize, |
| usage: GPUBufferUsage.QUERY_RESOLVE, |
| }); |
| |
| const encoder = t.createEncoder('non-pass'); |
| encoder.encoder.resolveQuerySet(querySet, 0, queryCount, destination, destinationOffset); |
| encoder.validateFinish(_success); |
| }); |
| |
| g.test('query_set_buffer,device_mismatch') |
| .desc( |
| 'Tests resolveQuerySet cannot be called with a query set or destination buffer created from another device' |
| ) |
| .paramsSubcasesOnly([ |
| { querySetMismatched: false, bufferMismatched: false }, // control case |
| { querySetMismatched: true, bufferMismatched: false }, |
| { querySetMismatched: false, bufferMismatched: true }, |
| ] as const) |
| .beforeAllSubcases(t => t.usesMismatchedDevice()) |
| .fn(t => { |
| const { querySetMismatched, bufferMismatched } = t.params; |
| |
| const kQueryCount = 1; |
| |
| const querySetDevice = querySetMismatched ? t.mismatchedDevice : t.device; |
| const querySet = t.trackForCleanup( |
| querySetDevice.createQuerySet({ |
| type: 'occlusion', |
| count: kQueryCount, |
| }) |
| ); |
| |
| const bufferDevice = bufferMismatched ? t.mismatchedDevice : t.device; |
| const buffer = t.trackForCleanup( |
| bufferDevice.createBuffer({ |
| size: kQueryCount * 8, |
| usage: GPUBufferUsage.QUERY_RESOLVE, |
| }) |
| ); |
| |
| const encoder = t.createEncoder('non-pass'); |
| encoder.encoder.resolveQuerySet(querySet, 0, kQueryCount, buffer, 0); |
| encoder.validateFinish(!(querySetMismatched || bufferMismatched)); |
| }); |