From b61190bac4d5f8c4f21a028ab11c7adcfca2421b Mon Sep 17 00:00:00 2001 From: Ewan Crawford Date: Fri, 11 Jul 2025 13:24:40 +0100 Subject: [PATCH 1/5] Redefine command-buffer simultaneous-use As discussed in https://github.com/KhronosGroup/OpenCL-Docs/issues/891 the current definition of [simultaneous use](https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_API.html#_command_buffers) is hard for users to reason about. Instead a better model is one simultaneous-use isn't a contraint of the command-buffer submission, but it's execution. That is simultaneous-use occurs when a command-buffer is enqueued for execution while any previous submission of the command-buffer is still in-flight, and there any no scheduling dependencies expressed to serialize execution. This means that pipelined submissions of a command-buffer, where there is an in-order queue, barrier, or cl_events to serialize execution, is always valid usage without this optional simultaneous-use device feature. To avoid the runtime having to incur overheads from monitoring when simultaneous-use occurs so it can throw an error, violating this valid usage for non simultaneous-use command-buffers is UB. Following from this related to https://github.com/KhronosGroup/OpenCL-Docs/issues/1311 the pending state has also been removed from the command-buffer lifecycle, and there is only the binary states of recording and executable. This is because a user can use the existing OpenCL mechanisms of host waits and event queries to inspect the state of individual command-buffer enqueues to avoid simultaneous-use, and having this stored as a command-buffer state incurs the runtime overhead of tracking a previous submissions. The pending count concept also now makes less sense. The implications for updating a command-buffer is that the error behavior is removed from update, so simultaneous-use is a property of execution rather than enqueue. See CTS test ideas for how this could work. I think the CTS changes that are required for this as follows, but I could create a separate CTS issue to track work once/if this PR merge. Or we could try prototype the CTS changes to give confidence in the spec change. * Remove test for pending state query * Either rework existing simulataneous use tests so that it tests the new definition, or delete them and create new more suitable tests without tech-debt from old definition. * Add tests for pipelined submission of a command-buffer not created with simultaneous-use. Ideally stressing indriect dependencies as well as direct ones: ** in-order queue to express depdencies ** out-of-order queue with event dependencies to express depenencies ** barrier to express for dependencies * Add cl_khr_command_buffer_mutable_dispatch tests for updating and enqueueing pipelined submissions of a non-simultaneous use command-buffer with depdencies between each enqueue, and only do a blocking wait at the end. * Add cl_khr_command_buffer_mutable_dispatch tests for a simultaneous-use command-buffer, where two invocations are scheduled such that they can run concurrently, but the second invocation is updated such that it uses different inputs/outputs to avoid race conditions in the kernel. --- api/cl_khr_command_buffer.asciidoc | 23 ++++--- api/opencl_runtime_layer.asciidoc | 93 ++++++++++++----------------- images/commandbuffer_lifecycle.png | Bin 38610 -> 20835 bytes xml/cl.xml | 4 +- 4 files changed, 54 insertions(+), 66 deletions(-) diff --git a/api/cl_khr_command_buffer.asciidoc b/api/cl_khr_command_buffer.asciidoc index 7ba41289e..5cf67ea48 100644 --- a/api/cl_khr_command_buffer.asciidoc +++ b/api/cl_khr_command_buffer.asciidoc @@ -4,7 +4,7 @@ include::{generated}/meta/{refprefix}cl_khr_command_buffer.txt[] // *Revision*:: -// 0.9.6 +// 0.9.7 // *Extension and Version Dependencies*:: // This extension requires OpenCL 1.2 or later. // Buffering of SVM commands requires OpenCL 2.0 or later. @@ -12,7 +12,7 @@ include::{generated}/meta/{refprefix}cl_khr_command_buffer.txt[] === Other Extension Metadata *Last Modified Date*:: - 2024-12-13 + 2025-07-10 *IP Status*:: No known IP claims. *Contributors*:: @@ -126,11 +126,16 @@ from the sync-point values returned is implementation defined. ==== Simultaneous Use -The optional simultaneous use capability was added to the extension so that -vendors can support pipelined workflows, where command-buffers are repeatedly -enqueued without blocking in user code. However, simultaneous use may result in -command-buffers being more expensive to enqueue than in a sequential model, so -the capability is optional to enable optimizations on command-buffer recording. +The optional <> capability was added to the +extension so that vendors could support concurrent execution of the same +command-buffer. However, simultaneous use may result in command-buffers having +a larger overhead to implement, so the capability is optional to enable +optimizations when this usage isn't required by a user. + +Instead the goal for the base level of functionality provided by the extension +is to support pipelined workflows. Where a command-buffer is repeatedly +enqueued, with each enqueue expressing dependencies on any previous submissions, +without the enqueue calls blocking in user code. === Interactions With Other Extensions @@ -257,7 +262,6 @@ features: * {cl_command_buffer_state_khr_TYPE} ** {CL_COMMAND_BUFFER_STATE_RECORDING_KHR} ** {CL_COMMAND_BUFFER_STATE_EXECUTABLE_KHR} - ** {CL_COMMAND_BUFFER_STATE_PENDING_KHR} * {cl_command_type_TYPE} ** {CL_COMMAND_COMMAND_BUFFER_KHR} * New Error Codes @@ -470,3 +474,6 @@ features: * 0.9.7, 2024-12-13 ** Refactor queue compatability between command-buffer creation and enqueue (experimental). + * 0.9.8, 2025-07-10 + ** Rework simultaneous use definition and remove pending state + (experimental). diff --git a/api/opencl_runtime_layer.asciidoc b/api/opencl_runtime_layer.asciidoc index e2b0406d3..cf073e2f6 100644 --- a/api/opencl_runtime_layer.asciidoc +++ b/api/opencl_runtime_layer.asciidoc @@ -14618,13 +14618,14 @@ on one or more command-queues without any application code interaction. Grouping the operations together allows efficient enqueuing of repetitive operations, as well as enabling driver optimizations. -Command-buffers are _sequential use_ by default, but may also be set to -_simultaneous use_ on creation if the device optionally supports this -capability. -A sequential use command-buffer must have a <> -of 0 or 1. -The simultaneous use capability removes this restriction and allows -command-buffers to have a <> greater than 1. +Upon creation a command-buffer is defined as being in the <> state, in order for the command-buffer to be enqueued +it must first be finalized using {clFinalizeCommandBufferKHR} after which no +further commands can be recorded. A command-buffer is submitted for execution +on command-queues with a call to {clEnqueueCommandBufferKHR}. It is +always valid to call {clEnqueueCommandBufferKHR} with a command-buffer that +has previously been enqueued, provided the call doesn't violate the definition +of <>. Command-buffers are created using an ordered list of command-queues that commands are recorded to and execute on by default. All these queue objects @@ -14690,6 +14691,24 @@ If using layered extension {cl_khr_command_buffer_mutable_dispatch_EXT}, usage>>. ==== +Simultaneous use is defined using the _prerequisite_ terminology from the +<<_execution_model, execution model>>, and is an optional feature for devices +to support concurrent executions of a command-buffer. A command-buffer must +be created with {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} to avoid undefined +behavior if a simultaneous use usage pattern occurs. + +[[simultaneous-use]] +Simultaneous Use:: When a command-buffer is submitted for +execution without a prerequisite on all the previous submissions of the same +command-buffer which are not in the {CL_COMPLETE} state. + +An example of simultaneous use would be two submissions of the same +command-buffer to a single out-of-order queue, without any events or barriers +used to express a dependency between the two enqueue calls. Using a single +in-order queue, events, or barriers to express dependencies between submissions +of the same command-buffer would each be ways to avoid simultaneous use and are +valid usage of command-buffers created without the +{CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} flag. ifdef::cl_khr_command_buffer_multi_device[] === Command-Buffers and Multiple Devices @@ -14733,7 +14752,9 @@ endif::cl_khr_command_buffer_multi_device[] === Command-Buffer Lifecycle -A command-buffer is always in one of the following states: +A command-buffer is created in the recording state and transitions to the +executable state when finalized, at which point it cannot move back to +the recording state. [[recording]] Recording:: Initial state of a command-buffer on creation, where commands can be @@ -14743,11 +14764,6 @@ recorded to the command-buffer. Executable:: State after command recording has finished with {clFinalizeCommandBufferKHR} and the command-buffer may be enqueued. -[[pending]] -Pending:: Once a command-buffer has been enqueued to a command-queue it enters -the Pending state until completion, at which point it moves back to the -<> state. - // Image generated from the following mermaid diagram description using https://mermaid.live // Ideally we'd use the asciidoctor-diagram extension to generate the rendered diagram, but // there are issues installing the gem with ruby 2.3.3 @@ -14757,21 +14773,10 @@ the Pending state until completion, at which point it moves back to the // stateDiagram-v2 // [*] --> Recording: Create // Recording -->Executable: Finalize -// Executable --> Pending: Enqueue -// Pending --> Executable: Completion // .... image::images/commandbuffer_lifecycle.png[align="center", title="Lifecycle of a command-buffer."] -[[pending_count]] -The Pending Count is the number of copies of the command -buffer in the <> state. -By default a command-buffer's Pending Count must be 0 or 1. -If the command-buffer was created with -{CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} then the command-buffer may have a -Pending Count greater than 1. - - === Creating Command-Buffer Objects [open,refpage='clCreateCommandBufferKHR',desc='Create a command-buffer',type='protos'] @@ -14813,9 +14818,9 @@ include::{generated}/api/version-notes/CL_COMMAND_BUFFER_FLAGS_KHR.asciidoc[] | This is a bitfield and can be set to a combination of the following values: {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR_anchor} - Allow multiple - instances of the command-buffer to be submitted to the device for - execution. - If set, devices must support + instances of the command-buffer to be scheduled for execution on the + device in a usage pattern that exhibits <>. If set, devices must support {CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR}. include::{generated}/api/version-notes/CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR.asciidoc[] @@ -14898,16 +14903,6 @@ ifdef::cl_khr_command_buffer_multi_device[] |==== endif::cl_khr_command_buffer_multi_device[] -[NOTE] -==== -Upon creation the command-buffer is defined as being in the -<> state, in order for the command-buffer to be enqueued -it must first be finalized using {clFinalizeCommandBufferKHR} after which no -further commands can be recorded. -A command-buffer is submitted for execution on command-queues with a call to -{clEnqueueCommandBufferKHR}. -==== - // refError {clCreateCommandBufferKHR} returns a valid non-zero command-buffer and @@ -15089,9 +15084,6 @@ execution was successfully queued, or one of the errors below: * {CL_INVALID_COMMAND_BUFFER_KHR} if _command_buffer_ is not a valid command-buffer. * {CL_INVALID_OPERATION} if _command_buffer_ has not been finalized. - * {CL_INVALID_OPERATION} if _command_buffer_ was not created with the - {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} flag and is in the <> state. * {CL_INVALID_VALUE} if _queues_ is `NULL` and _num_queues_ is > 0, or _queues_ is not `NULL` and _num_queues_ is 0. * {CL_INVALID_VALUE} if _num_queues_ is > 0 and not the same value as @@ -15125,6 +15117,10 @@ execution was successfully queued, or one of the errors below: required by the OpenCL implementation on the host. -- +Calling {clEnqueueCommandBufferKHR} in a usage pattern that exhbits +<> when _command_buffer_ was not created +with the {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} flag results in undefined +behavior. === Recording Commands to a Command-Buffer @@ -16553,8 +16549,7 @@ include::{generated}/api/version-notes/clRemapCommandBufferKHR.asciidoc[] * _errcode_ret_ returns an appropriate error code. If _errcode_ret_ is `NULL`, no error code is returned. -The returned command-buffer has the same state as the input command-buffer, -unless the input command-buffer is in the <> state, in +The returned command-buffer has the same state as the input command-buffer. which case the returned command-buffer has state <>. // refError @@ -16682,10 +16677,6 @@ one of the errors below is returned: * {CL_OUT_OF_HOST_MEMORY} if there is a failure to allocate resources required by the OpenCL implementation on the host. -Using this function when _command_buffer_ is in the <> -state and not created with the {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} flag -causes undefined behavior. - [NOTE] ==== Performant usage is to call {clUpdateMutableCommandsKHR} only when the @@ -16903,18 +16894,10 @@ include::{generated}/api/version-notes/CL_COMMAND_BUFFER_STATE_KHR.asciidoc[] include::{generated}/api/version-notes/CL_COMMAND_BUFFER_STATE_RECORDING_KHR.asciidoc[] {CL_COMMAND_BUFFER_STATE_EXECUTABLE_KHR_anchor} is returned when - _command_buffer_ has been finalized and there is not a <> instance of _command_buffer_ awaiting completion on a - command_queue. + _command_buffer_ has been finalized. include::{generated}/api/version-notes/CL_COMMAND_BUFFER_STATE_EXECUTABLE_KHR.asciidoc[] - {CL_COMMAND_BUFFER_STATE_PENDING_KHR_anchor} is returned when an - instance of _command_buffer_ has been enqueued for execution but not - yet completed. - -include::{generated}/api/version-notes/CL_COMMAND_BUFFER_STATE_PENDING_KHR.asciidoc[] - | {CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR_anchor} include::{generated}/api/version-notes/CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR.asciidoc[] diff --git a/images/commandbuffer_lifecycle.png b/images/commandbuffer_lifecycle.png index 12867c8045db47fc9f0e52bfbac4e2f2b265839d..8d82abdf1bc38a48dc0b2790a58537e30b1ab82d 100644 GIT binary patch literal 20835 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 diff --git a/xml/cl.xml b/xml/cl.xml index a68baafc7..1cf22ecd1 100644 --- a/xml/cl.xml +++ b/xml/cl.xml @@ -1371,7 +1371,6 @@ server's OpenCL/api-docs repository. - @@ -7324,7 +7323,7 @@ server's OpenCL/api-docs repository. - + @@ -7371,7 +7370,6 @@ server's OpenCL/api-docs repository. - From e45df2eca792c23a0fb83ae129d52baa7812604e Mon Sep 17 00:00:00 2001 From: Ewan Crawford Date: Mon, 4 Aug 2025 14:40:21 +0100 Subject: [PATCH 2/5] Address editorial PR feedback --- api/cl_khr_command_buffer.asciidoc | 7 ------- api/opencl_runtime_layer.asciidoc | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/api/cl_khr_command_buffer.asciidoc b/api/cl_khr_command_buffer.asciidoc index 5cf67ea48..1f7a12a67 100644 --- a/api/cl_khr_command_buffer.asciidoc +++ b/api/cl_khr_command_buffer.asciidoc @@ -3,8 +3,6 @@ include::{generated}/meta/{refprefix}cl_khr_command_buffer.txt[] -// *Revision*:: -// 0.9.7 // *Extension and Version Dependencies*:: // This extension requires OpenCL 1.2 or later. // Buffering of SVM commands requires OpenCL 2.0 or later. @@ -132,11 +130,6 @@ command-buffer. However, simultaneous use may result in command-buffers having a larger overhead to implement, so the capability is optional to enable optimizations when this usage isn't required by a user. -Instead the goal for the base level of functionality provided by the extension -is to support pipelined workflows. Where a command-buffer is repeatedly -enqueued, with each enqueue expressing dependencies on any previous submissions, -without the enqueue calls blocking in user code. - === Interactions With Other Extensions The introduction of the command-buffer abstraction enables functionality diff --git a/api/opencl_runtime_layer.asciidoc b/api/opencl_runtime_layer.asciidoc index cf073e2f6..ebf6ee7e0 100644 --- a/api/opencl_runtime_layer.asciidoc +++ b/api/opencl_runtime_layer.asciidoc @@ -14618,14 +14618,14 @@ on one or more command-queues without any application code interaction. Grouping the operations together allows efficient enqueuing of repetitive operations, as well as enabling driver optimizations. -Upon creation a command-buffer is defined as being in the <> state, in order for the command-buffer to be enqueued -it must first be finalized using {clFinalizeCommandBufferKHR} after which no -further commands can be recorded. A command-buffer is submitted for execution -on command-queues with a call to {clEnqueueCommandBufferKHR}. It is -always valid to call {clEnqueueCommandBufferKHR} with a command-buffer that -has previously been enqueued, provided the call doesn't violate the definition -of <>. +Upon creation a command-buffer is in the <> state. In +order for the command-buffer to be enqueued it must first be finalized using +{clFinalizeCommandBufferKHR}, after which no further commands can be recorded. +A command-buffer is enqueued for execution on command-queues with a call to +{clEnqueueCommandBufferKHR}. It is always valid to call +{clEnqueueCommandBufferKHR} with a command-buffer that has previously been +enqueued, provided the call doesn't violate the definition of +<>. Command-buffers are created using an ordered list of command-queues that commands are recorded to and execute on by default. All these queue objects @@ -14702,6 +14702,8 @@ Simultaneous Use:: When a command-buffer is submitted for execution without a prerequisite on all the previous submissions of the same command-buffer which are not in the {CL_COMPLETE} state. +[NOTE] +==== An example of simultaneous use would be two submissions of the same command-buffer to a single out-of-order queue, without any events or barriers used to express a dependency between the two enqueue calls. Using a single @@ -14709,6 +14711,7 @@ in-order queue, events, or barriers to express dependencies between submissions of the same command-buffer would each be ways to avoid simultaneous use and are valid usage of command-buffers created without the {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} flag. +==== ifdef::cl_khr_command_buffer_multi_device[] === Command-Buffers and Multiple Devices From 507374105d7d406b9a49a7836f0b8b5aef296287 Mon Sep 17 00:00:00 2001 From: Ewan Crawford Date: Thu, 7 Aug 2025 11:42:03 +0100 Subject: [PATCH 3/5] Address QC editoral feedback --- api/opencl_platform_layer.asciidoc | 4 ++-- api/opencl_runtime_layer.asciidoc | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/api/opencl_platform_layer.asciidoc b/api/opencl_platform_layer.asciidoc index 0108c87b9..389513156 100644 --- a/api/opencl_platform_layer.asciidoc +++ b/api/opencl_platform_layer.asciidoc @@ -1791,8 +1791,8 @@ include::{generated}/api/version-notes/CL_COMMAND_BUFFER_CAPABILITY_KERNEL_PRINT include::{generated}/api/version-notes/CL_COMMAND_BUFFER_CAPABILITY_DEVICE_SIDE_ENQUEUE_KHR.asciidoc[] {CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR_anchor} Device - supports the command-buffers having a <> that exceeds 1. + supports enqueueing command-buffers with a <> usage pattern. include::{generated}/api/version-notes/CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR.asciidoc[] diff --git a/api/opencl_runtime_layer.asciidoc b/api/opencl_runtime_layer.asciidoc index ebf6ee7e0..d11f4eb01 100644 --- a/api/opencl_runtime_layer.asciidoc +++ b/api/opencl_runtime_layer.asciidoc @@ -16553,7 +16553,6 @@ include::{generated}/api/version-notes/clRemapCommandBufferKHR.asciidoc[] If _errcode_ret_ is `NULL`, no error code is returned. The returned command-buffer has the same state as the input command-buffer. -which case the returned command-buffer has state <>. // refError From 650ba7e1a42dfe3c3ad0d461beac5413b3f0cc45 Mon Sep 17 00:00:00 2001 From: Ewan Crawford Date: Fri, 8 Aug 2025 12:56:08 +0100 Subject: [PATCH 4/5] Move simultaneous-use optional feature to mutable-dispatch --- api/cl_khr_command_buffer.asciidoc | 11 -------- ...r_command_buffer_mutable_dispatch.asciidoc | 18 +++++++++++- api/opencl_platform_layer.asciidoc | 2 ++ api/opencl_runtime_layer.asciidoc | 28 ++++++++++++++----- xml/cl.xml | 12 ++++---- 5 files changed, 47 insertions(+), 24 deletions(-) diff --git a/api/cl_khr_command_buffer.asciidoc b/api/cl_khr_command_buffer.asciidoc index 1f7a12a67..0c80a4d4f 100644 --- a/api/cl_khr_command_buffer.asciidoc +++ b/api/cl_khr_command_buffer.asciidoc @@ -122,14 +122,6 @@ There are no gurantees made around the values of sync-points returned from adding commands to a command-buffer. Any semantics that a could be inferred from the sync-point values returned is implementation defined. -==== Simultaneous Use - -The optional <> capability was added to the -extension so that vendors could support concurrent execution of the same -command-buffer. However, simultaneous use may result in command-buffers having -a larger overhead to implement, so the capability is optional to enable -optimizations when this usage isn't required by a user. - === Interactions With Other Extensions The introduction of the command-buffer abstraction enables functionality @@ -240,11 +232,8 @@ features: * {cl_device_command_buffer_capabilities_khr_TYPE} ** {CL_COMMAND_BUFFER_CAPABILITY_KERNEL_PRINTF_KHR} ** {CL_COMMAND_BUFFER_CAPABILITY_DEVICE_SIDE_ENQUEUE_KHR} - ** {CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR} * {cl_command_buffer_properties_khr_TYPE} ** {CL_COMMAND_BUFFER_FLAGS_KHR} - * {cl_command_buffer_flags_khr_TYPE} - ** {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} * {cl_command_buffer_info_khr_TYPE} ** {CL_COMMAND_BUFFER_QUEUES_KHR} ** {CL_COMMAND_BUFFER_NUM_QUEUES_KHR} diff --git a/api/cl_khr_command_buffer_mutable_dispatch.asciidoc b/api/cl_khr_command_buffer_mutable_dispatch.asciidoc index 5287ddcf7..1ef08b76e 100644 --- a/api/cl_khr_command_buffer_mutable_dispatch.asciidoc +++ b/api/cl_khr_command_buffer_mutable_dispatch.asciidoc @@ -6,7 +6,7 @@ include::{generated}/meta/{refprefix}cl_khr_command_buffer_mutable_dispatch.txt[ === Other Extension Metadata *Last Modified Date*:: - 2024-09-05 + 2025-08-08 *IP Status*:: No known IP claims. *Contributors*:: @@ -41,6 +41,15 @@ This allows inputs and outputs to the kernel, as well as work-item sizes and offsets, to change without having to re-record the entire command sequence in a new command-buffer. +==== Simultaneous Use + +The optional <> capability was added to the +extension so that vendors could support concurrent execution of the same +command-buffer object which has been updated between submissions. However, +simultaneous use may result in command-buffers having a larger overhead to +implement, so the capability is optional to enable optimizations when this +usage isn't required by a user. + === Interactions With Other Extensions The {clUpdateMutableCommandsKHR} entry-point has been designed for the purpose @@ -72,6 +81,8 @@ void pointer using {cl_command_buffer_update_type_khr_TYPE}. * {cl_device_info_TYPE} ** {CL_DEVICE_MUTABLE_DISPATCH_CAPABILITIES_KHR} + * {cl_device_command_buffer_capabilities_khr_TYPE} + ** {CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR} * {cl_command_properties_khr_TYPE} ** {CL_MUTABLE_DISPATCH_ASSERTS_KHR} ** {CL_MUTABLE_DISPATCH_UPDATABLE_FIELDS_KHR} @@ -95,6 +106,7 @@ void pointer using {cl_command_buffer_update_type_khr_TYPE}. ** {CL_MUTABLE_COMMAND_COMMAND_TYPE_KHR} * {cl_command_buffer_flags_khr_TYPE} ** {CL_COMMAND_BUFFER_MUTABLE_KHR} + ** {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} * {cl_command_buffer_properties_khr_TYPE} ** {CL_COMMAND_BUFFER_MUTABLE_DISPATCH_ASSERTS_KHR} * {cl_command_buffer_update_type_khr_TYPE} @@ -363,3 +375,7 @@ may be a introduced as a stand alone extension. * Revision 0.9.3, 2024-09-05 ** Rename `CL_MUTABLE_DISPATCH_PROPERTIES_ARRAY_KHR` to `CL_MUTABLE_COMMAND_PROPERTIES_ARRAY_KHR` (experimental). + * Revision 0.9.4, 2025-08-08 + ** Move `CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR` and + `CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR` in this + extension from the base extension (experimental). diff --git a/api/opencl_platform_layer.asciidoc b/api/opencl_platform_layer.asciidoc index 389513156..4072045eb 100644 --- a/api/opencl_platform_layer.asciidoc +++ b/api/opencl_platform_layer.asciidoc @@ -1790,11 +1790,13 @@ include::{generated}/api/version-notes/CL_COMMAND_BUFFER_CAPABILITY_KERNEL_PRINT include::{generated}/api/version-notes/CL_COMMAND_BUFFER_CAPABILITY_DEVICE_SIDE_ENQUEUE_KHR.asciidoc[] +ifdef::cl_khr_command_buffer_mutable_dispatch[] {CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR_anchor} Device supports enqueueing command-buffers with a <> usage pattern. include::{generated}/api/version-notes/CL_COMMAND_BUFFER_CAPABILITY_SIMULTANEOUS_USE_KHR.asciidoc[] +endif::cl_khr_command_buffer_mutable_dispatch[] ifdef::cl_khr_command_buffer_multi_device[] {CL_COMMAND_BUFFER_CAPABILITY_MULTIPLE_QUEUE_KHR_anchor} Device diff --git a/api/opencl_runtime_layer.asciidoc b/api/opencl_runtime_layer.asciidoc index d11f4eb01..a8cfeddfd 100644 --- a/api/opencl_runtime_layer.asciidoc +++ b/api/opencl_runtime_layer.asciidoc @@ -14692,10 +14692,17 @@ usage>>. ==== Simultaneous use is defined using the _prerequisite_ terminology from the -<<_execution_model, execution model>>, and is an optional feature for devices -to support concurrent executions of a command-buffer. A command-buffer must -be created with {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} to avoid undefined -behavior if a simultaneous use usage pattern occurs. +<<_execution_model, execution model>>. +ifndef::cl_khr_command_buffer_multi_device[] +A command-buffer exhibits undefined behavior if a simultaneous use usage +pattern occurs. +endif::cl_khr_command_buffer_multi_device[] +ifdef::cl_khr_command_buffer_multi_device[] +Simultaneous use is an optional feature for devices to support concurrent +executions of a command-buffer which have been updated between submissions. +A command-buffer must be created with {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} +to avoid undefined behavior if a simultaneous use usage pattern occurs. +endif::cl_khr_command_buffer_multi_device[] [[simultaneous-use]] Simultaneous Use:: When a command-buffer is submitted for @@ -14708,9 +14715,7 @@ An example of simultaneous use would be two submissions of the same command-buffer to a single out-of-order queue, without any events or barriers used to express a dependency between the two enqueue calls. Using a single in-order queue, events, or barriers to express dependencies between submissions -of the same command-buffer would each be ways to avoid simultaneous use and are -valid usage of command-buffers created without the -{CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} flag. +of the same command-buffer would each be ways to avoid simultaneous use. ==== ifdef::cl_khr_command_buffer_multi_device[] @@ -14820,6 +14825,7 @@ include::{generated}/api/version-notes/CL_COMMAND_BUFFER_FLAGS_KHR.asciidoc[] | {cl_command_buffer_flags_khr_TYPE} | This is a bitfield and can be set to a combination of the following values: +ifdef::cl_khr_command_buffer_mutable_dispatch[] {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR_anchor} - Allow multiple instances of the command-buffer to be scheduled for execution on the device in a usage pattern that exhibits <> results in undefined behavior. +endif::cl_khr_command_buffer_mutable_dispatch[] + +ifdef::cl_khr_command_buffer_mutable_dispatch[] Calling {clEnqueueCommandBufferKHR} in a usage pattern that exhbits <> when _command_buffer_ was not created with the {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} flag results in undefined behavior. +endif::cl_khr_command_buffer_mutable_dispatch[] === Recording Commands to a Command-Buffer diff --git a/xml/cl.xml b/xml/cl.xml index 1cf22ecd1..d8c286a14 100644 --- a/xml/cl.xml +++ b/xml/cl.xml @@ -7346,14 +7346,10 @@ server's OpenCL/api-docs repository. - - - - @@ -7469,7 +7465,7 @@ server's OpenCL/api-docs repository. - + @@ -7483,8 +7479,14 @@ server's OpenCL/api-docs repository. + + + + + + From d8f52a38c054a4f8b5bc8d08aec1f7a572a4bb6d Mon Sep 17 00:00:00 2001 From: Ewan Crawford Date: Mon, 11 Aug 2025 14:57:46 +0100 Subject: [PATCH 5/5] Don't use phrase "simultaneous use usage" --- api/opencl_runtime_layer.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/opencl_runtime_layer.asciidoc b/api/opencl_runtime_layer.asciidoc index a8cfeddfd..a28c4b7f8 100644 --- a/api/opencl_runtime_layer.asciidoc +++ b/api/opencl_runtime_layer.asciidoc @@ -14694,14 +14694,14 @@ usage>>. Simultaneous use is defined using the _prerequisite_ terminology from the <<_execution_model, execution model>>. ifndef::cl_khr_command_buffer_multi_device[] -A command-buffer exhibits undefined behavior if a simultaneous use usage +A command-buffer exhibits undefined behavior if a simultaneous use pattern occurs. endif::cl_khr_command_buffer_multi_device[] ifdef::cl_khr_command_buffer_multi_device[] Simultaneous use is an optional feature for devices to support concurrent executions of a command-buffer which have been updated between submissions. A command-buffer must be created with {CL_COMMAND_BUFFER_SIMULTANEOUS_USE_KHR} -to avoid undefined behavior if a simultaneous use usage pattern occurs. +to avoid undefined behavior if a simultaneous use pattern occurs. endif::cl_khr_command_buffer_multi_device[] [[simultaneous-use]]