-
Notifications
You must be signed in to change notification settings - Fork 30
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
First Timeline Semaphore use #158
base: development
Are you sure you want to change the base?
Conversation
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.
Cool stuff! Please mind the comments and update according to the requested changes in the Auto-Vk PR!
@@ -186,6 +186,7 @@ namespace avk | |||
.setShaderUniformTexelBufferArrayDynamicIndexing(VK_TRUE) | |||
.setShaderStorageTexelBufferArrayDynamicIndexing(VK_TRUE) | |||
.setDescriptorIndexing(VK_TRUE) | |||
.setTimelineSemaphore(VK_TRUE) |
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 probably not be enabled by default but instead, enabled through the std::function<void(vk::PhysicalDeviceVulkan12Features&)>
parameter that can be passed to configure_and_compose
.
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.
✅
/** \brief Records and submits commands to a queue together with a newly created timeline semaphore, which is signalled upon completion. | ||
* \param aRecordedCommandsAndSyncInstructions List of commands to record and submit. | ||
* \param aQueue The queue to submit the commands to. | ||
* \param aSrcSignalStage Defines in which stage it is safe to signal the created timeline semaphore. | ||
* \param aSignalValue The value to SIGNAL the timeline semaphore to. | ||
* \param aInitialValue (optional) The value to INITIALIZE the newly created timeline semaphore with. | ||
* \param aUsageFlags (optional) CommandBuffer usage flags. | ||
* \return The newly created timeline semaphore. | ||
*/ |
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.
/** \brief Records and submits commands to a queue together with a newly created timeline semaphore, which is signalled upon completion. | |
* \param aRecordedCommandsAndSyncInstructions List of commands to record and submit. | |
* \param aQueue The queue to submit the commands to. | |
* \param aSrcSignalStage Defines in which stage it is safe to signal the created timeline semaphore. | |
* \param aSignalValue The value to SIGNAL the timeline semaphore to. | |
* \param aInitialValue (optional) The value to INITIALIZE the newly created timeline semaphore with. | |
* \param aUsageFlags (optional) CommandBuffer usage flags. | |
* \return The newly created timeline semaphore. | |
*/ | |
/** @brief Records and submits commands to a queue together with a newly created timeline semaphore, which is signaled upon completion. | |
* @param aRecordedCommandsAndSyncInstructions List of commands to record and submit. | |
* @param aQueue The queue to submit the commands to. | |
* @param aSrcSignalStage Defines in which stage(s) after which is safe to signal the created timeline semaphore. | |
* @param aSignalValue The value to signal the timeline semaphore to. | |
* @param aInitialValue (optional) The value to initialize the newly created timeline semaphore with. | |
* @param aUsageFlags (optional) CommandBuffer usage flags. | |
* @return The newly created timeline semaphore. | |
*/ |
Please use @
instead of \
, and please try to horizontally align all the @
.
Also, please use spaces to align the comments!
Please mind the comment fixes!
And "signaled" is written in a wrong way multiple times, I'm afraid (also before this PR).
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.
✅
.submit(); | ||
|
||
aSignalInfo.mSignalSemaphore.get().handle_lifetime_of(std::move(cmdBfr)); | ||
// TODO we probably need another way to handle the lifetime of resources since timeline semaphores aren't single use ==> live longer |
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.
That should actually be okay, because the (timeline) semaphore takes care of the ownership of the command buffer.
Or what was your argument in this case exactly?
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.
What I was talking about here was that since timeline semaphores are no longer single-shot synchronization primitives (1 signal, 1 wait) they might have a lifetime close to the whole application runtime. If a command buffer now gets enqueued and executed early on in the semaphore's lifespan, won't it be kept alive until the semaphore is destroyed, way longer than it needs to exist?
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.
Oh, yeah. Now I get the point. You're completely right.
Hmm, the right way to do this would probably be to turn std::vector<any_owning_resource_t>
into std::vector<std::tuple<any_owning_resource_t, uint64_t>>
, where the uint64_t
item represents the timeline semaphore's value after which it is safe to delete the resource.
A similar approach is implemented for command buffers, see the following code:
// prepare command buffer for re-recording
void command_buffer_t::prepare_for_reuse()
{
if (mPostExecutionHandler.has_value()) {
// Clear post-execution handler
mPostExecutionHandler.reset();
}
if (mCustomDeleter.has_value() && *mCustomDeleter) {
// If there is a custom deleter => call it now
(*mCustomDeleter)();
mCustomDeleter.reset();
}
mLifetimeHandledResources.clear();
}
Just for timeline semaphores, it would not be a mLifetimeHandledResources.clear();
, but a clear depending on the uint64_t
value.
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.
With the most recent changes, I added an optional value
parameter to semaphore_t::handle_lifetime_of
. Here I just pass the same value the semaphore will be signaled to, once the work has finished.
I suspect this is wrong in cases where the passed aSignalInfo
uses a stage other than all_commands
. Do you think we should add another param for a cmdBuffer deletion value, or just let the caller setup the lifetime handling themselves?
std::move(posFillCmd), | ||
std::move(tcoFillCmd), | ||
std::move(nrmFillCmd), | ||
std::move(idxFillCmd) | ||
// ^ No need for any synchronization in-between, because the commands do not depend on each other. | ||
}, *mQueue); | ||
}, * mQueue, { vk::PipelineStageFlagBits2::eAllTransfer }, 1); |
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.
}, * mQueue, { vk::PipelineStageFlagBits2::eAllTransfer }, 1); | |
}, *mQueue, avk::stage::all_transfer, 1); |
Better in terms of conciseness and formatting.
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.
✅
std::move(materialCommands), | ||
mMaterialBuffer->fill(gpuMaterials.data(), 0) | ||
}, *mQueue); | ||
matFence->wait_until_signalled(); | ||
}, *mQueue, {vk::PipelineStageFlagBits2::eAllCommands}, 1); |
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.
}, *mQueue, {vk::PipelineStageFlagBits2::eAllCommands}, 1); | |
}, *mQueue, avk::stage::all_commands, 1); |
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.
✅
69721d4
to
fe3a09c
Compare
fe3a09c
to
2d00de1
Compare
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.
Let's review again after the requested changes in Auto-Vk!
* @param aRecordedCommandsAndSyncInstructions List of commands to record and submit. | ||
* @param aQueue The queue to submit the commands to. | ||
* @param aSrcSignalStage Defines in which stage it is safe to signal the created timeline semaphore. | ||
* @param aSignalValue The value to SIGNAL the timeline semaphore to. | ||
* @param aInitialValue (optional) The value to INITIALIZE the newly created timeline semaphore with. | ||
* @param aUsageFlags (optional) CommandBuffer usage flags. | ||
* @return The newly created timeline semaphore. | ||
*/ |
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.
* @param aRecordedCommandsAndSyncInstructions List of commands to record and submit. | |
* @param aQueue The queue to submit the commands to. | |
* @param aSrcSignalStage Defines in which stage it is safe to signal the created timeline semaphore. | |
* @param aSignalValue The value to SIGNAL the timeline semaphore to. | |
* @param aInitialValue (optional) The value to INITIALIZE the newly created timeline semaphore with. | |
* @param aUsageFlags (optional) CommandBuffer usage flags. | |
* @return The newly created timeline semaphore. | |
*/ | |
* @param aRecordedCommandsAndSyncInstructions List of commands to record and submit. | |
* @param aQueue The queue to submit the commands to. | |
* @param aSrcSignalStage Defines in which stage it is safe to signal the created timeline semaphore. | |
* @param aSignalValue The value to SIGNAL the timeline semaphore to. | |
* @param aInitialValue (optional) The value to INITIALIZE the newly created timeline semaphore with. | |
* @param aUsageFlags (optional) CommandBuffer usage flags. | |
* @return The newly created timeline semaphore. | |
*/ |
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.
Please add spaces before the *
, so that all *
are vertically aligned!
.submit(); | ||
|
||
aSignalInfo.mSignalSemaphore.get().handle_lifetime_of(std::move(cmdBfr)); | ||
// TODO we probably need another way to handle the lifetime of resources since timeline semaphores aren't single use ==> live longer |
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.
Oh, yeah. Now I get the point. You're completely right.
Hmm, the right way to do this would probably be to turn std::vector<any_owning_resource_t>
into std::vector<std::tuple<any_owning_resource_t, uint64_t>>
, where the uint64_t
item represents the timeline semaphore's value after which it is safe to delete the resource.
A similar approach is implemented for command buffers, see the following code:
// prepare command buffer for re-recording
void command_buffer_t::prepare_for_reuse()
{
if (mPostExecutionHandler.has_value()) {
// Clear post-execution handler
mPostExecutionHandler.reset();
}
if (mCustomDeleter.has_value() && *mCustomDeleter) {
// If there is a custom deleter => call it now
(*mCustomDeleter)();
mCustomDeleter.reset();
}
mLifetimeHandledResources.clear();
}
Just for timeline semaphores, it would not be a mLifetimeHandledResources.clear();
, but a clear depending on the uint64_t
value.
add context_vulkan::record_and_submit_with_timeline_semaphore replace fences in model_loader.cpp with timeline semaphores
comment formatting use more concise options for PipelineStageFlagBits2
2230be1
to
db06a39
Compare
…ng directory, s.t. assets and shaders can be found when run from within VS.
add particle + metadata structs add compute shader skeleton add compute shader queue and setup pipeline (still unused atm) create particle buffer, intermediate buffer and vertex buffers in init()
…ctly with the particle buffer i intend to use add a temporary uniform mHostParticleBuffer and use it to draw prticles with mRenderPipeline adjust a_triangle.vert to use the particleBuffer
compute shader still runs on tha same queue directly before each frame
…ll handle_lifetime_of, with the value the semaphore will be signaled to at the end of execution
…ate thread add slider modifying physics refresh rate
keep workgroup dimensions at 1 for now
The first step towards full timeline semaphore support. Related Issue: #45
Changes:
context_vulkan::record_and_submit_with_timeline_semaphore
model_loader
example with timeline semaphores.