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

depthCompare is not required for depth attachments if not used #3069

Merged
merged 3 commits into from
Oct 24, 2023
Merged
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,18 @@ g.test('format')

g.test('depthCompare_optional')
.desc(
`The depthCompare in depthStencilState is optional for stencil-only formats but required for formats with a depth.`
`The depthCompare in depthStencilState is optional for stencil-only formats but
required for formats with a depth if depthCompare is not used for anything.`
)
.params(u =>
u
.combine('isAsync', [false, true])
.combine('format', kDepthStencilFormats)
.beginSubcases()
.combine('depthCompare', ['always', undefined] as const)
.combine('depthWriteEnabled', [false, true, undefined] as const)
.combine('stencilFrontDepthFailOp', ['keep', 'zero'] as const)
.combine('stencilBackDepthFailOp', ['keep', 'zero'] as const)
)
.beforeAllSubcases(t => {
const { format } = t.params;
Expand All @@ -50,13 +54,44 @@ g.test('depthCompare_optional')
t.selectDeviceOrSkipTestCase(info.feature);
})
.fn(t => {
const { isAsync, format, depthCompare } = t.params;
const {
isAsync,
format,
depthCompare,
depthWriteEnabled,
stencilFrontDepthFailOp,
stencilBackDepthFailOp,
} = t.params;
const info = kTextureFormatInfo[format];
const descriptor = t.getDescriptor({
depthStencil: { format, depthCompare, depthWriteEnabled: false },
depthStencil: {
format,
depthCompare,
depthWriteEnabled,
stencilFront: { depthFailOp: stencilFrontDepthFailOp },
stencilBack: { depthFailOp: stencilBackDepthFailOp },
},
});

t.doCreateRenderPipelineTest(isAsync, !(info.depth && depthCompare === undefined), descriptor);
const areDepthFailOpKeep =
stencilFrontDepthFailOp === 'keep' && stencilBackDepthFailOp === 'keep';

let success = false;
if (!info.depth) {
// depthCompare is optional for stencil-only formats.
if (!depthWriteEnabled) success = true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: This confused me a little because depthWriteEnabled=true is not even allowed with stencil-only formats. Then I realized this check is here because of that. Digging further it's quite hard to see how all of the validation rules from the spec appear here. [continued in other comment]

} else {
// depthCompare is optional for formats with a depth if it's not used for anything.
if (depthWriteEnabled === false && areDepthFailOpKeep) success = true;
if (depthCompare) {
// validation will succeed normally for formats with depth aspect.
if (depthWriteEnabled && areDepthFailOpKeep) success = true;
// validation will succeed as well for formats with stencil and depth aspect.
if (info.stencil && depthWriteEnabled !== undefined) success = true;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Apologies for another big change. It is much easier to think about written this way, but I still find it quite hard to pick apart where the different rules from the spec appear here. (I probably shouldn't have suggested inverting the usual pattern, as I realize there's a good reason we usually have let success = true; if (...) success = false.)

I think the most readable form would stick close to the spec:

Suggested change
const areDepthFailOpKeep =
stencilFrontDepthFailOp === 'keep' && stencilBackDepthFailOp === 'keep';
let success = false;
if (!info.depth) {
// depthCompare is optional for stencil-only formats.
if (!depthWriteEnabled) success = true;
} else {
// depthCompare is optional for formats with a depth if it's not used for anything.
if (depthWriteEnabled === false && areDepthFailOpKeep) success = true;
if (depthCompare) {
// validation will succeed normally for formats with depth aspect.
if (depthWriteEnabled && areDepthFailOpKeep) success = true;
// validation will succeed as well for formats with stencil and depth aspect.
if (info.stencil && depthWriteEnabled !== undefined) success = true;
}
}
const depthFailOpsAreKeep =
stencilFrontDepthFailOp === 'keep' && stencilBackDepthFailOp === 'keep';
const stencilStateIsDefault = depthFailOpsAreKeep;
let success = true;
if (depthWriteEnabled || depthCompare !== 'always') {
if (!info.depth) success = false;
}
if (!stencilStateIsDefault) {
if (!info.stencil) success = false;
}
if (info.depth) {
if (depthWriteEnabled === undefined) success = false;
if (depthWriteEnabled || !depthFailOpsAreKeep) {
if (depthCompare === undefined) success = false;
}
}

I would need you to test this to make sure it's right, but it follows the spec very closely so I hope it is.

Copy link
Collaborator Author

@beaufortfrancois beaufortfrancois Oct 19, 2023

Choose a reason for hiding this comment

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

@kainino0x Thanks for the detailed answer. I followed your last suggestion with one nit:

-    if (depthWriteEnabled || depthCompare !== 'always') {
+    if (depthWriteEnabled || (depthCompare && depthCompare !== 'always')) {

I'm updating spec to make it clear as well. See gpuweb/gpuweb#4345

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@kainino0x (gentle ping)


t.doCreateRenderPipelineTest(isAsync, success, descriptor);
});

g.test('depthWriteEnabled_optional')
Expand Down