Skip to content

Commit

Permalink
Merge branch 'main' into attachment_compatibility-too-verbose
Browse files Browse the repository at this point in the history
  • Loading branch information
kainino0x authored Dec 11, 2024
2 parents 510829d + 1afb7eb commit c68e2ac
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 54 deletions.
4 changes: 2 additions & 2 deletions src/webgpu/api/operation/rendering/draw.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import {
TypedArrayBufferView,
TypedArrayBufferViewConstructor,
} from '../../../../common/util/util.js';
import { MaxLimitsTest, TextureTestMixin } from '../../../gpu_test.js';
import { GPUTest, MaxLimitsTestMixin, TextureTestMixin } from '../../../gpu_test.js';
import { PerPixelComparison } from '../../../util/texture/texture_ok.js';

class DrawTest extends TextureTestMixin(MaxLimitsTest) {
class DrawTest extends TextureTestMixin(MaxLimitsTestMixin(GPUTest)) {
checkTriangleDraw(opts: {
firstIndex: number | undefined;
count: number;
Expand Down
4 changes: 2 additions & 2 deletions src/webgpu/api/operation/sampling/sampler_texture.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Tests samplers with textures.

import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { assert, range } from '../../../../common/util/util.js';
import { MaxLimitsTest, TextureTestMixin } from '../../../gpu_test.js';
import { GPUTest, MaxLimitsTestMixin, TextureTestMixin } from '../../../gpu_test.js';
import { TexelView } from '../../../util/texture/texel_view.js';

export const g = makeTestGroup(TextureTestMixin(MaxLimitsTest));
export const g = makeTestGroup(TextureTestMixin(MaxLimitsTestMixin(GPUTest)));

g.test('sample_texture_combos')
.desc(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const description = `
Tests for resource compatibilty between pipeline layout and shader modules
Tests for resource compatibility between pipeline layout and shader modules
`;

import { makeTestGroup } from '../../../../common/framework/test_group.js';
Expand Down
29 changes: 20 additions & 9 deletions src/webgpu/gpu_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1333,16 +1333,27 @@ export class MaxLimitsGPUTestSubcaseBatchState extends GPUTestSubcaseBatchState
}
}

/**
* A Test that requests all the max limits from the adapter on the device.
*/
export class MaxLimitsTest extends GPUTest {
public static override MakeSharedState(
recorder: TestCaseRecorder,
params: TestParams
): GPUTestSubcaseBatchState {
return new MaxLimitsGPUTestSubcaseBatchState(recorder, params);
export type MaxLimitsTestMixinType = {
// placeholder. Change to an interface if we need MaxLimits specific methods.
};

export function MaxLimitsTestMixin<F extends FixtureClass<GPUTestBase>>(
Base: F
): FixtureClassWithMixin<F, MaxLimitsTestMixinType> {
class MaxLimitsImpl
extends (Base as FixtureClassInterface<GPUTestBase>)
implements MaxLimitsTestMixinType
{
//
public static override MakeSharedState(
recorder: TestCaseRecorder,
params: TestParams
): GPUTestSubcaseBatchState {
return new MaxLimitsGPUTestSubcaseBatchState(recorder, params);
}
}

return MaxLimitsImpl as unknown as FixtureClassWithMixin<F, MaxLimitsTestMixinType>;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const g = makeTestGroup(GPUTest);
function validForConst(c: Case): boolean {
const low = (c.input as Value[])[0] as ScalarValue;
const high = (c.input as Value[])[1] as ScalarValue;
return low.value < high.value;
return low.value !== high.value;
}

g.test('abstract_float')
Expand Down
123 changes: 89 additions & 34 deletions src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3430,25 +3430,72 @@ async function identifySamplePoints<T extends Dimensionality>(
// example when blockWidth = 2, blockHeight = 2
//
// 0 1 2 3
// +===+===+===+===+
// 0 # a | # | #
// +---+---+---+---+
// 1 # | # | #
// +===+===+===+===+
// 2 # | # | #
// +---+---+---+---+
// 3 # | # | b #
// +===+===+===+===+
// ╔═══╤═══╦═══╤═══╗
// 0 ║ a │ ║ │ ║
// ╟───┼───╫───┼───╢
// 1 ║ │ ║ │ ║
// ╠═══╪═══╬═══╪═══╣
// 2 ║ │ ║ │ ║
// ╟───┼───╫───┼───╢
// 3 ║ │ ║ │ b ║
// ╚═══╧═══╩═══╧═══╝

/* prettier-ignore */
const blockParts = {
top: { left: '╔', fill: '═══', right: '╗', block: '╦', texel: '╤' },
mid: { left: '╠', fill: '═══', right: '╣', block: '╬', texel: '╪' },
bot: { left: '╚', fill: '═══', right: '╝', block: '╩', texel: '╧' },
texelMid: { left: '╟', fill: '───', right: '╢', block: '╫', texel: '┼' },
value: { left: '║', fill: ' ', right: '║', block: '║', texel: '│' },
} as const;
/* prettier-ignore */
const nonBlockParts = {
top: { left: '┌', fill: '───', right: '┐', block: '┬', texel: '┬' },
mid: { left: '├', fill: '───', right: '┤', block: '┼', texel: '┼' },
bot: { left: '└', fill: '───', right: '┘', block: '┴', texel: '┴' },
texelMid: { left: '├', fill: '───', right: '┤', block: '┼', texel: '┼' },
value: { left: '│', fill: ' ', right: '│', block: '│', texel: '│' },
} as const;

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('');
const joinFn = (arr: string[], fn: (i: number) => string) => {
const joins = range(arr.length - 1, fn);
return arr.map((s, i) => `${s}${joins[i] ?? ''}`).join('');
};
const parts = Math.max(blockWidth, blockHeight) > 1 ? blockParts : nonBlockParts;
/**
* Makes a row that's [left, fill, texel, fill, block, fill, texel, fill, right]
* except if `contents` is supplied then it would be
* [left, contents[0], texel, contents[1], block, contents[2], texel, contents[3], right]
*/
const makeRow = (
blockPaddedWidth: number,
width: number,
{
left,
fill,
right,
block,
texel,
}: {
left: string;
fill: string;
right: string;
block: string;
texel: string;
},
contents?: string[]
) => {
return `${left}${joinFn(contents ?? range(blockPaddedWidth, x => fill), x => {
return (x + 1) % blockWidth === 0 ? block : texel;
})}${right}`;
};

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

const blockPaddedHeight = align(height, blockHeight);
const blockPaddedWidth = align(width, blockWidth);
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().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)} ${colChar}`;
orderedTexelIndices.push(texelIdx);
} else {
line += ` ${colChar}`;
}
}
lines.push(line);
}
if (y < height - 1) {
lines.push(
` +${rangeCat(width, () => ((y + 1) % blockHeight === 0 ? blockHCell : '---+'))}`
);
}
lines.push(` ${makeRow(blockPaddedWidth, width, parts.top)}`);
for (let y = 0; y < blockPaddedHeight; y++) {
lines.push(
`${y.toString().padStart(2)} ${makeRow(
blockPaddedWidth,
width,
parts.value,
range(blockPaddedWidth, x => {
const texelIdx = x + y * texelsPerRow;
const weight = layerEntries.get(texelIdx);
const outside = y >= height || x >= width;
if (outside || weight === undefined) {
return outside ? '░░░' : ' ';
} else {
const id = letter(idCount + orderedTexelIndices.length);
orderedTexelIndices.push(texelIdx);
return ` ${id} `;
}
})
)}`
);
// It's either a block row, a texel row, or the last row.
const end = y < blockPaddedHeight - 1;
const lineParts = end
? (y + 1) % blockHeight === 0
? parts.mid
: parts.texelMid
: parts.bot;
lines.push(` ${makeRow(blockPaddedWidth, width, lineParts)}`);
}
lines.push(` +${range(width, () => blockHCell).join('')}`);

const pad2 = (n: number) => n.toString().padStart(2);
const pad3 = (n: number) => n.toString().padStart(3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ Validates that constant evaluation and override evaluation of ${builtin}() rejec
.fn(t => {
const type = kValuesTypes[t.params.type];

// We expect to fail if low >= high.
const expectedResult = t.params.value1 < t.params.value2;
// We expect to fail if low == high.
const expectedResult = t.params.value1 !== t.params.value2;

validateConstOrOverrideBuiltinEval(
t,
Expand All @@ -66,7 +66,7 @@ Validates that constant evaluation and override evaluation of ${builtin}() rejec
const kStages = [...kConstantAndOverrideStages, 'runtime'] as const;

g.test('partial_eval_errors')
.desc('Validates that low < high')
.desc('Validates that low != high')
.params(u =>
u
.combine('lowStage', kStages)
Expand Down Expand Up @@ -127,7 +127,7 @@ fn foo() {
let tmp = smoothstep(${lowArg}, ${highArg}, x);
}`;

const error = t.params.low >= t.params.high;
const error = t.params.low === t.params.high;
const shader_error =
error && t.params.lowStage === 'constant' && t.params.highStage === 'constant';
const pipeline_error =
Expand Down Expand Up @@ -349,7 +349,7 @@ g.test('early_eval_errors')
validateConstOrOverrideBuiltinEval(
t,
builtin,
/* expectedResult */ t.params.low < t.params.high,
/* expectedResult */ t.params.low !== t.params.high,
[f32(t.params.low), f32(t.params.high), f32(0)],
t.params.stage
);
Expand Down

0 comments on commit c68e2ac

Please sign in to comment.