Skip to content

Commit

Permalink
Add warning in checkCallResults for compressed textures (#4053)
Browse files Browse the repository at this point in the history
We sample a compressed texture on the GPU and compare that
to expected. If they don't match we try to identify which texels
were sampled. This is done by doing a binary search, creating
textures with some pixels white and some black and then sampling
the texture to see if those white pixels contributed to the
sample values.

We can't do this for compressed textures because we can not easily
create a compressed texture with white and black pixels exactly
where we want them to appear.

So, for compressed textures we just use rgba8unorm when identifying
sample points.

That can be useful to help find major bugs either in the CTS itself
or in the GPU that are true for all texture formats. Unfortunately,
if the bug is specificially with compressed textures this doesn't
help.

So, print out a warning that the sample points might not match.

Also, change the diagram to show blocks. Eexample when blockWidth = 2, blockHeight = 2

```
   +===+===+===+===+
   # a |   #   |   #
   +---+---+---+---+
   #   |   #   |   #
   +===+===+===+===+
   #   |   #   |   #
   +---+---+---+---+
   #   |   #   | b #
   +===+===+===+===+
```
  • Loading branch information
greggman authored Nov 21, 2024
1 parent bc88622 commit 91a2cfe
Showing 1 changed file with 45 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2582,6 +2582,21 @@ export async function checkCallResults<T extends Dimensionality>(

const callForSamplePoints = checkInfo.calls[callIdx];

// We're going to create textures with black and white texels
// but if it's a compressed texture we use an encodable texture.
// It's not perfect but we already know it failed. We're just hoping
// to get sample points.
const useTexelFormatForGPUTexture = isCompressedTextureFormat(texture.descriptor.format);

if (useTexelFormatForGPUTexture) {
errs.push(`
### WARNING: sample points are derived from un-compressed textures and may not match the
actual GPU results of sampling a compressed texture. The test itself failed at this point
(see expected: and got: above). We're only trying to determine what the GPU sampled, but
we can not do that easily with compressed textures. ###
`);
}

const expectedSamplePoints = [
'expected:',
...(await identifySamplePoints(
Expand Down Expand Up @@ -2616,12 +2631,8 @@ export async function checkCallResults<T extends Dimensionality>(
call,
gpuTexels,
async (texels: TexelView[]) => {
// We're trying to create a texture with black and white texels
// but if it's a compressed texture we use an encodable texture.
// It's not perfect but we already know it failed. We're just hoping
// to get sample points.
const descriptor = { ...texture.descriptor };
if (isCompressedTextureFormat(descriptor.format)) {
if (useTexelFormatForGPUTexture) {
descriptor.format = texels[0].format;
}
const gpuTexture = createTextureFromTexelViewsLocal(t, texels, descriptor);
Expand Down Expand Up @@ -3401,19 +3412,29 @@ async function identifySamplePoints<T extends Dimensionality>(
layerEntries.set(xyId, weight);
}

// +---+---+---+---+
// | a | | | |
// +---+---+---+---+
// | | | | |
// +---+---+---+---+
// | | | | |
// +---+---+---+---+
// | | | | b |
// +---+---+---+---+
// example when blockWidth = 2, blockHeight = 2
//
// 0 1 2 3
// +===+===+===+===+
// 0 # a | # | #
// +---+---+---+---+
// 1 # | # | #
// +===+===+===+===+
// 2 # | # | #
// +---+---+---+---+
// 3 # | # | b #
// +===+===+===+===+

const lines: string[] = [];
const letter = (idx: number) => String.fromCodePoint(idx < 30 ? 97 + idx : idx + 9600 - 30); // 97: 'a'
let idCount = 0;

const { blockWidth, blockHeight } = kTextureFormatInfo[texture.descriptor.format];
const [blockHChar, blockVChar] = Math.max(blockWidth, blockHeight) > 1 ? ['=', '#'] : ['-', '|'];
const blockHCell = '+'.padStart(4, blockHChar); // generates ---+ or ===+
// range + concatenate results.
const rangeCat = <T>(num: number, fn: (i: number) => T) => range(num, fn).join('');

for (let mipLevel = 0; mipLevel < mipLevelCount; ++mipLevel) {
const level = levels[mipLevel];
if (!level) {
Expand Down Expand Up @@ -3442,50 +3463,31 @@ async function identifySamplePoints<T extends Dimensionality>(
continue;
}

{
let line = ' ';
for (let x = 0; x < width; x++) {
line += ` ${x.toString().padEnd(2)}`;
}
lines.push(line);
}
{
let line = ' +';
for (let x = 0; x < width; x++) {
line += x === width - 1 ? '---+' : '---+';
}
lines.push(line);
}
lines.push(` ${rangeCat(width, x => ` ${x.toString().padEnd(2)}`)}`);
lines.push(` +${rangeCat(width, () => blockHCell)}`);
for (let y = 0; y < height; y++) {
{
let line = `${y.toString().padEnd(2)}|`;
let line = `${y.toString().padStart(2)} ${blockVChar}`;
for (let x = 0; x < width; x++) {
const colChar = (x + 1) % blockWidth === 0 ? blockVChar : '|';
const texelIdx = x + y * texelsPerRow;
const weight = layerEntries.get(texelIdx);
if (weight !== undefined) {
line += ` ${letter(idCount + orderedTexelIndices.length)} |`;
line += ` ${letter(idCount + orderedTexelIndices.length)} ${colChar}`;
orderedTexelIndices.push(texelIdx);
} else {
line += ' |';
line += ` ${colChar}`;
}
}
lines.push(line);
}
if (y < height - 1) {
let line = ' +';
for (let x = 0; x < width; x++) {
line += x === width - 1 ? '---+' : '---+';
}
lines.push(line);
}
}
{
let line = ' +';
for (let x = 0; x < width; x++) {
line += x === width - 1 ? '---+' : '---+';
lines.push(
` +${rangeCat(width, () => ((y + 1) % blockHeight === 0 ? blockHCell : '---+'))}`
);
}
lines.push(line);
}
lines.push(` +${range(width, () => blockHCell).join('')}`);

const pad2 = (n: number) => n.toString().padStart(2);
const pad3 = (n: number) => n.toString().padStart(3);
Expand Down

0 comments on commit 91a2cfe

Please sign in to comment.