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

[wiki]Extraneous stage and access flags in depth clear\reuse example #2055

Open
krOoze opened this issue Feb 12, 2023 · 8 comments
Open

[wiki]Extraneous stage and access flags in depth clear\reuse example #2055

krOoze opened this issue Feb 12, 2023 · 8 comments
Assignees

Comments

@krOoze
Copy link
Contributor

krOoze commented Feb 12, 2023

There are extraneous stage and access bits in the following depth clear\reuse example

https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples#first-render-pass-writes-to-a-depth-attachment-second-render-pass-re-uses-the-same-depth-attachment

VkSubpassDependency dependency = {
   .srcSubpass = VK_SUBPASS_EXTERNAL,
   .dstSubpass = 0,
   .srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
                   VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // Both stages might have access the depth-buffer, so need both in src/dstStageMask
   .dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
                   VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
   .srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
   .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
   .dependencyFlags = 0}; 

Load op VK_ATTACHMENT_LOAD_OP_CLEAR for depth are performed in VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT with VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT. Therefore dst of VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT should be redundant.

@HansKristian-Work
Copy link
Contributor

Seems like the spec changed at some point here, so to synchronize the loadOp = CLEAR it makes sense to only have EARLY_FRAGMENT_TESTS. But fragments later in the render pass might end up running in EARLY or LATE and it may read or write, so I think we technically need to be conservative here.

@krOoze
Copy link
Contributor Author

krOoze commented Feb 18, 2023

@HansKristian-Work Not sure that is healthy to be "conservative" with something that is supposed to be formally described exactly. If that is so, there should be a red triangle with three exclamation marks with a note explaining why it is done in opposition of what the spec implies.

Even so, the CLEAR modifies the memory, therefore there is no producer-consumer relationship between the previous work and the "fragments later in the render pass", therefore the extraneous access mask would not even make much sense semantically. All needs to depend directly on the CLEAR load-op and nothing else.

@TomOlson
Copy link

The WG discussed on 2023-02-22. @krOoze's analysis is correct, but we're going to leave the example code as is. We expect that many devs will copy-paste the code into an app and then replace/follow the CLEAR with other commands, which is the case @HansKristian-Work was thinking about. We want the example code to be robust to that.

@krOoze
Copy link
Contributor Author

krOoze commented Feb 23, 2023

@TomOlson Following the CLEAR with other commands does not change the situation at all, as elaborated in the previous comment.

Replacing the CLEAR does not change the pipeline stage. Load op is always (only) VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, and store op is always (only) VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT. The comment in the code is a lie.

Only time this might make sense is dependencies between subpasses.

@Tobski
Copy link
Contributor

Tobski commented Mar 6, 2023

Ok, so this section of the spec got tightened up a lot since the examples were written, and I'm inclined to agree with @krOoze here. The only time being conservative would make sense is if you used the NONE ops (i.e. there is no load/store), but those are primarily intended for cases when you aren't going to access the data, so you wouldn't need a barrier 99% of the time anyway.

So I am going to update the example just so it's clear that yea, you can rely on the subset of pipeline stages.

@Tobski
Copy link
Contributor

Tobski commented Mar 6, 2023

Fixed per above. Assuming that satisfies you @krOoze I'm closing this issue, feel free to reopen if there's any further issues...

@Tobski Tobski closed this as completed Mar 6, 2023
@krOoze
Copy link
Contributor Author

krOoze commented Mar 12, 2023

@Tobski Well, the access masks are still extraneous. If we really want it to be robust against load\store op change, I would prefer this nuance to be explicitly stated in the code, such as:

VkAccessFlags dstAccessFlags;
if( depthFramebufferAttachment.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD )
	dstAccessFlags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
else if( depthFramebufferAttachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR
      || depthFramebufferAttachment.loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE )
	dstAccessFlags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
else panic();

@Tobski
Copy link
Contributor

Tobski commented Mar 13, 2023

We're currently discussing whether write flags are required at all in destination access flags because it seems there's been some confusion; until that's resolved I don't want to touch this, because the resolution there will affect the point you're making, and whether it needs addressing at all; but yea it probably should be a little more explicit about handling the different load ops.

@Tobski Tobski self-assigned this Mar 13, 2023
@Tobski Tobski reopened this Mar 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants