-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Fix push constants with ext sampler (VK) #9445
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
base: main
Are you sure you want to change the base?
Conversation
| } | ||
| // If we're doing bind in draw, it's possible there are some push constants that weren't | ||
| // written out because we didn't have the pipelineLayout yet. Push them now. | ||
| program->flushPushConstants(pipelineLayout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be inside the above if, only need to do this when we bind a new pipeline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
technically we probably shouldn't even have that if-statement, because it's guaranteed that condition will be true with the code written as it is today. that said, i'm happy to move this into the if block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do think that if block is still necessary, because you could have multiple draw calls for one pipeline. It's just an optomization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahhhhh ok - then in that case, yes, this absolutely should be in the if block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, thinking about it some more. I think it needs to be outside the conditional. This is also valid
bindPipeline
setPushConstant
draw
setPushConstant
draw
We need to be able do that second update of push constants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the second case, we wouldn't have the push constants in a list that needs to be flushed. we're only storing values if the layout is null. in the second case, the layout should not be null. unless i'm missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes you're right. The mPipelinState.pipelineLayout thing. Can you add a comment to that effect above the program->flushPushConstants(pipelineLayout);? Something like, "Further push constant updates after the pipeline is bound will immediately set the constants because the pipeline is known (see VulkanProgram::writePushConstant)".
Because this logic is getting harder to follow with intertwining paths.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added exactly that comment, sums it up fairly well.
| auto const& [doBindInDraw, bundle] = mPipelineState.bindInDraw; | ||
|
|
||
| fvkutils::DescriptorSetMask setsWithExternalSamplers = {}; | ||
| if (doBindInDraw) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this expected to be the common case? If not, it should be UTILS_UNLIKELY and in fact I think this should all be moved into a separate function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's common if you have externally sampled textures, otherwise will never be hit. So not sure how one would quantify that with UTILS_LIKELY/UNLIKELY
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this is out of scope for this change, and a much broader question
| // It's possible that we don't have the layout yet. But, we don't want to "forget" | ||
| // about the push constant! We can flush the constants later, once the layout is set. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you explain in which scenario we have or don't have a layout?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for external samplers, in bindPipeline(), there's an early return - prior to setting the layout. push constants are then set after that, and finally, the layout is selected and bound in draw2() (called after binding push constants in the render pass).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant, in the comment :-)
|
|
||
| PipelineInfo* mInfo; | ||
| VkDevice mDevice = VK_NULL_HANDLE; | ||
| std::vector<PushConstantInfo> mQueuedPushConstants; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we do a "reasonable" .reserve() for this, so we avoid too many heap allocations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i did consider that, but it's hard to know what a reasonable number is. the driver api takes one push constant at a time, and only the frontend knows how many push constants will be pushed. it's possible that actually, only the app knows about the push constants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, we have MAX_PUSH_CONSTANT_COUNT (32). So I think we can be pragmatic here and maybe do a reserve with 8 for instance.
Currently, in Vulkan, we set the pipeline layout when binding the pipeline, which doesn't happen until draw time when external samplers are present. In cases like that, we push constants with the layout VK_NULL_HANDLE, which is not valid. Instead, we can wait until the pipeline layout is known, and then flush all push constants.
5a5cb7e to
91a9b26
Compare
Some of the logic related to external samplers is getting to be a bit convoluted.
8035247 to
191ed71
Compare
poweifeng
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
|
@pixelflinger please re-review when you get a chance! |
Currently, in Vulkan, we set the pipeline layout when binding the pipeline, which doesn't happen until draw time when external samplers are present. In cases like that, we push constants with the layout VK_NULL_HANDLE, which is not valid. Instead, we can wait until the pipeline layout is known, and then flush all push constants.