summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/image_copy/buffer_related.spec.ts
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/image_copy/buffer_related.spec.ts')
-rw-r--r--dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/image_copy/buffer_related.spec.ts229
1 files changed, 229 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/image_copy/buffer_related.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/image_copy/buffer_related.spec.ts
new file mode 100644
index 0000000000..6c186818a7
--- /dev/null
+++ b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/image_copy/buffer_related.spec.ts
@@ -0,0 +1,229 @@
+export const description = `Validation tests for buffer related parameters for buffer <-> texture copies`;
+
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import {
+ kSizedTextureFormats,
+ kTextureDimensions,
+ kTextureFormatInfo,
+ textureDimensionAndFormatCompatible,
+} from '../../../capability_info.js';
+import { GPUConst } from '../../../constants.js';
+import { kResourceStates } from '../../../gpu_test.js';
+import { kImageCopyTypes } from '../../../util/texture/layout.js';
+
+import { ImageCopyTest, formatCopyableWithMethod } from './image_copy.js';
+
+export const g = makeTestGroup(ImageCopyTest);
+
+g.test('buffer_state')
+ .desc(
+ `
+Test that the buffer must be valid and not destroyed.
+- for all buffer <-> texture copy methods
+- for various buffer states
+`
+ )
+ .params(u =>
+ u //
+ // B2B copy validations are at api,validation,encoding,cmds,copyBufferToBuffer.spec.ts
+ .combine('method', ['CopyB2T', 'CopyT2B'] as const)
+ .combine('state', kResourceStates)
+ )
+ .fn(async t => {
+ const { method, state } = t.params;
+
+ // A valid buffer.
+ const buffer = t.createBufferWithState(state, {
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ // Invalid buffer will fail finish, and destroyed buffer will fail submit
+ const submit = state !== 'invalid';
+ const success = state === 'valid';
+
+ const texture = t.device.createTexture({
+ size: { width: 2, height: 2, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ t.testBuffer(
+ buffer,
+ texture,
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 16, method, success, submit }
+ );
+ });
+
+g.test('buffer,device_mismatch')
+ .desc('Tests the image copies cannot be called with a buffer created from another device')
+ .paramsSubcasesOnly(u =>
+ u.combine('method', ['CopyB2T', 'CopyT2B'] as const).combine('mismatched', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ t.selectMismatchedDeviceOrSkipTestCase(undefined);
+ })
+ .fn(async t => {
+ const { method, mismatched } = t.params;
+ const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
+
+ const buffer = sourceDevice.createBuffer({
+ size: 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+ t.trackForCleanup(buffer);
+
+ const texture = t.device.createTexture({
+ size: { width: 2, height: 2, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const success = !mismatched;
+
+ // Expect success in both finish and submit, or validation error in finish
+ t.testBuffer(
+ buffer,
+ texture,
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 16, method, success, submit: success }
+ );
+ });
+
+g.test('usage')
+ .desc(
+ `
+Test the buffer must have the appropriate COPY_SRC/COPY_DST usage.
+TODO update such that it tests
+- for all buffer source usages
+- for all buffer destination usages
+`
+ )
+ .params(u =>
+ u
+ // B2B copy validations are at api,validation,encoding,cmds,copyBufferToBuffer.spec.ts
+ .combine('method', ['CopyB2T', 'CopyT2B'] as const)
+ .beginSubcases()
+ .combine('usage', [
+ GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.UNIFORM,
+ GPUConst.BufferUsage.COPY_DST | GPUConst.BufferUsage.UNIFORM,
+ GPUConst.BufferUsage.COPY_SRC | GPUConst.BufferUsage.COPY_DST,
+ ])
+ )
+ .fn(async t => {
+ const { method, usage } = t.params;
+
+ const buffer = t.device.createBuffer({
+ size: 16,
+ usage,
+ });
+
+ const success =
+ method === 'CopyB2T'
+ ? (usage & GPUBufferUsage.COPY_SRC) !== 0
+ : (usage & GPUBufferUsage.COPY_DST) !== 0;
+
+ const texture = t.device.createTexture({
+ size: { width: 2, height: 2, depthOrArrayLayers: 1 },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ // Expect success in both finish and submit, or validation error in finish
+ t.testBuffer(
+ buffer,
+ texture,
+ { bytesPerRow: 0 },
+ { width: 0, height: 0, depthOrArrayLayers: 0 },
+ { dataSize: 16, method, success, submit: success }
+ );
+ });
+
+g.test('bytes_per_row_alignment')
+ .desc(
+ `
+Test that bytesPerRow must be a multiple of 256 for CopyB2T and CopyT2B if it is required.
+- for all copy methods between linear data and textures
+- for all texture dimensions
+- for all sized formats.
+- for various bytesPerRow aligned to 256 or not
+- for various number of blocks rows copied
+`
+ )
+ .params(u =>
+ u //
+ .combine('method', kImageCopyTypes)
+ .combine('format', kSizedTextureFormats)
+ .filter(formatCopyableWithMethod)
+ .combine('dimension', kTextureDimensions)
+ .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format))
+ .beginSubcases()
+ .combine('bytesPerRow', [undefined, 0, 1, 255, 256, 257, 512])
+ .combine('copyHeightInBlocks', [0, 1, 2, 3])
+ .expand('_textureHeightInBlocks', p => [
+ p.copyHeightInBlocks === 0 ? 1 : p.copyHeightInBlocks,
+ ])
+ .unless(p => p.dimension === '1d' && p.copyHeightInBlocks > 1)
+ // Depth/stencil format copies must copy the whole subresource.
+ .unless(p => {
+ const info = kTextureFormatInfo[p.format];
+ return (info.depth || info.stencil) && p.copyHeightInBlocks !== p._textureHeightInBlocks;
+ })
+ // bytesPerRow must be specified and it must be equal or greater than the bytes size of each row if we are copying multiple rows.
+ // Note that we are copying one single block on each row in this test.
+ .filter(
+ ({ format, bytesPerRow, copyHeightInBlocks }) =>
+ (bytesPerRow === undefined && copyHeightInBlocks <= 1) ||
+ (bytesPerRow !== undefined && bytesPerRow >= kTextureFormatInfo[format].bytesPerBlock)
+ )
+ )
+ .beforeAllSubcases(t => {
+ const info = kTextureFormatInfo[t.params.format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const {
+ method,
+ dimension,
+ format,
+ bytesPerRow,
+ copyHeightInBlocks,
+ _textureHeightInBlocks,
+ } = t.params;
+
+ const info = kTextureFormatInfo[format];
+
+ const buffer = t.device.createBuffer({
+ size: 512 * 8 * 16,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ let success = false;
+ // writeTexture doesn't require bytesPerRow to be 256-byte aligned.
+ if (method === 'WriteTexture') success = true;
+ // If the copy height <= 1, bytesPerRow is not required.
+ if (copyHeightInBlocks <= 1 && bytesPerRow === undefined) success = true;
+ // If bytesPerRow > 0 and it is a multiple of 256, it will succeed if other parameters are valid.
+ if (bytesPerRow !== undefined && bytesPerRow > 0 && bytesPerRow % 256 === 0) success = true;
+
+ const size = [info.blockWidth, _textureHeightInBlocks * info.blockHeight, 1];
+ const texture = t.device.createTexture({
+ size,
+ dimension,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ const copySize = [info.blockWidth, copyHeightInBlocks * info.blockHeight, 1];
+
+ // Expect success in both finish and submit, or validation error in finish
+ t.testBuffer(buffer, texture, { bytesPerRow }, copySize, {
+ dataSize: 512 * 8 * 16,
+ method,
+ success,
+ submit: success,
+ });
+ });