Class KHRDeferredHostOperations
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.
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;
}
- Name String
VK_KHR_deferred_host_operations- Extension Type
- Device extension
- Registered Extension Number
- 269
- Revision
- 4
- 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
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringThe extension name.static final intThe extension specification version.static final intExtendsVkObjectType.static final intExtendsVkResult.static final intExtendsVkResult.static final intExtendsVkResult.static final intExtendsVkResult. -
Method Summary
Modifier and TypeMethodDescriptionstatic intnvkCreateDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, long pAllocator, long pDeferredOperation) Unsafe version of:CreateDeferredOperationKHRstatic voidnvkDestroyDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, long operation, long pAllocator) Unsafe version of:DestroyDeferredOperationKHRstatic intvkCreateDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, @Nullable VkAllocationCallbacks pAllocator, long[] pDeferredOperation) Array version of:CreateDeferredOperationKHRstatic intvkCreateDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, @Nullable VkAllocationCallbacks pAllocator, LongBuffer pDeferredOperation) Create a deferred operation handle.static intvkDeferredOperationJoinKHR(org.lwjgl.vulkan.VkDevice device, long operation) Assign a thread to a deferred operation.static voidvkDestroyDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, long operation, @Nullable VkAllocationCallbacks pAllocator) Destroy a deferred operation handle.static intvkGetDeferredOperationMaxConcurrencyKHR(org.lwjgl.vulkan.VkDevice device, long operation) Query the maximum concurrency on a deferred operation.static intvkGetDeferredOperationResultKHR(org.lwjgl.vulkan.VkDevice device, long operation) Query the result of a deferred operation.
-
Field Details
-
VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION
public static final int VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSIONThe extension specification version.- See Also:
-
VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME
The extension name.- See Also:
-
VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR
public static final int VK_OBJECT_TYPE_DEFERRED_OPERATION_KHRExtendsVkObjectType.- See Also:
-
VK_THREAD_IDLE_KHR
public static final int VK_THREAD_IDLE_KHRExtendsVkResult.Enum values:
- See Also:
-
VK_THREAD_DONE_KHR
public static final int VK_THREAD_DONE_KHRExtendsVkResult.Enum values:
- See Also:
-
VK_OPERATION_DEFERRED_KHR
public static final int VK_OPERATION_DEFERRED_KHRExtendsVkResult.Enum values:
- See Also:
-
VK_OPERATION_NOT_DEFERRED_KHR
public static final int VK_OPERATION_NOT_DEFERRED_KHRExtendsVkResult.Enum values:
- See Also:
-
-
Method Details
-
nvkCreateDeferredOperationKHR
public static int nvkCreateDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, long pAllocator, long pDeferredOperation) Unsafe version of:CreateDeferredOperationKHR -
vkCreateDeferredOperationKHR
public static int vkCreateDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, @Nullable VkAllocationCallbacks pAllocator, LongBuffer pDeferredOperation) Create a deferred operation handle.C Specification
To construct the tracking object for a deferred command, call:
VkResult vkCreateDeferredOperationKHR( VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation);Valid Usage (Implicit)
devicemust be a validVkDevicehandle- If
pAllocatoris notNULL,pAllocatormust be a valid pointer to a validVkAllocationCallbacksstructure pDeferredOperationmust be a valid pointer to aVkDeferredOperationKHRhandle
Return Codes
- On success, this command returns
- On failure, this command returns
See Also
- Parameters:
device- the device which ownsoperation.pAllocator- controls host memory allocation as described in the Memory Allocation chapter.pDeferredOperation- a pointer to a handle in which the createdVkDeferredOperationKHRis returned.
-
nvkDestroyDeferredOperationKHR
public static void nvkDestroyDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, long operation, long pAllocator) Unsafe version of:DestroyDeferredOperationKHR -
vkDestroyDeferredOperationKHR
public static void vkDestroyDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, long operation, @Nullable VkAllocationCallbacks pAllocator) Destroy a deferred operation handle.C Specification
When a deferred operation is completed, the application can destroy the tracking object by calling:
void vkDestroyDeferredOperationKHR( VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator);Valid Usage
- If
VkAllocationCallbackswere provided whenoperationwas created, a compatible set of callbacks must be provided here - If no
VkAllocationCallbackswere provided whenoperationwas created,pAllocatormust beNULL operationmust be completed
Valid Usage (Implicit)
devicemust be a validVkDevicehandle- If
operationis notNULL_HANDLE,operationmust be a validVkDeferredOperationKHRhandle - If
pAllocatoris notNULL,pAllocatormust be a valid pointer to a validVkAllocationCallbacksstructure - If
operationis a valid handle, it must have been created, allocated, or retrieved fromdevice
Host Synchronization
- Host access to
operationmust be externally synchronized
See Also
- Parameters:
device- the device which ownsoperation.operation- the completed operation to be destroyed.pAllocator- controls host memory allocation as described in the Memory Allocation chapter.
- If
-
vkGetDeferredOperationMaxConcurrencyKHR
public static int vkGetDeferredOperationMaxConcurrencyKHR(org.lwjgl.vulkan.VkDevice device, long operation) Query the maximum concurrency on a deferred operation.C Specification
To query the number of additional threads that can usefully be joined to a deferred operation, call:
uint32_t vkGetDeferredOperationMaxConcurrencyKHR( VkDevice device, VkDeferredOperationKHR operation);Description
The returned value is the maximum number of threads that can usefully execute a deferred operation concurrently, reported for the state of the deferred operation at the point this command is called. This value is intended to be used to better schedule work onto available threads. Applications can join any number of threads to the deferred operation and expect it to eventually complete, though excessive joins may return
THREAD_DONE_KHRimmediately, performing no useful work.If
operationis complete,vkGetDeferredOperationMaxConcurrencyKHRreturns zero.If
operationis currently joined to any threads, the value returned by this command may immediately be out of date.If
operationis pending, implementations must not return zero unless at least one thread is currently executingDeferredOperationJoinKHRonoperation. If there are such threads, the implementation should return an estimate of the number of additional threads which it could profitably use.Implementations may return
232-1to indicate that the maximum concurrency is unknown and cannot be easily derived. Implementations may return values larger than the maximum concurrency available on the host CPU. In these situations, an application should clamp the return value rather than oversubscribing the machine.Note
The recommended usage pattern for applications is to query this value once, after deferral, and schedule no more than the specified number of threads to join the operation. Each time a joined thread receives
THREAD_IDLE_KHR, the application should schedule an additional join at some point in the future, but is not required to do so.Valid Usage (Implicit)
devicemust be a validVkDevicehandleoperationmust be a validVkDeferredOperationKHRhandleoperationmust have been created, allocated, or retrieved fromdevice
- Parameters:
device- the device which ownsoperation.operation- the deferred operation to be queried.
-
vkGetDeferredOperationResultKHR
public static int vkGetDeferredOperationResultKHR(org.lwjgl.vulkan.VkDevice device, long operation) Query the result of a deferred operation.C Specification
The
vkGetDeferredOperationResultKHRfunction is defined as:VkResult vkGetDeferredOperationResultKHR( VkDevice device, VkDeferredOperationKHR operation);Description
If no command has been deferred on
operation,vkGetDeferredOperationResultKHRreturnsSUCCESS.If the deferred operation is pending,
vkGetDeferredOperationResultKHRreturnsNOT_READY.If the deferred operation is complete, it returns the appropriate return value from the original command. This value must be one of the
VkResultvalues which could have been returned by the original command if the operation had not been deferred.Valid Usage (Implicit)
devicemust be a validVkDevicehandleoperationmust be a validVkDeferredOperationKHRhandleoperationmust have been created, allocated, or retrieved fromdevice
Return Codes
- Parameters:
device- the device which ownsoperation.operation- the operation whose deferred result is being queried.
-
vkDeferredOperationJoinKHR
public static int vkDeferredOperationJoinKHR(org.lwjgl.vulkan.VkDevice device, long operation) Assign a thread to a deferred operation.C Specification
To assign a thread to a deferred operation, call:
VkResult vkDeferredOperationJoinKHR( VkDevice device, VkDeferredOperationKHR operation);Description
The
vkDeferredOperationJoinKHRcommand will execute a portion of the deferred operation on the calling thread.The return value will be one of the following:
- A return value of
SUCCESSindicates thatoperationis complete. The application should useGetDeferredOperationResultKHRto retrieve the result ofoperation. - A return value of
THREAD_DONE_KHRindicates that the deferred operation is not complete, but there is no work remaining to assign to threads. Future calls toDeferredOperationJoinKHRare not necessary and will simply harm performance. This situation may occur when other threads executingDeferredOperationJoinKHRare about to completeoperation, and the implementation is unable to partition the workload any further. - A return value of
THREAD_IDLE_KHRindicates that the deferred operation is not complete, and there is no work for the thread to do at the time of the call. This situation may occur if the operation encounters a temporary reduction in parallelism. By returningTHREAD_IDLE_KHR, the implementation is signaling that it expects that more opportunities for parallelism will emerge as execution progresses, and that future calls toDeferredOperationJoinKHRcan be beneficial. In the meantime, the application can perform other work on the calling thread.
Implementations must guarantee forward progress by enforcing the following invariants:
- If only one thread has invoked
DeferredOperationJoinKHRon a given operation, that thread must execute the operation to completion and returnSUCCESS. - If multiple threads have concurrently invoked
DeferredOperationJoinKHRon the same operation, then at least one of them must complete the operation and returnSUCCESS.
Valid Usage (Implicit)
devicemust be a validVkDevicehandleoperationmust be a validVkDeferredOperationKHRhandleoperationmust have been created, allocated, or retrieved fromdevice
Return Codes
- On success, this command returns
- On failure, this command returns
- Parameters:
device- the device which ownsoperation.operation- the deferred operation that the calling thread should work on.
- A return value of
-
vkCreateDeferredOperationKHR
public static int vkCreateDeferredOperationKHR(org.lwjgl.vulkan.VkDevice device, @Nullable VkAllocationCallbacks pAllocator, long[] pDeferredOperation) Array version of:CreateDeferredOperationKHR
-