Skip to content

Commit 88db5da

Browse files
authored
Refactor render_pass_descriptor tests for texture formats. (#4197)
Issue #4181
1 parent 1245e3f commit 88db5da

File tree

3 files changed

+69
-41
lines changed

3 files changed

+69
-41
lines changed

src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts

+22-40
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@ import { GPUConst } from '../../../constants.js';
1212
import {
1313
computeBytesPerSampleFromFormats,
1414
kDepthStencilFormats,
15-
kRenderableColorTextureFormats,
16-
kTextureFormatInfo,
15+
kPossiblyRenderableColorTextureFormats,
16+
isTextureFormatColorRenderable,
17+
isDepthTextureFormat,
18+
isStencilTextureFormat,
19+
isTextureFormatResolvable,
1720
} from '../../../format_info.js';
18-
import { ValidationTest } from '../validation_test.js';
21+
import { AllFeaturesMaxLimitsValidationTest } from '../validation_test.js';
1922

2023
// MAINTENANCE_TODO: This should be changed to kMaxColorAttachmentsToTest
2124
// when this is made a MaxLimitTest (see above).
2225
const kMaxColorAttachments = getDefaultLimits('core').maxColorAttachments.default;
2326

24-
class F extends ValidationTest {
27+
class F extends AllFeaturesMaxLimitsValidationTest {
2528
createTestTexture(
2629
options: {
2730
format?: GPUTextureFormat;
@@ -202,20 +205,18 @@ g.test('color_attachments,limits,maxColorAttachmentBytesPerSample,aligned')
202205
)
203206
.params(u =>
204207
u
205-
.combine('format', kRenderableColorTextureFormats)
208+
.combine('format', kPossiblyRenderableColorTextureFormats)
206209
.beginSubcases()
207210
.combine(
208211
'attachmentCount',
209212
range(kMaxColorAttachments, i => i + 1)
210213
)
211214
)
212-
.beforeAllSubcases(t => {
213-
t.skipIfTextureFormatNotSupportedDeprecated(t.params.format);
214-
})
215215
.fn(t => {
216216
const { format, attachmentCount } = t.params;
217-
const info = kTextureFormatInfo[format];
218217

218+
t.skipIfTextureFormatNotSupported(format);
219+
t.skipIfTextureFormatNotUsableAsRenderAttachment(format);
219220
t.skipIf(
220221
attachmentCount > t.device.limits.maxColorAttachments,
221222
`attachmentCount: ${attachmentCount} > maxColorAttachments: ${t.device.limits.maxColorAttachments}`
@@ -227,7 +228,7 @@ g.test('color_attachments,limits,maxColorAttachmentBytesPerSample,aligned')
227228
colorAttachments.push(t.getColorAttachment(colorTexture));
228229
}
229230
const shouldError =
230-
info.colorRender === undefined ||
231+
!isTextureFormatColorRenderable(t.device, format) ||
231232
computeBytesPerSampleFromFormats(range(attachmentCount, () => format)) >
232233
t.device.limits.maxColorAttachmentBytesPerSample;
233234

@@ -1049,10 +1050,6 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO
10491050
.combine('stencilLoadOp', [undefined, 'clear', 'load'] as GPULoadOp[])
10501051
.combine('stencilStoreOp', [undefined, 'discard', 'store'] as GPUStoreOp[])
10511052
)
1052-
.beforeAllSubcases(t => {
1053-
const info = kTextureFormatInfo[t.params.format as GPUTextureFormat];
1054-
t.selectDeviceOrSkipTestCase(info.feature);
1055-
})
10561053
.fn(t => {
10571054
const {
10581055
format,
@@ -1064,6 +1061,8 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO
10641061
stencilStoreOp,
10651062
} = t.params;
10661063

1064+
t.skipIfTextureFormatNotSupported(format);
1065+
10671066
const depthAttachment = t.createTextureTracked({
10681067
format,
10691068
size: { width: 1, height: 1, depthOrArrayLayers: 1 },
@@ -1092,11 +1091,10 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO
10921091
const pass = encoder.beginRenderPass(renderPassDescriptor);
10931092
pass.end();
10941093

1095-
const info = kTextureFormatInfo[format];
10961094
const hasDepthSettings = !!depthLoadOp && !!depthStoreOp && !depthReadOnly;
10971095
const hasStencilSettings = !!stencilLoadOp && !!stencilStoreOp && !stencilReadOnly;
1098-
const hasDepth = info.depth;
1099-
const hasStencil = info.stencil;
1096+
const hasDepth = isDepthTextureFormat(format);
1097+
const hasStencil = isStencilTextureFormat(format);
11001098

11011099
const goodAspectSettingsPresent =
11021100
(hasDepthSettings ? hasDepth : true) && (hasStencilSettings ? hasStencil : true);
@@ -1162,27 +1160,19 @@ g.test('resolveTarget,format_supports_resolve')
11621160
if and only if they support 'resolve'.
11631161
`
11641162
)
1165-
.params(u =>
1166-
u
1167-
.combine('format', kRenderableColorTextureFormats)
1168-
.filter(t => kTextureFormatInfo[t.format].multisample)
1169-
)
1170-
.beforeAllSubcases(t => {
1171-
const { format } = t.params;
1172-
t.skipIfTextureFormatNotSupportedDeprecated(format);
1173-
t.skipIfMultisampleNotSupportedForFormatDeprecated(format);
1174-
})
1163+
.params(u => u.combine('format', kPossiblyRenderableColorTextureFormats))
11751164
.fn(t => {
11761165
const { format } = t.params;
1177-
const info = kTextureFormatInfo[format];
1166+
t.skipIfTextureFormatNotSupported(format);
1167+
t.skipIfMultisampleNotSupportedForFormat(format);
11781168

11791169
const multisampledColorTexture = t.createTestTexture({ format, sampleCount: 4 });
11801170
const resolveTarget = t.createTestTexture({ format });
11811171

11821172
const colorAttachment = t.getColorAttachment(multisampledColorTexture);
11831173
colorAttachment.resolveTarget = resolveTarget.createView();
11841174

1185-
t.tryRenderPass(!!info.colorRender?.resolve, {
1175+
t.tryRenderPass(isTextureFormatResolvable(t.device, format), {
11861176
colorAttachments: [colorAttachment],
11871177
});
11881178
});
@@ -1198,10 +1188,8 @@ g.test('timestampWrites,query_set_type')
11981188
u //
11991189
.combine('queryType', kQueryTypes)
12001190
)
1201-
.beforeAllSubcases(t => {
1202-
t.selectDeviceOrSkipTestCase(['timestamp-query']);
1203-
})
12041191
.fn(t => {
1192+
t.skipIfDeviceDoesNotSupportQueryType('timestamp');
12051193
const { queryType } = t.params;
12061194

12071195
const timestampWrites = {
@@ -1231,10 +1219,8 @@ g.test('timestampWrite,query_index')
12311219
.combine('beginningOfPassWriteIndex', [undefined, 0, 1, 2, 3] as const)
12321220
.combine('endOfPassWriteIndex', [undefined, 0, 1, 2, 3] as const)
12331221
)
1234-
.beforeAllSubcases(t => {
1235-
t.selectDeviceOrSkipTestCase(['timestamp-query']);
1236-
})
12371222
.fn(t => {
1223+
t.skipIfDeviceDoesNotSupportQueryType('timestamp');
12381224
const { beginningOfPassWriteIndex, endOfPassWriteIndex } = t.params;
12391225

12401226
const querySetCount = 2;
@@ -1262,13 +1248,9 @@ g.test('timestampWrite,query_index')
12621248
g.test('occlusionQuerySet,query_set_type')
12631249
.desc(`Test that occlusionQuerySet must have type 'occlusion'.`)
12641250
.params(u => u.combine('queryType', kQueryTypes))
1265-
.beforeAllSubcases(t => {
1266-
if (t.params.queryType === 'timestamp') {
1267-
t.selectDeviceOrSkipTestCase(['timestamp-query']);
1268-
}
1269-
})
12701251
.fn(t => {
12711252
const { queryType } = t.params;
1253+
t.skipIfDeviceDoesNotSupportQueryType(queryType);
12721254

12731255
const querySet = t.createQuerySetTracked({
12741256
type: queryType,

src/webgpu/format_info.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -1438,10 +1438,19 @@ const kASTCTextureFormatInfo = formatTableWithDefaults({
14381438
/* prettier-ignore */ export const kAllTextureFormats: readonly GPUTextureFormat[] = keysOf( kAllTextureFormatInfo);
14391439

14401440
// CompressedTextureFormat are unrenderable so filter from RegularTextureFormats for color targets is enough
1441+
// @deprecated
14411442
export const kRenderableColorTextureFormats = kRegularTextureFormats.filter(
14421443
v => kColorTextureFormatInfo[v].colorRender
14431444
);
14441445

1446+
// Color formats that are possibly renderable. Some may require features to be enabled.
1447+
// MAINTENANCE_TODO: remove 'rg11b10ufloat` once colorRender is added to its info.
1448+
// See: computeBytesPerSampleFromFormats
1449+
export const kPossiblyRenderableColorTextureFormats = [
1450+
...kRegularTextureFormats.filter(v => kColorTextureFormatInfo[v].colorRender),
1451+
'rg11b10ufloat',
1452+
] as const;
1453+
14451454
/** Per-GPUTextureFormat-per-aspect info. */
14461455
interface TextureFormatAspectInfo {
14471456
/** Whether the aspect can be used as `COPY_SRC`. */
@@ -2042,7 +2051,14 @@ export const kFeaturesForFormats = getFeaturesForFormats(kAllTextureFormats);
20422051
export function computeBytesPerSampleFromFormats(formats: readonly GPUTextureFormat[]) {
20432052
let bytesPerSample = 0;
20442053
for (const format of formats) {
2045-
const info = kTextureFormatInfo[format];
2054+
// MAINTENANCE_TODO: Add colorRender to rg11b10ufloat format in kTextureFormatInfo
2055+
// The issue is if we add it now lots of tests will break as they'll think they can
2056+
// render to the format but are not enabling 'rg11b10ufloat-renderable'. Once we
2057+
// get the CTS refactored (see issue 4181), then fix this.
2058+
const info =
2059+
format === 'rg11b10ufloat'
2060+
? { colorRender: { alignment: 4, byteCost: 8 } }
2061+
: kTextureFormatInfo[format];
20462062
const alignedBytesPerSample = align(bytesPerSample, info.colorRender!.alignment);
20472063
bytesPerSample = alignedBytesPerSample + info.colorRender!.byteCost;
20482064
}

src/webgpu/gpu_test.ts

+30
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
isMultisampledTextureFormatDeprecated,
3737
isTextureFormatUsableAsStorageFormat,
3838
isTextureFormatUsableAsRenderAttachment,
39+
isTextureFormatMultisampled,
3940
} from './format_info.js';
4041
import { checkElementsEqual, checkElementsBetween } from './util/check_contents.js';
4142
import { CommandBufferMaker, EncoderType } from './util/command_buffer_maker.js';
@@ -524,6 +525,26 @@ export class GPUTestBase extends Fixture<GPUTestSubcaseBatchState> {
524525
}
525526
}
526527

528+
/**
529+
* Skips test if device does not have feature.
530+
* Note: Try to use one of the more specific skipIf tests if possible.
531+
*/
532+
skipIfDeviceDoesNotHaveFeature(feature: GPUFeatureName) {
533+
this.skipIf(!this.device.features.has(feature), `device does not have feature: '${feature}'`);
534+
}
535+
536+
/**
537+
* Skips test if device des not support query type.
538+
*/
539+
skipIfDeviceDoesNotSupportQueryType(...types: GPUQueryType[]) {
540+
for (const type of types) {
541+
const feature = kQueryTypeInfo[type].feature;
542+
if (feature) {
543+
this.skipIfDeviceDoesNotHaveFeature(feature);
544+
}
545+
}
546+
}
547+
527548
/**
528549
* Skips test if any format is not supported.
529550
*/
@@ -545,6 +566,15 @@ export class GPUTestBase extends Fixture<GPUTestSubcaseBatchState> {
545566
}
546567
}
547568

569+
skipIfMultisampleNotSupportedForFormat(...formats: (GPUTextureFormat | undefined)[]) {
570+
for (const format of formats) {
571+
if (format === undefined) continue;
572+
if (!isTextureFormatMultisampled(this.device, format)) {
573+
this.skip(`texture format '${format}' is not supported to be multisampled`);
574+
}
575+
}
576+
}
577+
548578
/** @deprecated */
549579
skipIfTextureViewDimensionNotSupportedDeprecated(
550580
...dimensions: (GPUTextureViewDimension | undefined)[]

0 commit comments

Comments
 (0)