Skip to content

Commit

Permalink
Merge branch 'main' into types46fix
Browse files Browse the repository at this point in the history
  • Loading branch information
kainino0x authored Sep 30, 2024
2 parents 29a0e6c + 1746bcb commit 5ad5fa0
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 7 deletions.
36 changes: 29 additions & 7 deletions src/webgpu/api/operation/texture_view/write.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ const kTextureViewWriteMethods = [
] as const;
type TextureViewWriteMethod = (typeof kTextureViewWriteMethods)[number];

const kTextureViewUsageMethods = ['inherit', 'minimal'] as const;
type TextureViewUsageMethod = (typeof kTextureViewUsageMethods)[number];

// Src color values to read from a shader array.
const kColorsFloat = [
{ R: 1.0, G: 0.0, B: 0.0, A: 0.8 },
Expand Down Expand Up @@ -271,6 +274,22 @@ function writeTextureAndGetExpectedTexelView(
return expectedTexelView;
}

function getTextureViewUsage(
viewUsageMethod: TextureViewUsageMethod,
minimalUsageForTest: GPUTextureUsageFlags
) {
switch (viewUsageMethod) {
case 'inherit':
return 0;

case 'minimal':
return minimalUsageForTest;

default:
unreachable();
}
}

g.test('format')
.desc(
`Views of every allowed format.
Expand All @@ -280,6 +299,7 @@ Read values from color array in the shader, and write it to the texture view via
- x= every texture format
- x= sampleCount {1, 4} if valid
- x= every possible view write method (see above)
- x= inherited or minimal texture view usage
TODO: Test sampleCount > 1 for 'render-pass-store' after extending copySinglePixelTextureToBufferUsingComputePass
to read multiple pixels from multisampled textures. [1]
Expand Down Expand Up @@ -318,6 +338,7 @@ TODO: Test rgb10a2uint when TexelRepresentation.numericRange is made per-compone
}
return true;
})
.combine('viewUsageMethod', kTextureViewUsageMethods)
)
.beforeAllSubcases(t => {
const { format, method } = t.params;
Expand All @@ -332,13 +353,12 @@ TODO: Test rgb10a2uint when TexelRepresentation.numericRange is made per-compone
}
})
.fn(t => {
const { format, method, sampleCount } = t.params;
const { format, method, sampleCount, viewUsageMethod } = t.params;

const usage =
GPUTextureUsage.COPY_SRC |
(method.includes('storage')
? GPUTextureUsage.STORAGE_BINDING
: GPUTextureUsage.RENDER_ATTACHMENT);
const textureUsageForMethod = method.includes('storage')
? GPUTextureUsage.STORAGE_BINDING
: GPUTextureUsage.RENDER_ATTACHMENT;
const usage = GPUTextureUsage.COPY_SRC | textureUsageForMethod;

const texture = t.createTextureTracked({
format,
Expand All @@ -347,7 +367,9 @@ TODO: Test rgb10a2uint when TexelRepresentation.numericRange is made per-compone
sampleCount,
});

const view = texture.createView();
const view = texture.createView({
usage: getTextureViewUsage(viewUsageMethod, textureUsageForMethod),
});
const expectedTexelView = writeTextureAndGetExpectedTexelView(
t,
method,
Expand Down
72 changes: 72 additions & 0 deletions src/webgpu/api/validation/createView.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { unreachable } from '../../../common/util/util.js';
import {
kTextureAspects,
kTextureDimensions,
kTextureUsages,
kTextureViewDimensions,
} from '../../capability_info.js';
import { GPUConst } from '../../constants.js';
import {
kTextureFormatInfo,
kAllTextureFormats,
Expand Down Expand Up @@ -339,3 +341,73 @@ g.test('texture_state')
texture.createView();
}, state === 'invalid');
});

g.test('texture_view_usage')
.desc(
`Test texture view usage (single, combined, inherited) for every texture format and texture usage`
)
.params(u =>
u //
.combine('format', kAllTextureFormats)
.combine('textureUsage0', kTextureUsages)
.combine('textureUsage1', kTextureUsages)
.filter(({ format, textureUsage0, textureUsage1 }) => {
const info = kTextureFormatInfo[format];
const textureUsage = textureUsage0 | textureUsage1;

if (
(textureUsage & GPUConst.TextureUsage.RENDER_ATTACHMENT) !== 0 &&
info.color &&
!info.colorRender
) {
return false;
}

return true;
})
.beginSubcases()
.combine('textureViewUsage0', [0, ...kTextureUsages])
.combine('textureViewUsage1', [0, ...kTextureUsages])
)
.beforeAllSubcases(t => {
const { format, textureUsage0, textureUsage1 } = t.params;
const info = kTextureFormatInfo[format];
const textureUsage = textureUsage0 | textureUsage1;
t.skipIfTextureFormatNotSupported(format);
t.selectDeviceOrSkipTestCase(info.feature);
if (textureUsage & GPUTextureUsage.STORAGE_BINDING) {
t.skipIfTextureFormatNotUsableAsStorageTexture(format);
}
})
.fn(t => {
const { format, textureUsage0, textureUsage1, textureViewUsage0, textureViewUsage1 } = t.params;
const info = kTextureFormatInfo[format];

const size = [info.blockWidth, info.blockHeight, 1];
const dimension = '2d';
const mipLevelCount = 1;
const usage = textureUsage0 | textureUsage1;

const textureDescriptor: GPUTextureDescriptor = {
size,
mipLevelCount,
dimension,
format,
usage,
};

const texture = t.createTextureTracked(textureDescriptor);

let success = true;

const textureViewUsage = textureViewUsage0 | textureViewUsage1;

// Texture view usage must be a subset of texture usage
if ((~usage & textureViewUsage) !== 0) success = false;

t.expectValidationError(() => {
texture.createView({
usage: textureViewUsage,
});
}, !success);
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Texture Usages Validation Tests on All Kinds of WebGPU Subresource Usage Scopes.

import { makeTestGroup } from '../../../../../common/framework/test_group.js';
import { unreachable } from '../../../../../common/util/util.js';
import { kTextureUsages } from '../../../../capability_info.js';
import { ValidationTest } from '../../validation_test.js';
import {
TextureBindingType,
Expand Down Expand Up @@ -571,3 +572,79 @@ g.test('subresources,texture_usages_in_copy_and_render_pass')
encoder.finish();
}, false);
});

g.test('subresources,texture_view_usages')
.desc(
`
Test that the usages of the texture view are used to validate compatibility in command encoding
instead of the usages of the base texture.`
)
.params(u =>
u
.combine('bindingType', ['color-attachment', ...kTextureBindingTypes] as const)
.combine('viewUsage', [0, ...kTextureUsages])
)
.fn(t => {
const { bindingType, viewUsage } = t.params;

const texture = t.createTextureTracked({
format: 'r32float',
usage:
GPUTextureUsage.COPY_SRC |
GPUTextureUsage.COPY_DST |
GPUTextureUsage.TEXTURE_BINDING |
GPUTextureUsage.STORAGE_BINDING |
GPUTextureUsage.RENDER_ATTACHMENT,
size: [kTextureSize, kTextureSize, 1],
...(t.isCompatibility && {
textureBindingViewDimension: '2d-array',
}),
});

switch (bindingType) {
case 'color-attachment': {
const encoder = t.device.createCommandEncoder();
const renderPassEncoder = encoder.beginRenderPass({
colorAttachments: [
{ view: texture.createView({ usage: viewUsage }), loadOp: 'load', storeOp: 'store' },
],
});
renderPassEncoder.end();

const success = viewUsage === 0 || (viewUsage & GPUTextureUsage.RENDER_ATTACHMENT) !== 0;

t.expectValidationError(() => {
encoder.finish();
}, !success);
break;
}
case 'sampled-texture':
case 'readonly-storage-texture':
case 'writeonly-storage-texture':
case 'readwrite-storage-texture':
{
let success = true;
if (viewUsage !== 0) {
if (bindingType === 'sampled-texture') {
if ((viewUsage & GPUTextureUsage.TEXTURE_BINDING) === 0) success = false;
} else {
if ((viewUsage & GPUTextureUsage.STORAGE_BINDING) === 0) success = false;
}
}

t.expectValidationError(() => {
t.createBindGroupForTest(
texture.createView({
dimension: '2d-array',
usage: viewUsage,
}),
bindingType,
'unfilterable-float'
);
}, !success);
}
break;
default:
unreachable();
}
});

0 comments on commit 5ad5fa0

Please sign in to comment.