Skip to content

Commit

Permalink
Test fragment_input @Builtin(sample_mask)
Browse files Browse the repository at this point in the history
  • Loading branch information
greggman committed Feb 14, 2024
1 parent 559c806 commit 169db8e
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,7 @@
"webgpu:shader,execution,shader_io,fragment_builtins:inputs,interStage,centroid:*": { "subcaseMS": 1.001 },
"webgpu:shader,execution,shader_io,fragment_builtins:inputs,position:*": { "subcaseMS": 1.001 },
"webgpu:shader,execution,shader_io,fragment_builtins:inputs,sample_index:*": { "subcaseMS": 1.001 },
"webgpu:shader,execution,shader_io,fragment_builtins:inputs,sample_mask:*": { "subcaseMS": 1.001 },
"webgpu:shader,execution,shader_io,shared_structs:shared_between_stages:*": { "subcaseMS": 9.601 },
"webgpu:shader,execution,shader_io,shared_structs:shared_with_buffer:*": { "subcaseMS": 20.701 },
"webgpu:shader,execution,shader_io,shared_structs:shared_with_non_entry_point_function:*": { "subcaseMS": 6.801 },
Expand Down
128 changes: 128 additions & 0 deletions src/webgpu/shader/execution/shader_io/fragment_builtins.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ type FragData = {
ndcPoints: readonly number[][];
windowPoints: readonly number[][];
sampleIndex: number;
sampleMask: number;
frontFacing: boolean;
};

Expand Down Expand Up @@ -342,6 +343,22 @@ function generateFragmentInputs({

for (let y = 0; y < height; ++y) {
for (let x = 0; x < width; ++x) {
let sampleMask = 0;
for (let sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) {
const localSampleMask = 1 << sampleIndex;
const multisampleOffset = fragmentOffsets[sampleIndex];
const sampleFragmentPoint = [x + multisampleOffset[0], y + multisampleOffset[1]];
const sampleBarycentricCoords = calcBarycentricCoordinates(
windowPoints2D,
sampleFragmentPoint
);

const inside = isInsideTriangle(sampleBarycentricCoords);
if (inside) {
sampleMask |= localSampleMask;
}
}

for (let sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) {
const fragmentPoint = [x + 0.5, y + 0.5];
const multisampleOffset = fragmentOffsets[sampleIndex];
Expand All @@ -366,6 +383,7 @@ function generateFragmentInputs({
ndcPoints,
windowPoints,
sampleIndex,
sampleMask,
frontFacing,
});

Expand Down Expand Up @@ -474,6 +492,13 @@ function computeFragmentFrontFacing({ frontFacing }: FragData) {
return [frontFacing ? 1 : 0, 0, 0, 0];
}

/**
* Computes 'builtin(sample_mask)'
*/
function computeSampleMask({ sampleMask }: FragData) {
return [sampleMask, 0, 0, 0];
}

/**
* Renders float32 fragment shader inputs values to 4 rgba8unorm textures that
* can be multisampled textures. It stores each of the channels, r, g, b, a of
Expand Down Expand Up @@ -1210,3 +1235,106 @@ g.test('inputs,front_facing')
})
);
});

g.test('inputs,sample_mask')
.desc(
`
Test fragment shader builtin(sample_mask) values.
Draws a quad from 1 triangle that entirely cover clip space. (see diagram below in code)
It covers some samples and not others. Check the mask matches what's expected.
`
)
.params(u =>
u //
.combine('nearFar', [[0, 1] as const, [0.25, 0.75] as const] as const)
.combine('sampleCount', [1, 4] as const)
.combine('interpolation', [
{ type: 'perspective', sampling: 'center' },
{ type: 'perspective', sampling: 'centroid' },
{ type: 'perspective', sampling: 'sample' },
{ type: 'linear', sampling: 'center' },
{ type: 'linear', sampling: 'centroid' },
{ type: 'linear', sampling: 'sample' },
{ type: 'flat' },
] as const)
.beginSubcases()
.combine('x', [1, 2, 4, 16])
.combine('y', [1, 2, 4, 16])
)
.beforeAllSubcases(t => {
const {
interpolation: { type, sampling },
} = t.params;
t.skipIfInterpolationTypeOrSamplingNotSupported({ type, sampling });
})
.fn(async t => {
const {
x,
y,
nearFar,
sampleCount,
interpolation: { type, sampling },
} = t.params;
//
// We're drawing 1 triangles starting at y = -2 to y = +2
//
// -1 0 1
// +===+===+ 2
// |\..|...|
// +---+---+ 1 <---
// | \|...| |
// +---+---+ 0 | viewport
// | |\..| |
// +---+---+ -1 <---
// | | \|
// +===+===+ -2

// prettier-ignore
const clipSpacePoints = [
[ x, -y, 0, 1],
[-x, y, 0, 1],
[ x, y, 0, 1],
];

const interStagePoints = [
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24],
];

const width = 4;
const height = 4;
const actual = await renderFragmentShaderInputsTo4TexturesAndReadbackValues(t, {
interpolationType: type,
interpolationSampling: sampling,
sampleCount,
width,
height,
nearFar,
clipSpacePoints,
interStagePoints,
fragInCode: '@builtin(sample_mask) sample_mask: u32,',
outputCode: 'vec4f(f32(fin.sample_mask), 0, 0, 0)',
});

const expected = generateFragmentInputs({
width,
height,
nearFar,
sampleCount,
clipSpacePoints,
interpolateFn: computeSampleMask,
});

t.expectOK(
checkSampleRectsApproximatelyEqual({
width,
height,
sampleCount,
actual,
expected,
maxDiffULPsForFloatFormat: 0,
})
);
});

0 comments on commit 169db8e

Please sign in to comment.