Skip to content

Commit

Permalink
Fix readTextureToTextureViews for multisampled textures (#4049)
Browse files Browse the repository at this point in the history
* Fix readTextureToTextureViews for multisampled textures

I'm not sure when this bug was introduced. These tests (textureLoad:multisampled) used
to pass. Fixed the bug and added a test to hopefully find it
quicker if it breaks in the future.

Also added a test for createTextureWithRandomDataAndGetTexels
with a generator. This was fixed in a previous PR without a
a specific test as the fact that it failed other tests showed
it needed fixing but I decided it's probably best to keep
these tests too.

* Update src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts

Co-authored-by: Kai Ninomiya <[email protected]>
  • Loading branch information
greggman and kainino0x authored Nov 19, 2024
1 parent 990c238 commit 003cb57
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Tests for texture_utils.ts

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import { assert } from '../../../../../../common/util/util.js';
import { isMultisampledTextureFormat, kDepthStencilFormats } from '../../../../../format_info.js';
import { GPUTest } from '../../../../../gpu_test.js';
import { getTextureDimensionFromView, virtualMipSize } from '../../../../../util/texture/base.js';
import {
Expand All @@ -16,6 +17,7 @@ import {
chooseTextureSize,
createTextureWithRandomDataAndGetTexels,
isSupportedViewFormatCombo,
makeRandomDepthComparisonTexelGenerator,
readTextureToTexelViews,
texelsApproximatelyEqual,
} from './texture_utils.js';
Expand All @@ -26,6 +28,41 @@ function texelFormat(texel: Readonly<PerTexelComponent<number>>, rep: TexelRepre
return rep.componentOrder.map(component => `${component}: ${texel[component]}`).join(', ');
}

g.test('createTextureWithRandomDataAndGetTexels_with_generator')
.desc(
`
Test createTextureWithRandomDataAndGetTexels with a generator. Generators
are only used with textureXXXCompare builtins as we need specific random
values to test these builtins with a depth reference value.
`
)
.params(u =>
u
.combine('format', kDepthStencilFormats)
.combine('viewDimension', ['2d', '2d-array', 'cube', 'cube-array'] as const)
.filter(t => isSupportedViewFormatCombo(t.format, t.viewDimension))
)
.beforeAllSubcases(t => {
t.skipIfTextureViewDimensionNotSupported(t.params.viewDimension);
t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format);
})
.fn(async t => {
const { format, viewDimension } = t.params;
const size = chooseTextureSize({ minSize: 8, minBlocks: 4, format, viewDimension });
const descriptor: GPUTextureDescriptor = {
format,
dimension: getTextureDimensionFromView(viewDimension),
size,
mipLevelCount: 3,
usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
...(t.isCompatibility && { textureBindingViewDimension: viewDimension }),
};
await createTextureWithRandomDataAndGetTexels(t, descriptor, {
generator: makeRandomDepthComparisonTexelGenerator(descriptor, 'equal'),
});
// We don't expect any particular results. We just expect no validation errors.
});

g.test('readTextureToTexelViews')
.desc('test readTextureToTexelViews for various formats and dimensions')
.params(u =>
Expand All @@ -44,19 +81,26 @@ g.test('readTextureToTexelViews')
] as const)
.combine('viewDimension', ['1d', '2d', '2d-array', '3d', 'cube', 'cube-array'] as const)
.filter(t => isSupportedViewFormatCombo(t.srcFormat, t.viewDimension))
.combine('sampleCount', [1, 4] as const)
.unless(
t =>
t.sampleCount > 1 &&
(!isMultisampledTextureFormat(t.srcFormat) || t.viewDimension !== '2d')
)
)
.beforeAllSubcases(t => {
t.skipIfTextureViewDimensionNotSupported(t.params.viewDimension);
})
.fn(async t => {
const { srcFormat, texelViewFormat, viewDimension } = t.params;
const { srcFormat, texelViewFormat, viewDimension, sampleCount } = t.params;
const size = chooseTextureSize({ minSize: 8, minBlocks: 4, format: srcFormat, viewDimension });
const descriptor: GPUTextureDescriptor = {
format: srcFormat,
dimension: getTextureDimensionFromView(viewDimension),
size,
mipLevelCount: viewDimension === '1d' ? 1 : 3,
mipLevelCount: viewDimension === '1d' || sampleCount > 1 ? 1 : 3,
usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
sampleCount,
...(t.isCompatibility && { textureBindingViewDimension: viewDimension }),
};
const { texels: expectedTexelViews, texture } = await createTextureWithRandomDataAndGetTexels(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3031,11 +3031,14 @@ export async function readTextureToTexelViews(
}
`,
});
const sampleType = isDepthTextureFormat(texture.format)
? 'unfilterable-float'
: isStencilTextureFormat(texture.format)
const info = kTextureFormatInfo[texture.format];
const sampleType = info.depth
? 'unfilterable-float' // depth only supports unfilterable-float if not a comparison.
: info.stencil
? 'uint'
: kTextureFormatInfo[texture.format].color?.type ?? 'unfilterable-float';
: info.color.type === 'float'
? 'unfilterable-float'
: info.color.type;
const bindGroupLayout = device.createBindGroupLayout({
entries: [
{
Expand All @@ -3051,6 +3054,7 @@ export async function readTextureToTexelViews(
texture: {
sampleType,
viewDimension,
multisampled: texture.sampleCount > 1,
},
},
{
Expand Down Expand Up @@ -3169,7 +3173,7 @@ function createTextureFromTexelViewsLocal(
): GPUTexture {
const modifiedDescriptor = { ...desc };
// If it's a depth or stencil texture we need to render to it to fill it with data.
if (isDepthOrStencilTextureFormat(desc.format)) {
if (isDepthOrStencilTextureFormat(desc.format) || desc.sampleCount! > 1) {
modifiedDescriptor.usage = desc.usage | GPUTextureUsage.RENDER_ATTACHMENT;
}
return createTextureFromTexelViews(t, texelViews, modifiedDescriptor);
Expand Down

0 comments on commit 003cb57

Please sign in to comment.