Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

op: Add 'srcFactor' and 'dstFactor' to the parameters in 'blending,clamping' test #2107

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 97 additions & 5 deletions src/webgpu/api/operation/rendering/color_target_state.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,78 @@ function computeBlendOperation(
}
}

function calculateExpectedClampValue(
srcValue: number,
dstValue: number,
srcFactor: GPUBlendFactor,
dstFactor: GPUBlendFactor
) {
let srcFactorValue;
let dstFactorValue;

switch (srcFactor) {
case 'zero':
srcFactorValue = 0;
break;
// The default constant value is 0. So the src factor value of 'one-minus-constant' should be
// 1 - 0 = 1.
case 'one':
case 'one-minus-constant':
srcFactorValue = 1;
break;
case 'src':
case 'src-alpha':
srcFactorValue = srcValue;
break;
case 'dst':
srcFactorValue = dstValue;
break;
case 'one-minus-dst':
srcFactorValue = 1 - dstValue;
break;
case 'one-minus-src':
srcFactorValue = 1 - srcValue;
break;
case 'constant': // The default constant value is 0.
srcFactorValue = 0;
break;
default:
unreachable();
}

switch (dstFactor) {
case 'zero':
dstFactorValue = 0;
break;
// The default constant value is 0. So the dst factor value of 'one-minus-constant' should be
// 1 - 0 = 1.
case 'one':
case 'one-minus-constant':
dstFactorValue = 1;
break;
case 'src':
case 'src-alpha':
dstFactorValue = srcValue;
break;
case 'dst':
dstFactorValue = dstValue;
break;
case 'one-minus-dst':
dstFactorValue = 1 - dstValue;
break;
case 'one-minus-src':
dstFactorValue = 1 - srcValue;
break;
case 'constant': // The default constant value is 0.
dstFactorValue = 0;
break;
default:
unreachable();
}

return srcValue * srcFactorValue + dstValue * dstFactorValue;
}

g.test('blending,GPUBlendComponent')
.desc(
`Test all combinations of parameters for GPUBlendComponent.
Expand Down Expand Up @@ -791,19 +863,36 @@ g.test('blending,clamping')
Test that clamping occurs at the correct points in the blend process: src value, src factor, dst
factor, and output.
- TODO: Need to test snorm formats.
- TODO: Need to test src value, srcFactor and dstFactor.
`
)
.params(u =>
u //
.combine('format', ['rgba8unorm', 'rg16float'] as const)
.combine('srcFactor', kBlendFactors)
.combine('dstFactor', kBlendFactors)
.filter(t => {
return (
!(
t.srcFactor === 'one-minus-src-alpha' ||
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I applied these factors that include 'alpha', the test failed. Do you know any clue why?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I run this PR without the filter then I hit an unreachable in calculateExpectedClampValue. But fixing that it still fails. At least some of the failures are because we expect the color and alpha channels to always be the same, but that's not always true: https://gpuweb.github.io/gpuweb/#enumdef-gpublendfactor

"src-alpha-saturated" (min(Asrc, 1 - Adst), min(Asrc, 1 - Adst), min(Asrc, 1 - Adst), 1)

Note the last channel has different factors.

The other issue I see is that when the format is rg16float, there is no alpha channel. Therefore dst-alpha won't have the initial value the code expects. I think missing channels default to ,0,0,1 so dst-alpha would be 1 (similar to this), but I'm not 100% sure about that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ,0,0,1. Was confirmed in gpuweb/gpuweb#2025

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other issue I see is that when the format is rg16float, there is no alpha channel. Therefore dst-alpha won't have the initial value the code expects. I think missing channels default to ,0,0,1 so dst-alpha would be 1 (similar to this), but I'm not 100% sure about that.

yes, as you thought, the failures come from rg16float format and src-alpha-saturated factor. It's likely this PR should make the test use RGBA instead of using one value.

t.srcFactor === 'dst-alpha' ||
t.srcFactor === 'one-minus-dst-alpha' ||
t.srcFactor === 'src-alpha-saturated'
) &&
!(
t.dstFactor === 'one-minus-src-alpha' ||
t.dstFactor === 'dst-alpha' ||
t.dstFactor === 'one-minus-dst-alpha' ||
t.dstFactor === 'src-alpha-saturated'
)
);
})
.combine('srcValue', [0.4, 0.6, 0.8, 1.0])
.combine('dstValue', [0.2, 0.4])
)
.fn(async t => {
const { format, srcValue, dstValue } = t.params;
const { format, srcFactor, dstFactor, srcValue, dstValue } = t.params;

const blendComponent = { srcFactor: 'one', dstFactor: 'one', operation: 'add' } as const;
const blendComponent = { srcFactor, dstFactor, operation: 'add' } as const;

const pipeline = t.device.createRenderPipeline({
layout: 'auto',
Expand Down Expand Up @@ -866,10 +955,13 @@ g.test('blending,clamping')
let expValue: number;
switch (format) {
case 'rgba8unorm': // unorm types should clamp if the sum of srcValue and dstValue exceeds 1.
expValue = clamp(srcValue + dstValue, { min: 0, max: 1 });
expValue = clamp(calculateExpectedClampValue(srcValue, dstValue, srcFactor, dstFactor), {
min: 0,
max: 1,
});
break;
case 'rg16float': // float format types doesn't clamp.
expValue = srcValue + dstValue;
expValue = calculateExpectedClampValue(srcValue, dstValue, srcFactor, dstFactor);
break;
}

Expand Down