|
| 1 | +// Copyright 2018-2024 The Khronos Group. This work is licensed under a |
| 2 | +// Creative Commons Attribution 4.0 International License; see |
| 3 | +// http://creativecommons.org/licenses/by/4.0/ |
| 4 | + |
| 5 | +[[cl_khr_command_buffer_mutable_memory_commands]] |
| 6 | +== Command Buffers - Mutable Memory Commands (Provisional) |
| 7 | + |
| 8 | +This extension enables users to modify the configuration memory commands |
| 9 | +between command-buffer enqueues. |
| 10 | + |
| 11 | +=== General Information |
| 12 | + |
| 13 | +==== Name Strings |
| 14 | + |
| 15 | +`cl_khr_command_buffer_mutable_memory_commands` |
| 16 | + |
| 17 | +==== Version History |
| 18 | + |
| 19 | +[cols="1,1,3",options="header",] |
| 20 | +|==== |
| 21 | +| *Date* | *Version* | *Description* |
| 22 | +| 2023-11-21 | 0.9.0 | First assigned version (provisional). |
| 23 | +|==== |
| 24 | + |
| 25 | +==== Dependencies |
| 26 | + |
| 27 | +This extension requires the `cl_khr_command_buffer_mutable_dispatch` extension |
| 28 | +version 0.9.0. |
| 29 | + |
| 30 | +==== Contributors |
| 31 | + |
| 32 | +Ewan Crawford, Codeplay Software Ltd. + |
| 33 | +Kenneth Benzie, Codeplay Software Ltd. + |
| 34 | +Jack Frankland, Codeplay Software Ltd. + |
| 35 | +Ben Ashbaugh, Intel. + |
| 36 | +Balaji Calidas, Qualcomm Technologies Inc. + |
| 37 | +Sreelakshmi Haridas Maruthur, Qualcomm Technologies Inc. + |
| 38 | +Kevin Petit, Arm Ltd. + |
| 39 | + |
| 40 | +==== Status |
| 41 | + |
| 42 | +Draft spec, NOT APPROVED!! |
| 43 | + |
| 44 | +=== Overview |
| 45 | + |
| 46 | +The `cl_khr_command_buffer` extension separates command construction from |
| 47 | +enqueue by providing a mechanism to record an immutable set of commands which |
| 48 | +can then be repeatedly enqueued. Another extension layered on top, |
| 49 | +`cl_khr_command_buffer_mutable_dispatch` allows ND-Range kernel execution |
| 50 | +commands recorded to a command-buffer to be modified between command-buffer |
| 51 | +enqueues by providing a command-buffer update API {clUpdateMutableCommandsKHR}. |
| 52 | + |
| 53 | +`cl_khr_command_buffer_mutable_memory_commands` builds on |
| 54 | +`cl_khr_command_buffer_mutable_dispatch` to use the {clUpdateMutableCommandsKHR} |
| 55 | +entry-point for enabling mutability of _memory-commands_ recorded to a |
| 56 | +command-buffer, those commands taking a {cl_mem_TYPE} or SVM pointer argument. |
| 57 | + |
| 58 | +=== New API Types |
| 59 | + |
| 60 | +[[cl_mutable_copy_buffer_command_config_khr]] |
| 61 | +include::{generated}/api/structs/cl_mutable_copy_buffer_command_config_khr.txt[] |
| 62 | + |
| 63 | +_command_ A mutable-command object returned by {clCommandCopyBufferKHR}. |
| 64 | + |
| 65 | +_src_buffer_, _dst_buffer_, _src_offset_, _dst_offset_, _size_ as specified by |
| 66 | +the associated {clCommandCopyBufferKHR} parameters. |
| 67 | + |
| 68 | +[[cl_mutable_copy_buffer_rect_command_config_khr]] |
| 69 | +include::{generated}/api/structs/cl_mutable_copy_buffer_rect_command_config_khr.txt[] |
| 70 | + |
| 71 | +_command_ A mutable-command object returned by {clCommandCopyBufferRectKHR}. |
| 72 | + |
| 73 | +_src_buffer_, _dst_buffer_, _src_origin_, _dst_origin_, _region_, _src_row_pitch_, |
| 74 | +_src_slice_pitch_, _dst_row_pitch_, _dst_slice_pitch_ as specified by the |
| 75 | +associated {clCommandCopyBufferRectKHR} parameters. |
| 76 | + |
| 77 | +[[cl_mutable_copy_buffer_to_image_command_config_khr]] |
| 78 | +include::{generated}/api/structs/cl_mutable_copy_buffer_to_image_command_config_khr.txt[] |
| 79 | + |
| 80 | +_command_ A mutable-command object returned by {clCommandCopyBufferToImageKHR}. |
| 81 | + |
| 82 | +_src_buffer_, _dst_image_, _src_offset_, _dst_origin_, _region_ as specified by the |
| 83 | +associated {clCommandCopyBufferToImageKHR} parameters. |
| 84 | + |
| 85 | +[[cl_mutable_copy_image_command_config_khr]] |
| 86 | +include::{generated}/api/structs/cl_mutable_copy_image_command_config_khr.txt[] |
| 87 | + |
| 88 | +_command_ A mutable-command object returned by {clCommandCopyImageKHR}. |
| 89 | + |
| 90 | +_src_image_, _dst_image_, _src_origin_, _dst_origin_, _region_ as specified by the |
| 91 | +associated {clCommandCopyImageKHR} parameters. |
| 92 | + |
| 93 | +[[cl_mutable_copy_image_to_buffer_command_config_khr]] |
| 94 | +include::{generated}/api/structs/cl_mutable_copy_image_to_buffer_command_config_khr.txt[] |
| 95 | + |
| 96 | +_command_ A mutable-command object returned by {clCommandCopyImageToBufferKHR}. |
| 97 | + |
| 98 | +_src_image_, _dst_buffer_, _src_origin_, _region_, _dst_offset_ as specified by the |
| 99 | +associated {clCommandCopyImageToBufferKHR} parameters. |
| 100 | + |
| 101 | +[[cl_mutable_fill_buffer_command_config_khr]] |
| 102 | +include::{generated}/api/structs/cl_mutable_fill_buffer_command_config_khr.txt[] |
| 103 | + |
| 104 | +_command_ A mutable-command object returned by {clCommandFillBufferKHR}. |
| 105 | + |
| 106 | +_buffer_, _pattern_, _pattern_size_, _offset_, _size_ as specified by the |
| 107 | +associated {clCommandFillBufferKHR} parameters. |
| 108 | + |
| 109 | +[[cl_mutable_fill_image_command_config_khr]] |
| 110 | +include::{generated}/api/structs/cl_mutable_fill_image_command_config_khr.txt[] |
| 111 | + |
| 112 | +_command_ A mutable-command object returned by {clCommandFillImageKHR}. |
| 113 | + |
| 114 | +_image_, _fill_color_, _origin_, _region_ as specified by the associated |
| 115 | +{clCommandFillImageKHR} parameters. |
| 116 | + |
| 117 | +[[cl_mutable_svm_memcpy_command_config_khr]] |
| 118 | +include::{generated}/api/structs/cl_mutable_svm_memcpy_command_config_khr.txt[] |
| 119 | + |
| 120 | +_command_ A mutable-command object returned by {clCommandSVMMemcpyKHR}. |
| 121 | + |
| 122 | +_dst_ptr_, _src_ptr_, _size_ as specified by the associated {clCommandSVMMemcpyKHR} |
| 123 | +parameters. |
| 124 | + |
| 125 | +[[cl_mutable_svm_memfill_command_config_khr]] |
| 126 | +include::{generated}/api/structs/cl_mutable_svm_memfill_command_config_khr.txt[] |
| 127 | + |
| 128 | +_command_ A mutable-command object returned by {clCommandSVMMemFillKHR}. |
| 129 | + |
| 130 | +_svm_ptr_, _pattern_, _pattern_size_, _size_ as specified by the associated |
| 131 | +{clCommandSVMMemFillKHR} parameters. |
| 132 | + |
| 133 | +=== New API Enums |
| 134 | + |
| 135 | +Enums for querying device command-buffer capabilities with |
| 136 | +{clGetDeviceInfo}, see <<command-buffer-queries, device queries table>>: |
| 137 | + |
| 138 | +[source,c] |
| 139 | +---- |
| 140 | +// Bits for cl_device_command_buffer_capabilities_khr bitfield |
| 141 | +CL_COMMAND_BUFFER_CAPABILITY_MUTABLE_MEM_COMMANDS_KHR (0x1 << 5) |
| 142 | +---- |
| 143 | + |
| 144 | +Structure pointer chain enum values for {cl_update_config_type_khr_TYPE}: |
| 145 | +[source,c] |
| 146 | +---- |
| 147 | +CL_STRUCTURE_TYPE_MUTABLE_COPY_BUFFER_COMMAND_CONFIG_KHR 1 |
| 148 | +CL_STRUCTURE_TYPE_MUTABLE_COPY_BUFFER_RECT_COMMAND_CONFIG_KHR 2 |
| 149 | +CL_STRUCTURE_TYPE_MUTABLE_COPY_BUFFER_TO_IMAGE_COMMAND_CONFIG_KHR 3 |
| 150 | +CL_STRUCTURE_TYPE_MUTABLE_COPY_BUFFER_TO_IMAGE_COMMAND_CONFIG_KHR 4 |
| 151 | +CL_STRUCTURE_TYPE_MUTABLE_COPY_IMAGE_TO_BUFFER_COMMAND_CONFIG_KHR 5 |
| 152 | +CL_STRUCTURE_TYPE_MUTABLE_FILL_BUFFER_COMMAND_CONFIG_KHR 6 |
| 153 | +CL_STRUCTURE_TYPE_MUTABLE_FILL_IMAGE_COMMAND_CONFIG_KHR 7 |
| 154 | +CL_STRUCTURE_TYPE_MUTABLE_SVM_MEMCPY_COMMAND_CONFIG_KHR 8 |
| 155 | +CL_STRUCTURE_TYPE_MUTABLE_SVM_MEMFILL_COMMAND_CONFIG_KHR 9 |
| 156 | +---- |
| 157 | + |
| 158 | +Bits for {cl_command_buffer_flags_khr_TYPE} bitfield: |
| 159 | +[source,c] |
| 160 | +---- |
| 161 | +CL_MUTABLE_MEM_COMMANDS_ENABLE_KHR (0x1 << 3) |
| 162 | +---- |
| 163 | + |
| 164 | +=== Modifications to section 4.2 of the OpenCL API Specification |
| 165 | + |
| 166 | +Additional wording to _description_ column of *Table 5*, _Device Queries_, of |
| 167 | +section 4.2 under the {CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR} row: |
| 168 | +[cols="1,1,4",options="header"] |
| 169 | +|==== |
| 170 | +| cl_device_info |
| 171 | +| Return Type |
| 172 | +| Description |
| 173 | + |
| 174 | +| {CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR} |
| 175 | +| {cl_device_command_buffer_capabilities_khr_TYPE} |
| 176 | +| {CL_COMMAND_BUFFER_CAPABILITY_MUTABLE_MEM_COMMANDS_KHR} Device supports the |
| 177 | + ability to modify the {cl_mem_TYPE} arguments to commands operating on memory |
| 178 | + objects between command-buffer invocations. |
| 179 | +|==== |
| 180 | + |
| 181 | +=== Modifications to Section 5.X - Command Buffers of OpenCL API specification |
| 182 | + |
| 183 | +==== Additional Section 5.X.1 Introduction Text |
| 184 | + |
| 185 | +Further mutability for modifying _memory-commands_ recorded to a |
| 186 | +command-buffer is also possible, defined as those commands taking a |
| 187 | +{cl_mem_TYPE} or SVM pointer argument. |
| 188 | + |
| 189 | +The struct types defined by this extension for each memory-command type |
| 190 | +can be used in {clUpdateMutableCommandsKHR} to update the command |
| 191 | +configuration. |
| 192 | + |
| 193 | +The {CL_MUTABLE_MEM_COMMANDS_ENABLE_KHR} flag must be set on command-buffer |
| 194 | +creation to enable this functionality, in combination with |
| 195 | +{CL_COMMAND_BUFFER_MUTABLE_KHR} which is requires to use the |
| 196 | +{clUpdateMutableCommandsKHR} entry-point. |
| 197 | + |
| 198 | +==== clCreateCommandBufferKHR Modifications |
| 199 | + |
| 200 | +The function {clCreateCommandBufferKHR} function has an additional property |
| 201 | +bit defined: |
| 202 | + |
| 203 | +.*clCreateCommandBufferKHR* properties |
| 204 | +[cols=",,",options="header",] |
| 205 | +|==== |
| 206 | +| *Recording Properties* |
| 207 | +| *Property Value* |
| 208 | +| *Description* |
| 209 | + |
| 210 | +| {CL_COMMAND_BUFFER_FLAGS_KHR} |
| 211 | +| {cl_command_buffer_flags_khr_TYPE} |
| 212 | +| {CL_MUTABLE_MEM_COMMANDS_ENABLE_KHR} - Enable or disable modification of |
| 213 | + command-buffer memory-commands between enqueues. If set, the modification of |
| 214 | + the memory-commands in the command-buffer is enabled, |
| 215 | + otherwise it is disabled. |
| 216 | +|==== |
| 217 | + |
| 218 | +==== Memory-Command Modifications |
| 219 | + |
| 220 | +The descriptions of command recording entry-points that operate on {cl_mem_TYPE} |
| 221 | +or SVM pointer arguments are modified as described in this section. These |
| 222 | +changes apply to all of {clCommandCopyBufferKHR}, {clCommandCopyBufferRectKHR}, |
| 223 | +{clCommandCopyBufferToImageKHR}, {clCommandCopyImageKHR}, |
| 224 | +{clCommandCopyImageToBufferKHR}, {clCommandFillBufferKHR}, |
| 225 | +{clCommandFillImageKHR}, {clCommandSVMMemcpyKHR}, and {clCommandSVMMemFillKHR}. |
| 226 | + |
| 227 | +===== Parameter Update |
| 228 | + |
| 229 | +Parameter description of _mutable_handle_ is changed to: |
| 230 | + |
| 231 | +_mutable_handle_ Returns a handle to the command that can be used to modify the |
| 232 | +command between enqueues of _command_buffer_. _mutable_handle_ may be `NULL`. The |
| 233 | +lifetime of this handle is tied to the parent command-buffer, such that freeing |
| 234 | +the command-buffer will also free this handle. |
| 235 | + |
| 236 | +===== Error Updates |
| 237 | + |
| 238 | +The error condition |
| 239 | + |
| 240 | +* {CL_INVALID_VALUE} if _mutable_handle_ is not `NULL`. |
| 241 | + |
| 242 | +Is replaced with |
| 243 | + |
| 244 | +* {CL_INVALID_VALUE} if _mutable_handle_ is not `NULL` and _command_buffer_ |
| 245 | + was not created with property {CL_MUTABLE_MEM_COMMANDS_ENABLE_KHR}. |
| 246 | + |
| 247 | +==== clUpdateMutableCommandsKHR Modifications |
| 248 | + |
| 249 | +===== Error Updates |
| 250 | + |
| 251 | +The function {clUpdateMutableCommandsKHR} has the following additions to its |
| 252 | +error definitions: |
| 253 | + |
| 254 | +For any memory-command structs in the _configs_ array, then the errors defined by |
| 255 | +the associated command-buffer command creation entry-point are returned if a |
| 256 | +struct element is set to an invlaid value. Additionally, if the _command_ element |
| 257 | +of the struct is not a valid mutable command object returned from the matching |
| 258 | +memory-command entry-point then {CL_INVALID_MUTABLE_COMMAND_KHR} is returned. |
| 259 | +{CL_INVALID_MUTABLE_COMMAND_KHR} is also returned if _command_ was not created |
| 260 | +from _command_buffer_. |
| 261 | + |
| 262 | +=== Sample |
| 263 | + |
| 264 | +[source,cpp] |
| 265 | +---- |
| 266 | + #define CL_CHECK(ERROR) \ |
| 267 | + if (ERROR) { \ |
| 268 | + std::cerr << "OpenCL error: " << ERROR << "\n"; \ |
| 269 | + return ERROR; \ |
| 270 | + } |
| 271 | +
|
| 272 | + int main() { |
| 273 | + cl_platform_id platform; |
| 274 | + CL_CHECK(clGetPlatformIDs(1, &platform, nullptr)); |
| 275 | + cl_device_id device; |
| 276 | + CL_CHECK(clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, nullptr)); |
| 277 | +
|
| 278 | + cl_int error; |
| 279 | + cl_context context = |
| 280 | + clCreateContext(nullptr, 1, &device, nullptr, nullptr, &error); |
| 281 | + CL_CHECK(error); |
| 282 | +
|
| 283 | + cl_command_queue command_queue = |
| 284 | + clCreateCommandQueue(context, device, 0, &error); |
| 285 | + CL_CHECK(error); |
| 286 | +
|
| 287 | + size_t num_bytes = 128; |
| 288 | + cl_mem bufferA = |
| 289 | + clCreateBuffer(context, CL_MEM_READ_WRITE, num_bytes, nullptr, &error); |
| 290 | + CL_CHECK(error); |
| 291 | +
|
| 292 | + // Populate bufferA with data |
| 293 | +
|
| 294 | + cl_mem bufferB = |
| 295 | + clCreateBuffer(context, CL_MEM_READ_WRITE, num_bytes, nullptr, &error); |
| 296 | + CL_CHECK(error); |
| 297 | +
|
| 298 | + // Populate bufferB with data |
| 299 | +
|
| 300 | + cl_mem bufferC = |
| 301 | + clCreateBuffer(context, CL_MEM_READ_WRITE, num_bytes, nullptr, &error); |
| 302 | + CL_CHECK(eror); |
| 303 | +
|
| 304 | + cl_command_buffer_properties_khr properties[3] = { |
| 305 | + CL_COMMAND_BUFFER_FLAGS_KHR, |
| 306 | + CL_COMMAND_BUFFER_MUTABLE_KHR | CL_MUTABLE_MEM_COMMANDS_ENABLE_KHR, |
| 307 | + 0 |
| 308 | + }; |
| 309 | +
|
| 310 | + cl_command_buffer_khr command_buffer = |
| 311 | + clCreateCommandBufferKHR(1, &command_queue, properties, &error); |
| 312 | + CL_CHECK(error) |
| 313 | +
|
| 314 | + cl_mutable_command_khr copy_command_handle; |
| 315 | + CL_CHECK(clCommandCopyBufferKHR( |
| 316 | + command_buffer, |
| 317 | + command_queue, |
| 318 | + bufferA, |
| 319 | + bufferC, |
| 320 | + 0, |
| 321 | + 0, |
| 322 | + num_bytes, |
| 323 | + 0, |
| 324 | + nullptr, |
| 325 | + nullptr, |
| 326 | + ©_command_handle); |
| 327 | +
|
| 328 | + CL_CHECK(clFinalizeCommandBufferKHR(command_buffer)); |
| 329 | + CL_CHECK(clEnqueueCommandBufferKHR(0, nullptr, command_buffer, 0, nullptr, |
| 330 | + nullptr)); |
| 331 | +
|
| 332 | + cl_mutable_copy_buffer_command_config_khr buffer_copy_config = { |
| 333 | + copy_command_handle, // command |
| 334 | + bufferB, // src_buffer |
| 335 | + bufferC, // dst_buffer |
| 336 | + 0, // src_offset |
| 337 | + 0, // dst_offset |
| 338 | + num_bytes // size |
| 339 | + }; |
| 340 | +
|
| 341 | + cl_uint num_configs = 1; |
| 342 | + cl_update_config_type_khr config_types[1] = { |
| 343 | + CL_STRUCTURE_TYPE_MUTABLE_COPY_BUFFER_COMMAND_CONFIG_KHR |
| 344 | + }; |
| 345 | + void* configs[1] = {&buffer_copy_config}; |
| 346 | + CL_CHECK(clUpdateMutableCommandsKHR(command_buffer, num_configs, |
| 347 | + config_types, configs)); |
| 348 | + CL_CHECK(clEnqueueCommandBufferKHR(command_buffer, 0, nullptr, nullptr)); |
| 349 | + CL_CHECK(clFinish(command_queue)); |
| 350 | +
|
| 351 | + CL_CHECK(clReleaseCommandBufferKHR(command_buffer)); |
| 352 | + CL_CHECK(clReleaseCommandQueue(command_queue)); |
| 353 | + CL_CHECK(clReleaseContext(context)); |
| 354 | +
|
| 355 | + CL_CHECK(clReleaseMemObject(bufferA)); |
| 356 | + CL_CHECK(clReleaseMemObject(bufferB)); |
| 357 | + CL_CHECK(clReleaseMemObject(bufferC)); |
| 358 | +
|
| 359 | + return 0; |
| 360 | + } |
| 361 | +---- |
| 362 | + |
| 363 | +=== Conformance tests |
| 364 | + |
| 365 | +TODO - OpenCL-CTS Github issue with CTS plan once API design has been agreed. |
| 366 | + |
0 commit comments