Contact
-
Josh Barczak jbarczak
Other Extension Metadata
- Last Modified Date
-
2020-11-12
- IP Status
-
No known IP claims.
- Contributors
-
-
Joshua Barczak, Intel
-
Jeff Bolz, NVIDIA
-
Daniel Koch, NVIDIA
-
Slawek Grajewski, Intel
-
Tobias Hector, AMD
-
Yuriy O’Donnell, Epic
-
Eric Werness, NVIDIA
-
Baldur Karlsson, Valve
-
Jesse Barker, Unity
-
Contributors to VK_KHR_acceleration_structure, VK_KHR_ray_tracing_pipeline
-
Description
The VK_KHR_deferred_host_operations
extension defines the
infrastructure and usage patterns for deferrable commands, but does not
specify any commands as deferrable.
This is left to additional dependent extensions.
Commands must not be deferred unless the deferral is specifically allowed
by another extension which depends on
VK_KHR_deferred_host_operations
.
New Enum Constants
-
VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME
-
VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION
-
Extending VkObjectType:
-
VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR
-
-
Extending VkResult:
-
VK_OPERATION_DEFERRED_KHR
-
VK_OPERATION_NOT_DEFERRED_KHR
-
VK_THREAD_DONE_KHR
-
VK_THREAD_IDLE_KHR
-
Code Examples
The following examples will illustrate the concept of deferrable operations
using a hypothetical example.
The command vkDoSomethingExpensive
denotes a deferrable command.
The following example illustrates how a vulkan application might request deferral of an expensive operation:
// create a deferred operation
VkDeferredOperationKHR hOp;
VkResult result = vkCreateDeferredOperationKHR(device, pCallbacks, &hOp);
assert(result == VK_SUCCESS);
result = vkDoSomethingExpensive(device, hOp, ...);
assert( result == VK_OPERATION_DEFERRED_KHR );
// operation was deferred. Execute it asynchronously
std::async::launch(
[ hOp ] ( )
{
vkDeferredOperationJoinKHR(device, hOp);
result = vkGetDeferredOperationResultKHR(device, hOp);
// deferred operation is now complete. 'result' indicates success or failure
vkDestroyDeferredOperationKHR(device, hOp, pCallbacks);
}
);
The following example illustrates extracting concurrency from a single deferred operation:
// create a deferred operation
VkDeferredOperationKHR hOp;
VkResult result = vkCreateDeferredOperationKHR(device, pCallbacks, &hOp);
assert(result == VK_SUCCESS);
result = vkDoSomethingExpensive(device, hOp, ...);
assert( result == VK_OPERATION_DEFERRED_KHR );
// Query the maximum amount of concurrency and clamp to the desired maximum
uint32_t numLaunches = std::min(vkGetDeferredOperationMaxConcurrencyKHR(device, hOp), maxThreads);
std::vector<std::future<void> > joins;
for (uint32_t i = 0; i < numLaunches; i++) {
joins.emplace_back(std::async::launch(
[ hOp ] ( )
{
vkDeferredOperationJoinKHR(device, hOp);
// in a job system, a return of VK_THREAD_IDLE_KHR should queue another
// job, but it is not functionally required
}
));
}
for (auto &f : joins) {
f.get();
}
result = vkGetDeferredOperationResultKHR(device, hOp);
// deferred operation is now complete. 'result' indicates success or failure
vkDestroyDeferredOperationKHR(device, hOp, pCallbacks);
The following example shows a subroutine which guarantees completion of a deferred operation, in the presence of multiple worker threads, and returns the result of the operation.
VkResult FinishDeferredOperation(VkDeferredOperationKHR hOp)
{
// Attempt to join the operation until the implementation indicates that we should stop
VkResult result = vkDeferredOperationJoinKHR(device, hOp);
while( result == VK_THREAD_IDLE_KHR )
{
std::this_thread::yield();
result = vkDeferredOperationJoinKHR(device, hOp);
}
switch( result )
{
case VK_SUCCESS:
{
// deferred operation has finished. Query its result
result = vkGetDeferredOperationResultKHR(device, hOp);
}
break;
case VK_THREAD_DONE_KHR:
{
// deferred operation is being wrapped up by another thread
// wait for that thread to finish
do
{
std::this_thread::yield();
result = vkGetDeferredOperationResultKHR(device, hOp);
} while( result == VK_NOT_READY );
}
break;
default:
assert(false); // other conditions are illegal.
break;
}
return result;
}
Issues
-
Should this extension have a VkPhysicalDevice*FeaturesKHR structure?
RESOLVED: No. This extension does not add any functionality on its own and requires a dependent extension to actually enable functionality and thus there is no value in adding a feature structure. If necessary, any dependent extension could add a feature boolean if it wanted to indicate that it is adding optional deferral support.
Version History
-
Revision 1, 2019-12-05 (Josh Barczak, Daniel Koch)
-
Initial draft.
-
-
Revision 2, 2020-03-06 (Daniel Koch, Tobias Hector)
-
Add missing VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR enum
-
fix sample code
-
Clarified deferred operation parameter lifetimes (#2018,!3647)
-
-
Revision 3, 2020-05-15 (Josh Barczak)
-
Clarify behavior of vkGetDeferredOperationMaxConcurrencyKHR, allowing it to return 0 if the operation is complete (#2036,!3850)
-
-
Revision 4, 2020-11-12 (Tobias Hector, Daniel Koch)
-
Remove VkDeferredOperationInfoKHR and change return value semantics when deferred host operations are in use (#2067,3813)
-
clarify return value of vkGetDeferredOperationResultKHR (#2339,!4110)
-
Document Notes
For more information, see the Vulkan Specification
This page is a generated document. Fixes and changes should be made to the generator scripts, not directly.