• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2014-2022 The Khronos Group Inc.
2//
3// SPDX-License-Identifier: CC-BY-4.0
4
5include::{generated}/meta/{refprefix}VK_KHR_deferred_host_operations.adoc[]
6
7=== Other Extension Metadata
8
9*Last Modified Date*::
10    2020-11-12
11*IP Status*::
12    No known IP claims.
13*Contributors*::
14  - Joshua Barczak, Intel
15  - Jeff Bolz, NVIDIA
16  - Daniel Koch, NVIDIA
17  - Slawek Grajewski, Intel
18  - Tobias Hector, AMD
19  - Yuriy O'Donnell, Epic
20  - Eric Werness, NVIDIA
21  - Baldur Karlsson, Valve
22  - Jesse Barker, Unity
23  - Contributors to VK_KHR_acceleration_structure,
24    VK_KHR_ray_tracing_pipeline
25
26=== Description
27
28The `apiext:VK_KHR_deferred_host_operations` extension defines the
29infrastructure and usage patterns for deferrable commands, but does not
30specify any commands as deferrable.
31This is left to additional dependent extensions.
32Commands must: not be deferred unless the deferral is specifically allowed
33by another extension which depends on
34`apiext:VK_KHR_deferred_host_operations`.
35
36include::{generated}/interfaces/VK_KHR_deferred_host_operations.adoc[]
37
38=== Code Examples
39
40The following examples will illustrate the concept of deferrable operations
41using a hypothetical example.
42The command ftext:vkDoSomethingExpensive denotes a deferrable command.
43
44The following example illustrates how a vulkan application might request
45deferral of an expensive operation:
46
47[source,cpp]
48----
49// create a deferred operation
50VkDeferredOperationKHR hOp;
51VkResult result = vkCreateDeferredOperationKHR(device, pCallbacks, &hOp);
52assert(result == VK_SUCCESS);
53
54result = vkDoSomethingExpensive(device, hOp, ...);
55assert( result == VK_OPERATION_DEFERRED_KHR );
56
57// operation was deferred.  Execute it asynchronously
58std::async::launch(
59    [ hOp ] ( )
60    {
61        vkDeferredOperationJoinKHR(device, hOp);
62
63        result = vkGetDeferredOperationResultKHR(device, hOp);
64
65        // deferred operation is now complete.  'result' indicates success or failure
66
67        vkDestroyDeferredOperationKHR(device, hOp, pCallbacks);
68    }
69);
70
71----
72
73The following example illustrates extracting concurrency from a single
74deferred operation:
75
76[source,cpp]
77----
78
79// create a deferred operation
80VkDeferredOperationKHR hOp;
81VkResult result = vkCreateDeferredOperationKHR(device, pCallbacks, &hOp);
82assert(result == VK_SUCCESS);
83
84result = vkDoSomethingExpensive(device, hOp, ...);
85assert( result == VK_OPERATION_DEFERRED_KHR );
86
87// Query the maximum amount of concurrency and clamp to the desired maximum
88uint32_t numLaunches = std::min(vkGetDeferredOperationMaxConcurrencyKHR(device, hOp), maxThreads);
89
90std::vector<std::future<void> > joins;
91
92for (uint32_t i = 0; i < numLaunches; i++) {
93  joins.emplace_back(std::async::launch(
94    [ hOp ] ( )
95    {
96        vkDeferredOperationJoinKHR(device, hOp);
97                // in a job system, a return of VK_THREAD_IDLE_KHR should queue another
98                // job, but it is not functionally required
99    }
100  ));
101}
102
103for (auto &f : joins) {
104  f.get();
105}
106
107result = vkGetDeferredOperationResultKHR(device, hOp);
108
109// deferred operation is now complete.  'result' indicates success or failure
110
111vkDestroyDeferredOperationKHR(device, hOp, pCallbacks);
112
113----
114
115
116The following example shows a subroutine which guarantees completion of a
117deferred operation, in the presence of multiple worker threads, and returns
118the result of the operation.
119
120[source,cpp]
121----
122
123VkResult FinishDeferredOperation(VkDeferredOperationKHR hOp)
124{
125    // Attempt to join the operation until the implementation indicates that we should stop
126
127    VkResult result = vkDeferredOperationJoinKHR(device, hOp);
128    while( result == VK_THREAD_IDLE_KHR )
129    {
130        std::this_thread::yield();
131        result = vkDeferredOperationJoinKHR(device, hOp);
132    }
133
134    switch( result )
135    {
136    case VK_SUCCESS:
137        {
138            // deferred operation has finished.  Query its result
139            result = vkGetDeferredOperationResultKHR(device, hOp);
140        }
141        break;
142
143    case VK_THREAD_DONE_KHR:
144        {
145            // deferred operation is being wrapped up by another thread
146            //  wait for that thread to finish
147            do
148            {
149                std::this_thread::yield();
150                result = vkGetDeferredOperationResultKHR(device, hOp);
151            } while( result == VK_NOT_READY );
152        }
153        break;
154
155    default:
156        assert(false); // other conditions are illegal.
157        break;
158    }
159
160    return result;
161}
162----
163
164=== Issues
165
166. Should this extension have a VkPhysicalDevice*FeaturesKHR structure?
167
168*RESOLVED*: No.
169This extension does not add any functionality on its own and requires a
170dependent extension to actually enable functionality and thus there is no
171value in adding a feature structure.
172If necessary, any dependent extension could add a feature boolean if it
173wanted to indicate that it is adding optional deferral support.
174
175=== Version History
176
177  * Revision 1, 2019-12-05 (Josh Barczak, Daniel Koch)
178  ** Initial draft.
179  * Revision 2, 2020-03-06 (Daniel Koch, Tobias Hector)
180  ** Add missing VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR enum
181  ** fix sample code
182  ** Clarified deferred operation parameter lifetimes (#2018,!3647)
183  * Revision 3, 2020-05-15 (Josh Barczak)
184  ** Clarify behavior of vkGetDeferredOperationMaxConcurrencyKHR, allowing
185     it to return 0 if the operation is complete (#2036,!3850)
186  * Revision 4, 2020-11-12 (Tobias Hector, Daniel Koch)
187  ** Remove VkDeferredOperationInfoKHR and change return value semantics
188     when deferred host operations are in use (#2067,3813)
189  ** clarify return value of vkGetDeferredOperationResultKHR (#2339,!4110)
190