Skip to content

Commit

Permalink
Compat: fix float16(32)-renderable tests (validation) (gpuweb#4152)
Browse files Browse the repository at this point in the history
* Compat: fix float16(32)-renderable tests (validation)

* address review comments

* address review comments 2

* fix

* fix2
  • Loading branch information
shrekshao authored Jan 22, 2025
1 parent 9273480 commit c30b7f8
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ import {
} from './limit_utils.js';

const kFormatsToUseBySize: GPUTextureFormat[] = [
'rgba32float',
'rgba16float',
'rgba32uint',
'rgba16uint',
'rgba8unorm',
'rg8unorm',
'r8unorm',
];

const kInterleaveFormats: GPUTextureFormat[] = [
'rgba16float',
'rg16float',
'rgba16uint',
'rg16uint',
'rgba8unorm',
'rg8unorm',
'r8unorm',
Expand Down
18 changes: 14 additions & 4 deletions src/webgpu/api/validation/createBindGroup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import { getTextureDimensionFromView } from '../../util/texture/base.js';

import { ValidationTest } from './validation_test.js';

const kTestFormat: GPUTextureFormat = 'r32float';

function clone<T extends GPUTextureDescriptor>(descriptor: T): T {
return JSON.parse(JSON.stringify(descriptor));
}
Expand Down Expand Up @@ -144,7 +146,7 @@ g.test('binding_must_contain_resource_defined_in_layout')
.params(u =>
u //
.combine('resourceType', kBindableResources)
.combine('entry', allBindingEntries(false))
.combine('entry', allBindingEntries(false, kTestFormat))
)
.fn(t => {
const { resourceType, entry } = t.params;
Expand Down Expand Up @@ -195,18 +197,26 @@ g.test('texture_binding_must_have_correct_usage')
.desc('Tests that texture bindings must have the correct usage.')
.paramsSubcasesOnly(u =>
u //
.combine('entry', sampledAndStorageBindingEntries(false))
.combine('entry', sampledAndStorageBindingEntries(false, kTestFormat))
.combine('usage', kTextureUsages)
.unless(({ entry, usage }) => {
const info = texBindingTypeInfo(entry);
// Can't create the texture for this (usage=STORAGE_BINDING and sampleCount=4), so skip.
return usage === GPUConst.TextureUsage.STORAGE_BINDING && info.resource === 'sampledTexMS';
})
)
.beforeAllSubcases(t => {
t.selectDeviceForRenderableColorFormatOrSkipTestCase(kTestFormat);
})
.fn(t => {
const { entry, usage } = t.params;
const info = texBindingTypeInfo(entry);

t.skipIf(
t.isCompatibility && info.resource === 'sampledTexMS',
"The test requires 'r32float' multisampled support which compat mode doesn't guarantee."
);

const bindGroupLayout = t.device.createBindGroupLayout({
entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, ...entry }],
});
Expand All @@ -217,7 +227,7 @@ g.test('texture_binding_must_have_correct_usage')

const descriptor = {
size: { width: 16, height: 16, depthOrArrayLayers: 1 },
format: 'r32float' as const,
format: kTestFormat,
usage: appliedUsage,
sampleCount: info.resource === 'sampledTexMS' ? 4 : 1,
};
Expand Down Expand Up @@ -601,7 +611,7 @@ g.test('texture,resource_state')
.paramsSubcasesOnly(u =>
u
.combine('state', kResourceStates)
.combine('entry', sampledAndStorageBindingEntries(true))
.combine('entry', sampledAndStorageBindingEntries(true, kTestFormat))
.combine('visibilityMask', [kAllShaderStages, GPUConst.ShaderStage.COMPUTE] as const)
)
.fn(t => {
Expand Down
6 changes: 6 additions & 0 deletions src/webgpu/api/validation/createTexture.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,16 @@ g.test('sampleCount,valid_sampleCount_with_other_parameter_varies')
const info = kTextureFormatInfo[format];
t.skipIfTextureFormatNotSupported(format);
t.selectDeviceOrSkipTestCase(info.feature);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(format);
})
.fn(t => {
const { dimension, sampleCount, format, mipLevelCount, arrayLayerCount, usage } = t.params;
const { blockWidth, blockHeight } = kTextureFormatInfo[format];

if (sampleCount > 1) {
t.skipIfMultisampleNotSupportedForFormat(format);
}

const size =
dimension === '1d'
? [32 * blockWidth, 1 * blockHeight, 1]
Expand Down Expand Up @@ -1047,6 +1052,7 @@ g.test('texture_usage')
const info = kTextureFormatInfo[format];
t.skipIfTextureFormatNotSupported(format);
t.selectDeviceOrSkipTestCase(info.feature);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(format);
})
.fn(t => {
const { dimension, format, usage0, usage1 } = t.params;
Expand Down
3 changes: 3 additions & 0 deletions src/webgpu/api/validation/createView.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,9 @@ g.test('texture_view_usage')
if (textureUsage & GPUTextureUsage.STORAGE_BINDING) {
t.skipIfTextureFormatNotUsableAsStorageTexture(format);
}
if (textureUsage & GPUTextureUsage.RENDER_ATTACHMENT) {
t.selectDeviceForRenderableColorFormatOrSkipTestCase(format);
}
})
.fn(t => {
const { format, textureUsage0, textureUsage1, textureViewUsage0, textureViewUsage1 } = t.params;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ g.test('attachment_state,limits,maxColorAttachmentBytesPerSample,aligned')
)
.beforeAllSubcases(t => {
t.skipIfTextureFormatNotSupported(t.params.format);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(t.params.format);
})
.fn(t => {
const { format, colorFormatCount } = t.params;
Expand Down Expand Up @@ -118,6 +119,9 @@ g.test('attachment_state,limits,maxColorAttachmentBytesPerSample,unaligned')
},
])
)
.beforeAllSubcases(t => {
t.selectDeviceForRenderableColorFormatOrSkipTestCase('r32float');
})
.fn(t => {
const { formats } = t.params;

Expand Down Expand Up @@ -168,6 +172,7 @@ g.test('valid_texture_formats')
.beforeAllSubcases(t => {
const { format } = t.params;
t.selectDeviceForTextureFormatOrSkipTestCase(format);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(format);
})
.fn(t => {
const { format, attachment } = t.params;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,7 @@ g.test('destination_texture,format')
const { format } = t.params;
t.skipIfTextureFormatNotSupported(format);
t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(format);
})
.fn(async t => {
const { format, copySize } = t.params;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ g.test('render_pass_and_bundle,color_format')
const { passFormat, bundleFormat } = t.params;

t.skipIfTextureFormatNotSupported(passFormat, bundleFormat);
t.skipIfColorRenderableNotSupportedForFormat(passFormat, bundleFormat);

const bundleEncoder = t.device.createRenderBundleEncoder({
colorFormats: [bundleFormat],
Expand Down Expand Up @@ -358,7 +359,7 @@ g.test('render_pass_and_bundle,device_mismatch')
const { mismatched } = t.params;
const sourceDevice = mismatched ? t.mismatchedDevice : t.device;

const format = 'r16float';
const format = 'r16uint';
const bundleEncoder = sourceDevice.createRenderBundleEncoder({
colorFormats: [format],
});
Expand Down Expand Up @@ -390,6 +391,7 @@ Test that color attachment formats in render passes or bundles match the pipelin
const { encoderType, encoderFormat, pipelineFormat } = t.params;

t.skipIfTextureFormatNotSupported(encoderFormat, pipelineFormat);
t.skipIfColorRenderableNotSupportedForFormat(encoderFormat, pipelineFormat);

const pipeline = t.createRenderPipeline([{ format: pipelineFormat, writeMask: 0 }]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ g.test('color_attachments,limits,maxColorAttachmentBytesPerSample,aligned')
)
.beforeAllSubcases(t => {
t.skipIfTextureFormatNotSupported(t.params.format);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(t.params.format);
})
.fn(t => {
const { format, attachmentCount } = t.params;
Expand Down Expand Up @@ -267,6 +268,9 @@ g.test('color_attachments,limits,maxColorAttachmentBytesPerSample,unaligned')
},
])
)
.beforeAllSubcases(t => {
t.selectDeviceForRenderableColorFormatOrSkipTestCase('r32float');
})
.fn(t => {
const { formats } = t.params;

Expand Down Expand Up @@ -1168,7 +1172,10 @@ g.test('resolveTarget,format_supports_resolve')
.filter(t => kTextureFormatInfo[t.format].multisample)
)
.beforeAllSubcases(t => {
t.skipIfTextureFormatNotSupported(t.params.format);
const { format } = t.params;
t.skipIfTextureFormatNotSupported(format);
t.skipIfMultisampleNotSupportedForFormat(format);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(format);
})
.fn(t => {
const { format } = t.params;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pipeline that uses blending with any float32-format attachment.
if (t.params.enabled) {
t.selectDeviceOrSkipTestCase('float32-blendable');
}
t.selectDeviceForRenderableColorFormatOrSkipTestCase('r32float');
})
.fn(t => {
const { isAsync, enabled, hasBlend, format } = t.params;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ g.test('limits,maxColorAttachmentBytesPerSample,aligned')
)
.beforeAllSubcases(t => {
t.skipIfTextureFormatNotSupported(t.params.format);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(t.params.format);
})
.fn(t => {
const { format, attachmentCount, isAsync } = t.params;
Expand Down Expand Up @@ -228,6 +229,9 @@ g.test('limits,maxColorAttachmentBytesPerSample,unaligned')
.beginSubcases()
.combine('isAsync', [false, true])
)
.beforeAllSubcases(t => {
t.selectDeviceForRenderableColorFormatOrSkipTestCase('r32float');
})
.fn(t => {
const { formats, isAsync } = t.params;

Expand Down Expand Up @@ -394,6 +398,7 @@ g.test('pipeline_output_targets')
)
.beforeAllSubcases(t => {
t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
t.selectDeviceForRenderableColorFormatOrSkipTestCase(t.params.format);
})
.fn(t => {
const { isAsync, format, writeMask, shaderOutput } = t.params;
Expand Down
25 changes: 17 additions & 8 deletions src/webgpu/capability_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,16 +592,22 @@ export function textureBindingEntries(includeUndefined: boolean): readonly BGLEn
*
* Note: Generates different `access` options, but not `format` or `viewDimension` options.
*/
export function storageTextureBindingEntries(): readonly BGLEntry[] {
export function storageTextureBindingEntries(format: GPUTextureFormat): readonly BGLEntry[] {
return [
{ storageTexture: { access: 'write-only', format: 'r32float' } },
{ storageTexture: { access: 'read-only', format: 'r32float' } },
{ storageTexture: { access: 'read-write', format: 'r32float' } },
{ storageTexture: { access: 'write-only', format } },
{ storageTexture: { access: 'read-only', format } },
{ storageTexture: { access: 'read-write', format } },
] as const;
}
/** Generate a list of possible texture-or-storageTexture-typed BGLEntry values. */
export function sampledAndStorageBindingEntries(includeUndefined: boolean): readonly BGLEntry[] {
return [...textureBindingEntries(includeUndefined), ...storageTextureBindingEntries()] as const;
export function sampledAndStorageBindingEntries(
includeUndefined: boolean,
format: GPUTextureFormat = 'r32float'
): readonly BGLEntry[] {
return [
...textureBindingEntries(includeUndefined),
...storageTextureBindingEntries(format),
] as const;
}
/**
* Generate a list of possible BGLEntry values of every type, but not variants with different:
Expand All @@ -610,11 +616,14 @@ export function sampledAndStorageBindingEntries(includeUndefined: boolean): read
* - texture.viewDimension
* - storageTexture.viewDimension
*/
export function allBindingEntries(includeUndefined: boolean): readonly BGLEntry[] {
export function allBindingEntries(
includeUndefined: boolean,
format: GPUTextureFormat = 'r32float'
): readonly BGLEntry[] {
return [
...bufferBindingEntries(includeUndefined),
...samplerBindingEntries(includeUndefined),
...sampledAndStorageBindingEntries(includeUndefined),
...sampledAndStorageBindingEntries(includeUndefined, format),
] as const;
}

Expand Down
81 changes: 81 additions & 0 deletions src/webgpu/gpu_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
isTextureFormatUsableAsStorageFormat,
is32Float,
is16Float,
isMultisampledTextureFormat,
} from './format_info.js';
import { checkElementsEqual, checkElementsBetween } from './util/check_contents.js';
import { CommandBufferMaker, EncoderType } from './util/command_buffer_maker.js';
Expand Down Expand Up @@ -288,6 +289,46 @@ export class GPUTestSubcaseBatchState extends SubcaseBatchState {
}
}

skipIfMultisampleNotSupportedForFormat(...formats: (GPUTextureFormat | undefined)[]) {
if (this.isCompatibility) {
for (const format of formats) {
if (format === undefined) continue;
if (format === 'rgba16float' || is32Float(format)) {
this.skip(
`texture format '${format} is not guaranteed to be multisampled support in compat mode`
);
}
}
}

for (const format of formats) {
if (format === undefined) continue;
if (!isMultisampledTextureFormat(format)) {
this.skip(`texture format '${format} is not supported to be multisampled`);
}
}
}

skipIfColorRenderableNotSupportedForFormat(...formats: (GPUTextureFormat | undefined)[]) {
if (this.isCompatibility) {
for (const format of formats) {
if (format === undefined) continue;
if (is16Float(format) || is32Float(format)) {
this.skip(
`texture format '${format} is not guaranteed to be color renderable in compat mode`
);
}
}
}

for (const format of formats) {
if (format === undefined) continue;
if (!kTextureFormatInfo[format].color) {
this.skip(`texture format '${format} is not color renderable`);
}
}
}

getFloatTextureFormatColorRenderableFeatures(...formats: (GPUTextureFormat | undefined)[]) {
const requiredFeatures: GPUFeatureName[] = [];
if (this.isCompatibility) {
Expand Down Expand Up @@ -543,6 +584,46 @@ export class GPUTestBase extends Fixture<GPUTestSubcaseBatchState> {
}
}

skipIfMultisampleNotSupportedForFormat(...formats: (GPUTextureFormat | undefined)[]) {
if (this.isCompatibility) {
for (const format of formats) {
if (format === undefined) continue;
if (format === 'rgba16float' || is32Float(format)) {
this.skip(
`texture format '${format} is not guaranteed to be multisampled support in compat mode`
);
}
}
}

for (const format of formats) {
if (format === undefined) continue;
if (!isMultisampledTextureFormat(format)) {
this.skip(`texture format '${format} is not supported to be multisampled`);
}
}
}

skipIfColorRenderableNotSupportedForFormat(...formats: (GPUTextureFormat | undefined)[]) {
if (this.isCompatibility) {
for (const format of formats) {
if (format === undefined) continue;
if (is16Float(format) || is32Float(format)) {
this.skip(
`texture format '${format} is not guaranteed to be color renderable in compat mode`
);
}
}
}

for (const format of formats) {
if (format === undefined) continue;
if (!kTextureFormatInfo[format].color) {
this.skip(`texture format '${format} is not color renderable`);
}
}
}

skipIfTextureViewDimensionNotSupported(...dimensions: (GPUTextureViewDimension | undefined)[]) {
if (this.isCompatibility) {
for (const dimension of dimensions) {
Expand Down

0 comments on commit c30b7f8

Please sign in to comment.