Skip to content

Commit

Permalink
Refactor compat tests for texture formats (#4198)
Browse files Browse the repository at this point in the history
Issue #4181
  • Loading branch information
greggman authored Feb 21, 2025
1 parent 88db5da commit a6e2c34
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ Tests limitations of copyTextureToBuffer in compat mode.
`;

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import { kCompressedTextureFormats, kTextureFormatInfo } from '../../../../../format_info.js';
import {
getBlockInfoForColorTextureFormat,
kCompressedTextureFormats,
} from '../../../../../format_info.js';
import { align } from '../../../../../util/math.js';
import { CompatibilityTest } from '../../../../compatibility_test.js';

Expand All @@ -12,14 +15,11 @@ export const g = makeTestGroup(CompatibilityTest);
g.test('compressed')
.desc(`Tests that you can not call copyTextureToBuffer with compressed textures in compat mode.`)
.params(u => u.combine('format', kCompressedTextureFormats))
.beforeAllSubcases(t => {
const { format } = t.params;
t.selectDeviceOrSkipTestCase([kTextureFormatInfo[format].feature]);
})
.fn(t => {
const { format } = t.params;
t.skipIfTextureFormatNotSupported(format);

const info = kTextureFormatInfo[format];
const info = getBlockInfoForColorTextureFormat(format);

const textureSize = [info.blockWidth, info.blockHeight, 1];
const texture = t.createTextureTracked({
Expand All @@ -28,7 +28,7 @@ g.test('compressed')
usage: GPUTextureUsage.COPY_SRC,
});

const bytesPerRow = align(info.color.bytes, 256);
const bytesPerRow = align(info.bytesPerBlock, 256);

const buffer = t.createBufferTracked({
size: bytesPerRow,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ Tests limitations of copyTextureToTextures in compat mode.

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import {
kAllTextureFormats,
getBlockInfoForColorTextureFormat,
getBlockInfoForTextureFormat,
kCompressedTextureFormats,
kTextureFormatInfo,
kPossibleMultisampledTextureFormats,
} from '../../../../../format_info.js';
import { CompatibilityTest } from '../../../../compatibility_test.js';

Expand All @@ -15,14 +16,11 @@ export const g = makeTestGroup(CompatibilityTest);
g.test('compressed')
.desc(`Tests that you can not call copyTextureToTexture with compressed textures in compat mode.`)
.params(u => u.combine('format', kCompressedTextureFormats))
.beforeAllSubcases(t => {
const { format } = t.params;
t.selectDeviceOrSkipTestCase([kTextureFormatInfo[format].feature]);
})
.fn(t => {
const { format } = t.params;
t.skipIfTextureFormatNotSupported(format);

const { blockWidth, blockHeight } = kTextureFormatInfo[format];
const { blockWidth, blockHeight } = getBlockInfoForColorTextureFormat(format);

const srcTexture = t.createTextureTracked({
size: [blockWidth, blockHeight, 1],
Expand All @@ -49,23 +47,13 @@ g.test('compressed')

g.test('multisample')
.desc(`Test that you can not call copyTextureToTexture with multisample textures in compat mode.`)
.params(u =>
u
.combine('format', kAllTextureFormats)
.beginSubcases()
.filter(({ format }) => {
const info = kTextureFormatInfo[format];
return info.multisample && !info.feature;
})
)
.beforeAllSubcases(t => {
t.skipIfMultisampleNotSupportedForFormatDeprecated(t.params.format);
})
.params(u => u.combine('format', kPossibleMultisampledTextureFormats))
.fn(t => {
const { format } = t.params;
const { blockWidth, blockHeight } = kTextureFormatInfo[format];
const { blockWidth, blockHeight } = getBlockInfoForTextureFormat(format);

t.skipIfTextureFormatNotSupportedDeprecated(format as GPUTextureFormat);
t.skipIfTextureFormatNotSupported(format);
t.skipIfTextureFormatNotMultisampled(format);

const srcTexture = t.createTextureTracked({
size: [blockWidth, blockHeight, 1],
Expand Down
29 changes: 11 additions & 18 deletions src/webgpu/compat/api/validation/texture/createTexture.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ Tests that textureBindingViewDimension must compatible with texture dimension
import { makeTestGroup } from '../../../../../common/framework/test_group.js';
import { kTextureDimensions, kTextureViewDimensions } from '../../../../capability_info.js';
import {
kColorTextureFormats,
kCompatModeUnsupportedStorageTextureFormats,
kTextureFormatInfo,
kDifferentBaseFormatTextureFormats,
getBlockInfoForTextureFormat,
getBaseFormatForTextureFormat,
} from '../../../../format_info.js';
import { getTextureDimensionFromView } from '../../../../util/texture/base.js';
import { CompatibilityTest } from '../../../compatibility_test.js';
Expand Down Expand Up @@ -121,27 +122,19 @@ g.test('format_reinterpretation')
)
.params(u =>
u //
.combine('format', kColorTextureFormats as GPUTextureFormat[])
.filter(
({ format }) =>
!!kTextureFormatInfo[format].baseFormat &&
kTextureFormatInfo[format].baseFormat !== format
)
.combine('format', kDifferentBaseFormatTextureFormats)
)
.beforeAllSubcases(t => {
const info = kTextureFormatInfo[t.params.format];
t.skipIfTextureFormatNotSupportedDeprecated(t.params.format);
t.selectDeviceOrSkipTestCase(info.feature);
})
.fn(t => {
const { format } = t.params;
const info = kTextureFormatInfo[format];
t.skipIfTextureFormatNotSupported(format);
const info = getBlockInfoForTextureFormat(format);
const baseFormat = getBaseFormatForTextureFormat(format);

const formatPairs = [
{ format, viewFormats: [info.baseFormat!] },
{ format: info.baseFormat!, viewFormats: [format] },
{ format, viewFormats: [format, info.baseFormat!] },
{ format: info.baseFormat!, viewFormats: [format, info.baseFormat!] },
{ format, viewFormats: [baseFormat] },
{ format: baseFormat, viewFormats: [format] },
{ format, viewFormats: [format, baseFormat] },
{ format: baseFormat, viewFormats: [format, baseFormat] },
];
for (const { format, viewFormats } of formatPairs) {
t.expectGPUErrorInCompatibilityMode(
Expand Down
4 changes: 2 additions & 2 deletions src/webgpu/compat/compatibility_test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ValidationTest } from '../api/validation/validation_test.js';
import { AllFeaturesMaxLimitsValidationTest } from '../api/validation/validation_test.js';

export class CompatibilityTest extends ValidationTest {
export class CompatibilityTest extends AllFeaturesMaxLimitsValidationTest {
override async init() {
await super.init();
}
Expand Down
23 changes: 21 additions & 2 deletions src/webgpu/format_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,18 @@ export const kPossibleStorageTextureFormats = [
'bgra8unorm',
] as const;

// Texture formats that may possibly be multisampled.
// Some may require certain features to be enabled.
export const kPossibleMultisampledTextureFormats = [
...kAllTextureFormats.filter(f => kTextureFormatInfo[f].multisample),
'rg11b10ufloat',
] as const;

// Texture formats that have a different base format. This is effectively all -srgb formats.
export const kDifferentBaseFormatTextureFormats = kAllTextureFormats.filter(
f => kTextureFormatInfo[f].baseFormat && kTextureFormatInfo[f].baseFormat !== f
);

/** Valid GPUTextureFormats for `copyExternalImageToTexture`, by spec. */
export const kValidTextureFormatsForCopyE2T = [
'r8unorm',
Expand Down Expand Up @@ -1790,6 +1802,7 @@ export function textureFormatsAreViewCompatible(

/**
* Gets the block width, height, and bytes per block for a color texture format.
* This is for color textures only. For all texture formats @see {@link getBlockInfoForTextureFormat}
*/
export function getBlockInfoForColorTextureFormat(format: ColorTextureFormat) {
const info = kTextureFormatInfo[format];
Expand All @@ -1803,6 +1816,7 @@ export function getBlockInfoForColorTextureFormat(format: ColorTextureFormat) {
/**
* Gets the block width, height, and bytes per block for a color texture format.
* Note that bytesPerBlock will be undefined if format's size is undefined.
* If you are only using color formats, @see {@link getBlockInfoForColorTextureFormat}
*/
export function getBlockInfoForTextureFormat(format: GPUTextureFormat) {
const info = kTextureFormatInfo[format];
Expand All @@ -1816,8 +1830,10 @@ export function getBlockInfoForTextureFormat(format: GPUTextureFormat) {
/**
* Gets the baseFormat for a texture format.
*/
export function getBaseFormatForTextureFormat(format: GPUTextureFormat) {
return kTextureFormatInfo[format].baseFormat;
export function getBaseFormatForTextureFormat(
format: (typeof kDifferentBaseFormatTextureFormats)[number]
): GPUTextureFormat {
return kTextureFormatInfo[format].baseFormat!;
}

/**
Expand Down Expand Up @@ -2043,6 +2059,9 @@ export function isTextureFormatResolvable(device: GPUDevice, format: GPUTextureF
return !!info.colorRender?.resolve;
}

// MAINTENANCE_TODD: See if we can remove this. This doesn't seem useful since
// formats are not on/off by feature. Some are on but a feature allows them to be
// used in more cases, like going from un-renderable to renderable, etc...
export const kFeaturesForFormats = getFeaturesForFormats(kAllTextureFormats);

/**
Expand Down
13 changes: 12 additions & 1 deletion src/webgpu/gpu_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,15 @@ export class GPUTestBase extends Fixture<GPUTestSubcaseBatchState> {
}
}

skipIfTextureFormatNotMultisampled(...formats: (GPUTextureFormat | undefined)[]) {
for (const format of formats) {
if (format === undefined) continue;
if (!isTextureFormatMultisampled(this.device, format)) {
this.skip(`texture format '${format}' is not supported to be multisampled`);
}
}
}

skipIfTextureFormatDoesNotSupportUsage(
usage: GPUTextureUsageFlags,
...formats: (GPUTextureFormat | undefined)[]
Expand Down Expand Up @@ -1484,7 +1493,9 @@ function applyLimitsToDescriptor(
}

function getAdapterFeaturesAsDeviceRequiredFeatures(adapter: GPUAdapter): Iterable<GPUFeatureName> {
return adapter.features as Iterable<GPUFeatureName>;
return [...adapter.features].filter(
f => f !== 'core-features-and-limits'
) as Iterable<GPUFeatureName>;
}

function applyFeaturesToDescriptor(
Expand Down

0 comments on commit a6e2c34

Please sign in to comment.