| // Copyright (c) 2015-2018 Khronos Group. This work is licensed under a |
| // Creative Commons Attribution 4.0 International License; see |
| // http://creativecommons.org/licenses/by/4.0/ |
| |
| [[synchronization]] |
| = Synchronization and Cache Control |
| |
| Synchronization of access to resources is primarily the responsibility of |
| the application in Vulkan. |
| The order of execution of commands with respect to the host and other |
| commands on the device has few implicit guarantees, and needs to be |
| explicitly specified. |
| Memory caches and other optimizations are also explicitly managed, requiring |
| that the flow of data through the system is largely under application |
| control. |
| |
| Whilst some implicit guarantees exist between commands, five explicit |
| synchronization mechanisms are exposed by Vulkan: |
| |
| <<synchronization-fences,Fences>>:: |
| Fences can: be used to communicate to the host that execution of some |
| task on the device has completed. |
| |
| <<synchronization-semaphores,Semaphores>>:: |
| Semaphores can: be used to control resource access across multiple |
| queues. |
| |
| <<synchronization-events,Events>>:: |
| Events provide a fine-grained synchronization primitive which can: be |
| signaled either within a command buffer or by the host, and can: be |
| waited upon within a command buffer or queried on the host. |
| |
| <<synchronization-pipeline-barriers,Pipeline Barriers>>:: |
| Pipeline barriers also provide synchronization control within a command |
| buffer, but at a single point, rather than with separate signal and wait |
| operations. |
| |
| <<renderpass,Render Passes>>:: |
| Render passes provide a useful synchronization framework for most |
| rendering tasks, built upon the concepts in this chapter. |
| Many cases that would otherwise need an application to use other |
| synchronization primitives can: be expressed more efficiently as part of |
| a render pass. |
| |
| |
| [[synchronization-dependencies]] |
| == Execution and Memory Dependencies |
| |
| An _operation_ is an arbitrary amount of work to be executed on the host, a |
| device, or an external entity such as a presentation engine. |
| Synchronization commands introduce explicit _execution dependencies_, and |
| _memory dependencies_ between two sets of operations defined by the |
| command's two _synchronization scopes_. |
| |
| [[synchronization-dependencies-scopes]] |
| The synchronization scopes define which other operations a synchronization |
| command is able to create execution dependencies with. |
| Any type of operation that is not in a synchronization command's |
| synchronization scopes will not be included in the resulting dependency. |
| For example, for many synchronization commands, the synchronization scopes |
| can: be limited to just operations executing in specific |
| <<synchronization-pipeline-stages,pipeline stages>>, which allows other |
| pipeline stages to be excluded from a dependency. |
| Other scoping options are possible, depending on the particular command. |
| |
| [[synchronization-dependencies-execution]] |
| An _execution dependency_ is a guarantee that for two sets of operations, |
| the first set must: _happen-before_ the second set. |
| If an operation happens-before another operation, then the first operation |
| must: complete before the second operation is initiated. |
| More precisely: |
| |
| * Let *A* and *B* be separate sets of operations. |
| * Let *S* be a synchronization command. |
| * Let *A~S~* and *B~S~* be the synchronization scopes of *S*. |
| * Let *A'* be the intersection of sets *A* and *A~S~*. |
| * Let *B'* be the intersection of sets *B* and *B~S~*. |
| * Submitting *A*, *S* and *B* for execution, in that order, will result in |
| execution dependency *E* between *A'* and *B'*. |
| * Execution dependency *E* guarantees that *A'* happens-before *B'*. |
| |
| [[synchronization-dependencies-chains]] |
| An _execution dependency chain_ is a sequence of execution dependencies that |
| form a happens-before relation between the first dependency's *A'* and the |
| final dependency's *B'*. |
| For each consecutive pair of execution dependencies, a chain exists if the |
| intersection of *B~S~* in the first dependency and *A~S~* in the second |
| dependency is not an empty set. |
| The formation of a single execution dependency from an execution dependency |
| chain can be described by substituting the following in the description of |
| execution dependencies: |
| |
| * Let *S* be a set of synchronization commands that generate an execution |
| dependency chain. |
| * Let *A~S~* be the first synchronization scope of the first command in |
| *S*. |
| * Let *B~S~* be the second synchronization scope of the last command in |
| *S*. |
| |
| [NOTE] |
| .Note |
| ==== |
| An execution dependency is inherently also multiple execution dependencies - |
| a dependency exists between each subset of *A'* and each subset of *B'*, and |
| the same is true for execution dependency chains. |
| For example, a synchronization command with multiple |
| <<synchronization-pipeline-stages,pipeline stages>> in its stage masks |
| effectively generates one dependency between each source stage and each |
| destination stage. |
| This can be useful to think about when considering how execution chains are |
| formed if they do not involve all parts of a synchronization command's |
| dependency. |
| Similarly, any set of adjacent dependencies in an execution dependency chain |
| can: be considered an execution dependency chain in its own right. |
| ==== |
| |
| Execution dependencies alone are not sufficient to guarantee that values |
| resulting from writes in one set of operations can: be read from another set |
| of operations. |
| |
| [[synchronization-dependencies-available-and-visible]] |
| Two additional types of operation are used to control memory access. |
| _Availability operations_ cause the values generated by specified memory |
| write accesses to become _available_ for future access. |
| Any available value remains available until a subsequent write to the same |
| memory location occurs (whether it is made available or not) or the memory |
| is freed. |
| _Visibility operations_ cause any available values to become _visible_ to |
| specified memory accesses. |
| |
| [[synchronization-dependencies-memory]] |
| A _memory dependency_ is an execution dependency which includes availability |
| and visibility operations such that: |
| |
| * The first set of operations happens-before the availability operation. |
| * The availability operation happens-before the visibility operation. |
| * The visibility operation happens-before the second set of operations. |
| |
| Once written values are made visible to a particular type of memory access, |
| they can: be read or written by that type of memory access. |
| Most synchronization commands in Vulkan define a memory dependency. |
| |
| [[synchronization-dependencies-access-scopes]] |
| The specific memory accesses that are made available and visible are defined |
| by the _access scopes_ of a memory dependency. |
| Any type of access that is in a memory dependency's first access scope and |
| occurs in *A'* is made available. |
| Any type of access that is in a memory dependency's second access scope and |
| occurs in *B'* has any available writes made visible to it. |
| Any type of operation that is not in a synchronization command's access |
| scopes will not be included in the resulting dependency. |
| |
| A memory dependency enforces availability and visibility of memory accesses |
| and execution order between two sets of operations. |
| Adding to the description of <<synchronization-dependencies-chains, |
| execution dependency chains>>: |
| |
| * Let *a* be the set of memory accesses performed by *A'*. |
| * Let *b* be the set of memory accesses performed by *B'*. |
| * Let *a~S~* be the first access scope of the first command in *S*. |
| * Let *b~S~* be the second access scope of the last command in *S*. |
| * Let *a'* be the intersection of sets *a* and *a~S~*. |
| * Let *b'* be the intersection of sets *b* and *b~S~*. |
| * Submitting *A*, *S* and *B* for execution, in that order, will result in |
| a memory dependency *m* between *A'* and *B'*. |
| * Memory dependency *m* guarantees that: |
| ** Memory writes in *a'* are made available. |
| ** Available memory writes, including those from *a'*, are made visible to |
| *b'*. |
| |
| [NOTE] |
| .Note |
| ==== |
| Execution and memory dependencies are used to solve data hazards, i.e. to |
| ensure that read and write operations occur in a well-defined order. |
| Write-after-read hazards can be solved with just an execution dependency, |
| but read-after-write and write-after-write hazards need appropriate memory |
| dependencies to be included between them. |
| If an application does not include dependencies to solve these hazards, the |
| results and execution orders of memory accesses are undefined. |
| ==== |
| |
| |
| [[synchronization-image-layout-transitions]] |
| === Image Layout Transitions |
| |
| Image subresources can: be transitioned from one <<resources-image-layouts, |
| layout>> to another as part of a <<synchronization-dependencies-memory, |
| memory dependency>> (e.g. by using an |
| <<synchronization-image-memory-barriers,image memory barrier>>). |
| When a layout transition is specified in a memory dependency, it |
| happens-after the availability operations in the memory dependency, and |
| happens-before the visibility operations. |
| Image layout transitions may: perform read and write accesses on all memory |
| bound to the image subresource range, so applications must: ensure that all |
| memory writes have been made |
| <<synchronization-dependencies-available-and-visible, available>> before a |
| layout transition is executed. |
| Available memory is automatically made visible to a layout transition, and |
| writes performed by a layout transition are automatically made available. |
| |
| Layout transitions always apply to a particular image subresource range, and |
| specify both an old layout and new layout. |
| If the old layout does not match the new layout, a transition occurs. |
| The old layout must: match the current layout of the image subresource |
| range, with one exception. |
| The old layout can: always be specified as ename:VK_IMAGE_LAYOUT_UNDEFINED, |
| though doing so invalidates the contents of the image subresource range. |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| As image layout transitions may: perform read and write accesses on the |
| memory bound to the image, if the image subresource affected by the layout |
| transition is bound to peer memory for any device in the current device mask |
| then the memory heap the bound memory comes from must: support the |
| ename:VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT and |
| ename:VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT capabilities as returned by |
| flink:vkGetDeviceGroupPeerMemoryFeatures. |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| |
| [NOTE] |
| .Note |
| ==== |
| Setting the old layout to ename:VK_IMAGE_LAYOUT_UNDEFINED implies that the |
| contents of the image subresource need not be preserved. |
| Implementations may: use this information to avoid performing expensive data |
| transition operations. |
| ==== |
| |
| [NOTE] |
| .Note |
| ==== |
| Applications must: ensure that layout transitions happen-after all |
| operations accessing the image with the old layout, and happen-before any |
| operations that will access the image with the new layout. |
| Layout transitions are potentially read/write operations, so not defining |
| appropriate memory dependencies to guarantee this will result in a data |
| race. |
| ==== |
| |
| Image layout transitions interact with <<resources-memory-aliasing,memory |
| aliasing>>. |
| |
| |
| [[synchronization-pipeline-stages]] |
| === Pipeline Stages |
| |
| The work performed by an <<fundamentals-queueoperation-command-types, action |
| or synchronization command>> consists of multiple operations, which are |
| performed as a sequence of logically independent steps known as _pipeline |
| stages_. |
| The exact pipeline stages executed depend on the particular command that is |
| used, and current command buffer state when the command was recorded. |
| <<drawing,Drawing commands>>, <<dispatch,dispatching commands>>, |
| <<copies,copy commands>>, <<clears,clear commands>>, and <<synchronization, |
| synchronization commands>> all execute in different sets of |
| <<synchronization-pipeline-stages-types,pipeline stages>>. |
| <<synchronization, Synchronization commands>> do not execute in a defined |
| pipeline, but do execute ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT and |
| ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT. |
| |
| [NOTE] |
| .Note |
| ==== |
| Operations performed by synchronization commands (e.g. |
| <<synchronization-dependencies-available-and-visible, availability and |
| visibility operations>>) are not executed by a defined pipeline stage. |
| However other commands can still synchronize with them via the |
| ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT and |
| ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT pipeline stages. |
| ==== |
| |
| Execution of operations across pipeline stages must: adhere to |
| <<synchronization-implicit, implicit ordering guarantees>>, particularly |
| including <<synchronization-pipeline-stages-order, pipeline stage order>>. |
| Otherwise, execution across pipeline stages may: overlap or execute out of |
| order with regards to other stages, unless otherwise enforced by an |
| execution dependency. |
| |
| [open,refpage='VkPipelineStageFlagBits',desc='Bitmask specifying pipeline stages',type='enums'] |
| -- |
| |
| Several of the synchronization commands include pipeline stage parameters, |
| restricting the <<synchronization-dependencies-scopes, synchronization |
| scopes>> for that command to just those stages. |
| This allows fine grained control over the exact execution dependencies and |
| accesses performed by action commands. |
| Implementations should: use these pipeline stages to avoid unnecessary |
| stalls or cache flushing. |
| |
| Bits which can be set, specifying pipeline stages, are: |
| |
| include::../api/enums/VkPipelineStageFlagBits.txt[] |
| |
| * ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT specifies the stage of the |
| pipeline where any commands are initially received by the queue. |
| * ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT specifies the stage of the |
| pipeline where Draw/DispatchIndirect data structures are consumed. |
| ifdef::VK_NVX_device_generated_commands[] |
| This stage also includes reading commands written by |
| flink:vkCmdProcessCommandsNVX. |
| endif::VK_NVX_device_generated_commands[] |
| * ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT specifies the stage of the |
| pipeline where vertex and index buffers are consumed. |
| * ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT specifies the vertex shader |
| stage. |
| * ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT specifies the |
| tessellation control shader stage. |
| * ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT specifies the |
| tessellation evaluation shader stage. |
| * ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT specifies the geometry |
| shader stage. |
| * ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT specifies the fragment |
| shader stage. |
| * ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT specifies the stage of |
| the pipeline where early fragment tests (depth and stencil tests before |
| fragment shading) are performed. |
| This stage also includes <<renderpass-load-store-ops, subpass load |
| operations>> for framebuffer attachments with a depth/stencil format. |
| * ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT specifies the stage of |
| the pipeline where late fragment tests (depth and stencil tests after |
| fragment shading) are performed. |
| This stage also includes <<renderpass-load-store-ops, subpass store |
| operations>> for framebuffer attachments with a depth/stencil format. |
| * ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT specifies the stage |
| of the pipeline after blending where the final color values are output |
| from the pipeline. |
| This stage also includes <<renderpass-load-store-ops, subpass load and |
| store operations>> and multisample resolve operations for framebuffer |
| attachments with a color format. |
| * ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT specifies the execution of a |
| compute shader. |
| * [[synchronization-pipeline-stages-transfer]] |
| ename:VK_PIPELINE_STAGE_TRANSFER_BIT specifies the execution of copy |
| commands. |
| This includes the operations resulting from all <<copies,copy |
| commands>>, <<clears,clear commands>> (with the exception of |
| flink:vkCmdClearAttachments), and flink:vkCmdCopyQueryPoolResults. |
| * ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT specifies the final stage in |
| the pipeline where operations generated by all commands complete |
| execution. |
| * ename:VK_PIPELINE_STAGE_HOST_BIT specifies a pseudo-stage indicating |
| execution on the host of reads/writes of device memory. |
| This stage is not invoked by any commands recorded in a command buffer. |
| * ename:VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT specifies the execution of all |
| graphics pipeline stages, and is equivalent to the logical OR of: |
| ** ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT |
| ** ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
| ** ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
| ** ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
| ** ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
| ** ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| ** ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
| ** ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| ** ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| ** ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
| ** ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| ** ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT |
| ifdef::VK_EXT_conditional_rendering[] |
| ** ename:VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT |
| endif::VK_EXT_conditional_rendering[] |
| * ename:VK_PIPELINE_STAGE_ALL_COMMANDS_BIT is equivalent to the logical OR |
| of every other pipeline stage flag that is supported on the queue it is |
| used with. |
| ifdef::VK_EXT_conditional_rendering[] |
| * ename:VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT specifies the |
| stage of the pipeline where the predicate of conditional rendering is |
| consumed. |
| endif::VK_EXT_conditional_rendering[] |
| ifdef::VK_NVX_device_generated_commands[] |
| * ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX specifies the stage of |
| the pipeline where device-side generation of commands via |
| flink:vkCmdProcessCommandsNVX is handled. |
| endif::VK_NVX_device_generated_commands[] |
| |
| [NOTE] |
| .Note |
| ==== |
| An execution dependency with only ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT |
| in the destination stage mask will only prevent that stage from executing in |
| subsequently submitted commands. |
| As this stage does not perform any actual execution, this is not observable |
| - in effect, it does not delay processing of subsequent commands. |
| Similarly an execution dependency with only |
| ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage mask will |
| effectively not wait for any prior commands to complete. |
| |
| When defining a memory dependency, using only |
| ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT or |
| ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT would never make any accesses |
| available and/or visible because these stages do not access memory. |
| |
| ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT and |
| ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT are useful for accomplishing layout |
| transitions and queue ownership operations when the required execution |
| dependency is satisfied by other means - for example, semaphore operations |
| between queues. |
| ==== |
| |
| -- |
| |
| [open,refpage='VkPipelineStageFlags',desc='Bitmask of VkPipelineStageFlagBits',type='enums'] |
| -- |
| include::../api/flags/VkPipelineStageFlags.txt[] |
| |
| sname:VkPipelineStageFlags is a bitmask type for setting a mask of zero or |
| more slink:VkPipelineStageFlagBits. |
| -- |
| |
| [[synchronization-pipeline-stages-masks]] |
| If a synchronization command includes a source stage mask, its first |
| <<synchronization-dependencies-scopes, synchronization scope>> only includes |
| execution of the pipeline stages specified in that mask, and its first |
| <<synchronization-dependencies-access-scopes, access scope>> only includes |
| memory access performed by pipeline stages specified in that mask. |
| If a synchronization command includes a destination stage mask, its second |
| <<synchronization-dependencies-scopes, synchronization scope>> only includes |
| execution of the pipeline stages specified in that mask, and its second |
| <<synchronization-dependencies-access-scopes, access scope>> only includes |
| memory access performed by pipeline stages specified in that mask. |
| |
| [NOTE] |
| .Note |
| ==== |
| Including a particular pipeline stage in the first |
| <<synchronization-dependencies-scopes, synchronization scope>> of a command |
| implicitly includes <<synchronization-pipeline-stages-order, logically |
| earlier>> pipeline stages in the synchronization scope. |
| Similarly, the second <<synchronization-dependencies-scopes, synchronization |
| scope>> includes <<synchronization-pipeline-stages-order, logically later>> |
| pipeline stages. |
| |
| However, note that <<synchronization-dependencies-access-scopes, access |
| scopes>> are not affected in this way - only the precise stages specified |
| are considered part of each access scope. |
| ==== |
| |
| Certain pipeline stages are only available on queues that support a |
| particular set of operations. |
| The following table lists, for each pipeline stage flag, which queue |
| capability flag must: be supported by the queue. |
| When multiple flags are enumerated in the second column of the table, it |
| means that the pipeline stage is supported on the queue if it supports any |
| of the listed capability flags. |
| For further details on queue capabilities see |
| <<devsandqueues-physical-device-enumeration,Physical Device Enumeration>> |
| and <<devsandqueues-queues,Queues>>. |
| |
| [[synchronization-pipeline-stages-supported]] |
| .Supported pipeline stage flags |
| [cols="60%,40%",options="header"] |
| |==== |
| |Pipeline stage flag | Required queue capability flag |
| |ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | None required |
| |ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | ename:VK_QUEUE_GRAPHICS_BIT or ename:VK_QUEUE_COMPUTE_BIT |
| |ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | ename:VK_QUEUE_COMPUTE_BIT |
| |ename:VK_PIPELINE_STAGE_TRANSFER_BIT | ename:VK_QUEUE_GRAPHICS_BIT, ename:VK_QUEUE_COMPUTE_BIT or ename:VK_QUEUE_TRANSFER_BIT |
| |ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | None required |
| |ename:VK_PIPELINE_STAGE_HOST_BIT | None required |
| |ename:VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | ename:VK_QUEUE_GRAPHICS_BIT |
| |ename:VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | None required |
| ifdef::VK_EXT_conditional_rendering[] |
| |ename:VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT | ename:VK_QUEUE_GRAPHICS_BIT or ename:VK_QUEUE_COMPUTE_BIT |
| endif::VK_EXT_conditional_rendering[] |
| ifdef::VK_NVX_device_generated_commands[] |
| |ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX | ename:VK_QUEUE_GRAPHICS_BIT or ename:VK_QUEUE_COMPUTE_BIT |
| endif::VK_NVX_device_generated_commands[] |
| |==== |
| |
| [[synchronization-pipeline-stages-order]] |
| Pipeline stages that execute as a result of a command logically complete |
| execution in a specific order, such that completion of a logically later |
| pipeline stage must: not happen-before completion of a logically earlier |
| stage. |
| This means that including any stage in the source stage mask for a |
| particular synchronization command also implies that any logically earlier |
| stages are included in *A~S~* for that command. |
| |
| Similarly, initiation of a logically earlier pipeline stage must: not |
| happen-after initiation of a logically later pipeline stage. |
| Including any given stage in the destination stage mask for a particular |
| synchronization command also implies that any logically later stages are |
| included in *B~S~* for that command. |
| |
| [NOTE] |
| .Note |
| ==== |
| Implementations may: not support synchronization at every pipeline stage for |
| every synchronization operation. |
| If a pipeline stage that an implementation does not support synchronization |
| for appears in a source stage mask, it may: substitute any logically later |
| stage in its place for the first synchronization scope. |
| If a pipeline stage that an implementation does not support synchronization |
| for appears in a destination stage mask, it may: substitute any logically |
| earlier stage in its place for the second synchronization scope. |
| |
| For example, if an implementation is unable to signal an event immediately |
| after vertex shader execution is complete, it may: instead signal the event |
| after color attachment output has completed. |
| |
| If an implementation makes such a substitution, it must: not affect the |
| semantics of execution or memory dependencies or image and buffer memory |
| barriers. |
| ==== |
| |
| [[synchronization-pipeline-stages-types]] |
| The order and set of pipeline stages executed by a given command is |
| determined by the command's pipeline type, as described below: |
| |
| For the graphics pipeline, the following stages occur in this order: |
| |
| * ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT |
| * ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
| * ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
| * ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
| * ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
| * ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| * ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
| * ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| * ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| * ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
| * ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| * ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT |
| |
| For the compute pipeline, the following stages occur in this order: |
| |
| * ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT |
| * ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
| * ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
| * ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT |
| |
| ifdef::VK_EXT_conditional_rendering[] |
| The conditional rendering stage is formally part of both the graphics, and |
| the compute pipeline. |
| The pipeline stage where the predicate read happens has unspecified order |
| relative to other stages of these pipelines: |
| |
| * ename:VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT |
| endif::VK_EXT_conditional_rendering[] |
| |
| For the transfer pipeline, the following stages occur in this order: |
| |
| * ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT |
| * ename:VK_PIPELINE_STAGE_TRANSFER_BIT |
| * ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT |
| |
| For host operations, only one pipeline stage occurs, so no order is |
| guaranteed: |
| |
| * ename:VK_PIPELINE_STAGE_HOST_BIT |
| |
| ifdef::VK_NVX_device_generated_commands[] |
| For the command processing pipeline, the following stages occur in this |
| order: |
| |
| * ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT |
| * ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX |
| * ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT |
| endif::VK_NVX_device_generated_commands[] |
| |
| |
| [[synchronization-access-types]] |
| === Access Types |
| |
| [open,refpage='VkAccessFlagBits',desc='Bitmask specifying memory access types that will participate in a memory dependency',type='enums'] |
| -- |
| |
| Memory in Vulkan can: be accessed from within shader invocations and via |
| some fixed-function stages of the pipeline. |
| The _access type_ is a function of the <<descriptorsets, descriptor type>> |
| used, or how a fixed-function stage accesses memory. |
| Each access type corresponds to a bit flag in slink:VkAccessFlagBits. |
| |
| [[synchronization-access-masks]] |
| Some synchronization commands take sets of access types as parameters to |
| define the <<synchronization-dependencies-access-scopes, access scopes>> of |
| a memory dependency. |
| If a synchronization command includes a source access mask, its first |
| <<synchronization-dependencies-access-scopes, access scope>> only includes |
| accesses via the access types specified in that mask. |
| Similarly, if a synchronization command includes a destination access mask, |
| its second <<synchronization-dependencies-access-scopes, access scope>> only |
| includes accesses via the access types specified in that mask. |
| |
| Access types that can: be set in an access mask include: |
| |
| include::../api/enums/VkAccessFlagBits.txt[] |
| |
| * ename:VK_ACCESS_INDIRECT_COMMAND_READ_BIT specifies read access to an |
| indirect command structure read as part of an indirect drawing or |
| dispatch command. |
| * ename:VK_ACCESS_INDEX_READ_BIT specifies read access to an index buffer |
| as part of an indexed drawing command, bound by |
| flink:vkCmdBindIndexBuffer. |
| * ename:VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT specifies read access to a |
| vertex buffer as part of a drawing command, bound by |
| flink:vkCmdBindVertexBuffers. |
| * ename:VK_ACCESS_UNIFORM_READ_BIT specifies read access to a |
| <<descriptorsets-uniformbuffer, uniform buffer>>. |
| * ename:VK_ACCESS_INPUT_ATTACHMENT_READ_BIT specifies read access to an |
| <<renderpass, input attachment>> within a render pass during fragment |
| shading. |
| * ename:VK_ACCESS_SHADER_READ_BIT specifies read access to a |
| <<descriptorsets-storagebuffer, storage buffer>>, |
| <<descriptorsets-uniformtexelbuffer, uniform texel buffer>>, |
| <<descriptorsets-storagetexelbuffer, storage texel buffer>>, |
| <<descriptorsets-sampledimage, sampled image>>, or |
| <<descriptorsets-storageimage, storage image>>. |
| * ename:VK_ACCESS_SHADER_WRITE_BIT specifies write access to a |
| <<descriptorsets-storagebuffer, storage buffer>>, |
| <<descriptorsets-storagetexelbuffer, storage texel buffer>>, or |
| <<descriptorsets-storageimage, storage image>>. |
| * ename:VK_ACCESS_COLOR_ATTACHMENT_READ_BIT specifies read access to a |
| <<renderpass, color attachment>>, such as via <<framebuffer-blending, |
| blending>>, <<framebuffer-logicop, logic operations>>, or via certain |
| <<renderpass-load-store-ops, subpass load operations>>. |
| ifdef::VK_EXT_blend_operation_advanced[] |
| It does not include <<framebuffer-blend-advanced,advanced blend |
| operations>>. |
| endif::VK_EXT_blend_operation_advanced[] |
| * ename:VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT specifies write access to a |
| <<renderpass, color or resolve attachment>> during a <<renderpass, |
| render pass>> or via certain <<renderpass-load-store-ops, subpass load |
| and store operations>>. |
| * ename:VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT specifies read access |
| to a <<renderpass, depth/stencil attachment>>, via <<fragops-ds-state, |
| depth or stencil operations>> or via certain |
| <<renderpass-load-store-ops, subpass load operations>>. |
| * ename:VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT specifies write |
| access to a <<renderpass, depth/stencil attachment>>, via |
| <<fragops-ds-state, depth or stencil operations>> or via certain |
| <<renderpass-load-store-ops, subpass load and store operations>>. |
| * ename:VK_ACCESS_TRANSFER_READ_BIT specifies read access to an image or |
| buffer in a <<copies, copy>> operation. |
| * ename:VK_ACCESS_TRANSFER_WRITE_BIT specifies write access to an image or |
| buffer in a <<clears, clear>> or <<copies, copy>> operation. |
| * ename:VK_ACCESS_HOST_READ_BIT specifies read access by a host operation. |
| Accesses of this type are not performed through a resource, but directly |
| on memory. |
| * ename:VK_ACCESS_HOST_WRITE_BIT specifies write access by a host |
| operation. |
| Accesses of this type are not performed through a resource, but directly |
| on memory. |
| * ename:VK_ACCESS_MEMORY_READ_BIT specifies read access via non-specific |
| entities. |
| These entities include the Vulkan device and host, but may: also include |
| entities external to the Vulkan device or otherwise not part of the core |
| Vulkan pipeline. |
| When included in a destination access mask, makes all available writes |
| visible to all future read accesses on entities known to the Vulkan |
| device. |
| * ename:VK_ACCESS_MEMORY_WRITE_BIT specifies write access via non-specific |
| entities. |
| These entities include the Vulkan device and host, but may: also include |
| entities external to the Vulkan device or otherwise not part of the core |
| Vulkan pipeline. |
| When included in a source access mask, all writes that are performed by |
| entities known to the Vulkan device are made available. |
| When included in a destination access mask, makes all available writes |
| visible to all future write accesses on entities known to the Vulkan |
| device. |
| ifdef::VK_EXT_conditional_rendering[] |
| * ename:VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT specifies read access |
| to a predicate as part of conditional rendering. |
| endif::VK_EXT_conditional_rendering[] |
| ifdef::VK_NVX_device_generated_commands[] |
| * ename:VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX specifies reads from |
| sname:VkBuffer inputs to flink:vkCmdProcessCommandsNVX. |
| * ename:VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX specifies writes to the |
| target command buffer in flink:vkCmdProcessCommandsNVX. |
| endif::VK_NVX_device_generated_commands[] |
| ifdef::VK_EXT_blend_operation_advanced[] |
| * ename:VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT is similar to |
| ename:VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, but also includes |
| <<framebuffer-blend-advanced,advanced blend operations>>. |
| endif::VK_EXT_blend_operation_advanced[] |
| |
| Certain access types are only performed by a subset of pipeline stages. |
| Any synchronization command that takes both stage masks and access masks |
| uses both to define the <<synchronization-dependencies-access-scopes, access |
| scopes>> - only the specified access types performed by the specified stages |
| are included in the access scope. |
| An application must: not specify an access flag in a synchronization command |
| if it does not include a pipeline stage in the corresponding stage mask that |
| is able to perform accesses of that type. |
| The following table lists, for each access flag, which pipeline stages can: |
| perform that type of access. |
| |
| [[synchronization-access-types-supported]] |
| .Supported access types |
| [cols="50,50",options="header"] |
| |==== |
| |Access flag | Supported pipeline stages |
| |ename:VK_ACCESS_INDIRECT_COMMAND_READ_BIT | ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
| |ename:VK_ACCESS_INDEX_READ_BIT | ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
| |ename:VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
| |ename:VK_ACCESS_UNIFORM_READ_BIT | ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, or ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
| |ename:VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| |ename:VK_ACCESS_SHADER_READ_BIT | ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, or ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
| |ename:VK_ACCESS_SHADER_WRITE_BIT | ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, or ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
| |ename:VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| |ename:VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| |ename:VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, or ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
| |ename:VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, or ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
| |ename:VK_ACCESS_TRANSFER_READ_BIT | ename:VK_PIPELINE_STAGE_TRANSFER_BIT |
| |ename:VK_ACCESS_TRANSFER_WRITE_BIT | ename:VK_PIPELINE_STAGE_TRANSFER_BIT |
| |ename:VK_ACCESS_HOST_READ_BIT | ename:VK_PIPELINE_STAGE_HOST_BIT |
| |ename:VK_ACCESS_HOST_WRITE_BIT | ename:VK_PIPELINE_STAGE_HOST_BIT |
| |ename:VK_ACCESS_MEMORY_READ_BIT | N/A |
| |ename:VK_ACCESS_MEMORY_WRITE_BIT | N/A |
| ifdef::VK_EXT_blend_operation_advanced[] |
| |ename:VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT | ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| endif::VK_EXT_blend_operation_advanced[] |
| ifdef::VK_NVX_device_generated_commands[] |
| |ename:VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX | ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX |
| |ename:VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX | ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX |
| endif::VK_NVX_device_generated_commands[] |
| ifdef::VK_EXT_conditional_rendering[] |
| |ename:VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT | ename:VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT |
| endif::VK_EXT_conditional_rendering[] |
| |==== |
| |
| [[synchronization-host-access-types]] |
| If a memory object does not have the |
| ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT property, then |
| flink:vkFlushMappedMemoryRanges must: be called in order to guarantee that |
| writes to the memory object from the host are made visible to the |
| ename:VK_ACCESS_HOST_WRITE_BIT <<synchronization-access-types, access |
| type>>, where it can: be further made available to the device by |
| <<synchronization, synchronization commands>>. |
| Similarly, flink:vkInvalidateMappedMemoryRanges must: be called to guarantee |
| that writes which are visible to the ename:VK_ACCESS_HOST_READ_BIT |
| <<synchronization-access-types, access type>> are made visible to host |
| operations. |
| |
| If the memory object does have the |
| ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT property flag, writes to the |
| memory object from the host are automatically made visible to the |
| ename:VK_ACCESS_HOST_WRITE_BIT <<synchronization-access-types,access type>>. |
| Similarly, writes made visible to the ename:VK_ACCESS_HOST_READ_BIT |
| <<synchronization-access-types, access type>> are automatically made visible |
| to the host. |
| |
| [NOTE] |
| .Note |
| ==== |
| The flink:vkQueueSubmit command <<synchronization-submission-host-writes, |
| automatically guarantees that host writes flushed to |
| ename:VK_ACCESS_HOST_WRITE_BIT are made available>> if they were flushed |
| before the command executed, so in most cases an explicit memory barrier is |
| not needed for this case. |
| In the few circumstances where a submit does not occur between the host |
| write and the device read access, writes can: be made available by using an |
| explicit memory barrier. |
| ==== |
| |
| -- |
| |
| [open,refpage='VkAccessFlags',desc='Bitmask of VkAccessFlagBits',type='enums'] |
| -- |
| include::../api/flags/VkAccessFlags.txt[] |
| |
| sname:VkAccessFlags is a bitmask type for setting a mask of zero or more |
| slink:VkAccessFlagBits. |
| -- |
| |
| |
| [[synchronization-framebuffer-regions]] |
| === Framebuffer Region Dependencies |
| |
| <<synchronization-pipeline-stages, Pipeline stages>> that operate on, or |
| with respect to, the framebuffer are collectively the _framebuffer-space_ |
| pipeline stages. |
| These stages are: |
| |
| * ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
| * ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
| * ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
| * ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| |
| For these pipeline stages, an execution or memory dependency from the first |
| set of operations to the second set can: either be a single |
| _framebuffer-global_ dependency, or split into multiple _framebuffer-local_ |
| dependencies. |
| A dependency with non-framebuffer-space pipeline stages is neither |
| framebuffer-global nor framebuffer-local. |
| |
| A _framebuffer region_ is a set of sample (x, y, layer, sample) coordinates |
| that is a subset of the entire framebuffer. |
| |
| Both <<synchronization-dependencies-scopes, synchronization scopes>> of a |
| framebuffer-local dependency include only the operations performed within |
| corresponding framebuffer regions (as defined below). |
| No ordering guarantees are made between different framebuffer regions for a |
| framebuffer-local dependency. |
| |
| Both <<synchronization-dependencies-scopes, synchronization scopes>> of a |
| framebuffer-global dependency include operations on all framebuffer-regions. |
| |
| If the first synchronization scope includes operations on pixels/fragments |
| with N samples and the second synchronization scope includes operations on |
| pixels/fragments with M samples, where N does not equal M, then a |
| framebuffer region containing all samples at a given (x, y, layer) |
| coordinate in the first synchronization scope corresponds to a region |
| containing all samples at the same coordinate in the second synchronization |
| scope. |
| In other words, it is a pixel granularity dependency. |
| If N equals M, then a framebuffer region containing a single (x, y, layer, |
| sample) coordinate in the first synchronization scope corresponds to a |
| region containing the same sample at the same coordinate in the second |
| synchronization scope. |
| In other words, it is a sample granularity dependency. |
| |
| [NOTE] |
| .Note |
| ==== |
| Since fragment invocations are not specified to run in any particular |
| groupings, the size of a framebuffer region is implementation-dependent, not |
| known to the application, and must: be assumed to be no larger than |
| specified above. |
| ==== |
| |
| [NOTE] |
| .Note |
| ==== |
| Practically, the pixel vs sample granularity dependency means that if an |
| input attachment has a different number of samples than the pipeline's |
| pname:rasterizationSamples, then a fragment can: access any sample in the |
| input attachment's pixel even if it only uses framebuffer-local |
| dependencies. |
| If the input attachment has the same number of samples, then the fragment |
| can: only access the covered samples in its input code:SampleMask (i.e. the |
| fragment operations happen-after a framebuffer-local dependency for each |
| sample the fragment covers). |
| To access samples that are not covered, a framebuffer-global dependency is |
| required. |
| ==== |
| |
| If a synchronization command includes a pname:dependencyFlags parameter, and |
| specifies the ename:VK_DEPENDENCY_BY_REGION_BIT flag, then it defines |
| framebuffer-local dependencies for the framebuffer-space pipeline stages in |
| that synchronization command, for all framebuffer regions. |
| If no pname:dependencyFlags parameter is included, or the |
| ename:VK_DEPENDENCY_BY_REGION_BIT flag is not specified, then a |
| framebuffer-global dependency is specified for those stages. |
| The ename:VK_DEPENDENCY_BY_REGION_BIT flag does not affect the dependencies |
| between non-framebuffer-space pipeline stages, nor does it affect the |
| dependencies between framebuffer-space and non-framebuffer-space pipeline |
| stages. |
| |
| [NOTE] |
| .Note |
| ==== |
| Framebuffer-local dependencies are more optimal for most architectures; |
| particularly tile-based architectures - which can keep framebuffer-regions |
| entirely in on-chip registers and thus avoid external bandwidth across such |
| a dependency. |
| Including a framebuffer-global dependency in your rendering will usually |
| force all implementations to flush data to memory, or to a higher level |
| cache, breaking any potential locality optimizations. |
| ==== |
| |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| |
| [[synchronization-view-local-dependencies]] |
| === View-Local Dependencies |
| |
| In a render pass instance that has <<renderpass-multiview,multiview>> |
| enabled, dependencies can: be either view-local or view-global. |
| |
| A view-local dependency only includes operations from a single |
| <<renderpass-multiview-view-local,source view>> from the source subpass in |
| the first synchronization scope, and only includes operations from a single |
| <<renderpass-multiview-view-local,destination view>> from the destination |
| subpass in the second synchronization scope. |
| A view-global dependency includes all views in the view mask of the source |
| and destination subpasses in the corresponding synchronization scopes. |
| |
| If a synchronization command includes a pname:dependencyFlags parameter and |
| specifies the ename:VK_DEPENDENCY_VIEW_LOCAL_BIT flag, then it defines |
| view-local dependencies for that synchronization command, for all views. |
| If no pname:dependencyFlags parameter is included or the |
| ename:VK_DEPENDENCY_VIEW_LOCAL_BIT flag is not specified, then a view-global |
| dependency is specified. |
| |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| |
| [[synchronization-device-local-dependencies]] |
| === Device-Local Dependencies |
| |
| Dependencies can: be either device-local or non-device-local. |
| A device-local dependency acts as multiple separate dependencies, one for |
| each physical device that executes the synchronization command, where each |
| dependency only includes operations from that physical device in both |
| synchronization scopes. |
| A non-device-local dependency is a single dependency where both |
| synchronization scopes include operations from all physical devices that |
| participate in the synchronization command. |
| For subpass dependencies, all physical devices in the |
| slink:VkDeviceGroupRenderPassBeginInfo::pname:deviceMask participate in the |
| dependency, and for pipeline barriers all physical devices that are set in |
| the command buffer's current device mask participate in the dependency. |
| |
| If a synchronization command includes a pname:dependencyFlags parameter and |
| specifies the ename:VK_DEPENDENCY_DEVICE_GROUP_BIT flag, then it defines a |
| non-device-local dependency for that synchronization command. |
| If no pname:dependencyFlags parameter is included or the |
| ename:VK_DEPENDENCY_DEVICE_GROUP_BIT flag is not specified, then it defines |
| device-local dependencies for that synchronization command, for all |
| participating physical devices. |
| |
| Semaphore and event dependencies are device-local and only execute on the |
| one physical device that performs the dependency. |
| |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| |
| |
| [[synchronization-implicit]] |
| == Implicit Synchronization Guarantees |
| |
| A small number of implicit ordering guarantees are provided by Vulkan, |
| ensuring that the order in which commands are submitted is meaningful, and |
| avoiding unnecessary complexity in common operations. |
| |
| [[synchronization-submission-order]] |
| _Submission order_ is a fundamental ordering in Vulkan, giving meaning to |
| the order in which <<fundamentals-queueoperation-command-types, action and |
| synchronization commands>> are recorded and submitted to a single queue. |
| Explicit and implicit ordering guarantees between commands in Vulkan all |
| work on the premise that this ordering is meaningful. |
| This order does not itself define any execution or memory dependencies; |
| synchronization commands and other orderings within the API use this |
| ordering to define their scopes. |
| |
| Submission order for any given set of commands is based on the order in |
| which they were recorded to command buffers and then submitted. |
| This order is determined as follows: |
| |
| . The initial order is determined by the order in which |
| flink:vkQueueSubmit commands are executed on the host, for a single |
| queue, from first to last. |
| . The order in which slink:VkSubmitInfo structures are specified in the |
| pname:pSubmits parameter of flink:vkQueueSubmit, from lowest index to |
| highest. |
| . The order in which command buffers are specified in the |
| pname:pCommandBuffers member of slink:VkSubmitInfo, from lowest index to |
| highest. |
| . The order in which commands were recorded to a command buffer on the |
| host, from first to last: |
| ** For commands recorded outside a render pass, this includes all other |
| commands recorded outside a render pass, including |
| flink:vkCmdBeginRenderPass and flink:vkCmdEndRenderPass commands; it |
| does not directly include commands inside a render pass. |
| ** For commands recorded inside a render pass, this includes all other |
| commands recorded inside the same subpass, including the |
| flink:vkCmdBeginRenderPass and flink:vkCmdEndRenderPass commands that |
| delimit the same render pass instance; it does not include commands |
| recorded to other subpasses. |
| |
| <<fundamentals-queueoperation-command-types, Action and synchronization |
| commands>> recorded to a command buffer execute the |
| ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT pipeline stage in |
| <<synchronization-submission-order, submission order>> - forming an implicit |
| execution dependency between this stage in each command. |
| |
| <<fundamentals-queueoperation-command-types, State commands>> do not execute |
| any operations on the device, instead they set the state of the command |
| buffer when they execute on the host, in the order that they are recorded. |
| <<fundamentals-queueoperation-command-types, Action commands>> consume the |
| current state of the command buffer when they are recorded, and will execute |
| state changes on the device as required to match the recorded state. |
| |
| <<queries-order, Query commands>>, <<drawing-primitive-order, the order of |
| primitives passing through the graphics pipeline>> and |
| <<synchronization-image-barrier-layout-transition-order, image layout |
| transitions as part of an image memory barrier>> provide additional |
| guarantees based on submission order. |
| |
| Execution of <<synchronization-pipeline-stages-order, pipeline stages>> |
| within a given command also has a loose ordering, dependent only on a single |
| command. |
| |
| |
| [[synchronization-fences]] |
| == Fences |
| |
| [open,refpage='VkFence',desc='Opaque handle to a fence object',type='handles'] |
| -- |
| |
| Fences are a synchronization primitive that can: be used to insert a |
| dependency from a queue to the host. |
| Fences have two states - signaled and unsignaled. |
| A fence can: be signaled as part of the execution of a |
| <<devsandqueues-submission, queue submission>> command. |
| Fences can: be unsignaled on the host with flink:vkResetFences. |
| Fences can: be waited on by the host with the flink:vkWaitForFences command, |
| and the current state can: be queried with flink:vkGetFenceStatus. |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_fence[] |
| [[synchronization-fences-payloads]] |
| As with most objects in Vulkan, fences are an interface to internal data |
| which is typically opaque to applications. |
| This internal data is referred to as a fence's _payload_. |
| |
| However, in order to enable communication with agents outside of the current |
| device, it is necessary to be able to export that payload to a commonly |
| understood format, and subsequently import from that format as well. |
| |
| The internal data of a fence may: include a reference to any resources and |
| pending work associated with signal or unsignal operations performed on that |
| fence object. |
| Mechanisms to import and export that internal data to and from fences are |
| provided <<VkExportFenceCreateInfo, below>>. |
| These mechanisms indirectly enable applications to share fence state between |
| two or more fences and other synchronization primitives across process and |
| API boundaries. |
| |
| endif::VK_VERSION_1_1,VK_KHR_external_fence[] |
| |
| Fences are represented by sname:VkFence handles: |
| |
| include::../api/handles/VkFence.txt[] |
| |
| -- |
| |
| [open,refpage='vkCreateFence',desc='Create a new fence object',type='protos'] |
| -- |
| |
| To create a fence, call: |
| |
| include::../api/protos/vkCreateFence.txt[] |
| |
| * pname:device is the logical device that creates the fence. |
| * pname:pCreateInfo is a pointer to an instance of the |
| sname:VkFenceCreateInfo structure which contains information about how |
| the fence is to be created. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| * pname:pFence points to a handle in which the resulting fence object is |
| returned. |
| |
| include::../validity/protos/vkCreateFence.txt[] |
| -- |
| |
| [open,refpage='VkFenceCreateInfo',desc='Structure specifying parameters of a newly created fence',type='structs'] |
| -- |
| |
| The sname:VkFenceCreateInfo structure is defined as: |
| |
| include::../api/structs/VkFenceCreateInfo.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:flags is a bitmask of elink:VkFenceCreateFlagBits specifying the |
| initial state and behavior of the fence. |
| |
| include::../validity/structs/VkFenceCreateInfo.txt[] |
| -- |
| |
| [open,refpage='VkFenceCreateFlagBits',desc='Bitmask specifying initial state and behavior of a fence',type='enums'] |
| -- |
| |
| include::../api/enums/VkFenceCreateFlagBits.txt[] |
| |
| * ename:VK_FENCE_CREATE_SIGNALED_BIT specifies that the fence object is |
| created in the signaled state. |
| Otherwise, it is created in the unsignaled state. |
| |
| -- |
| |
| [open,refpage='VkFenceCreateFlags',desc='Bitmask of VkFenceCreateFlagBits',type='enums'] |
| -- |
| include::../api/flags/VkFenceCreateFlags.txt[] |
| |
| sname:VkFenceCreateFlags is a bitmask type for setting a mask of zero or |
| more slink:VkFenceCreateFlagBits. |
| -- |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_fence[] |
| |
| [open,refpage='VkExportFenceCreateInfo',desc='Structure specifying handle types that can be exported from a fence',type='structs'] |
| -- |
| |
| To create a fence whose payload can: be exported to external handles, add |
| the slink:VkExportFenceCreateInfo structure to the pname:pNext chain of the |
| slink:VkFenceCreateInfo structure. |
| The sname:VkExportFenceCreateInfo structure is defined as: |
| |
| include::../api/structs/VkExportFenceCreateInfo.txt[] |
| |
| ifdef::VK_KHR_external_fence[] |
| or the equivalent |
| |
| include::../api/structs/VkExportFenceCreateInfoKHR.txt[] |
| endif::VK_KHR_external_fence[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:handleTypes is a bitmask of |
| elink:VkExternalFenceHandleTypeFlagBits specifying one or more fence |
| handle types the application can: export from the resulting fence. |
| The application can: request multiple handle types for the same fence. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkExportFenceCreateInfo-handleTypes-01446]] |
| The bits in pname:handleTypes must be supported and compatible, as |
| reported by slink:VkExternalFenceProperties. |
| **** |
| |
| include::../validity/structs/VkExportFenceCreateInfo.txt[] |
| -- |
| |
| endif::VK_VERSION_1_1,VK_KHR_external_fence[] |
| |
| ifdef::VK_KHR_external_fence_win32[] |
| |
| [open,refpage='VkExportFenceWin32HandleInfoKHR',desc='Structure specifying additional attributes of Windows handles exported from a fence',type='structs'] |
| -- |
| |
| To specify additional attributes of NT handles exported from a fence, add |
| the slink:VkExportFenceWin32HandleInfoKHR structure to the pname:pNext chain |
| of the slink:VkFenceCreateInfo structure. |
| The sname:VkExportFenceWin32HandleInfoKHR structure is defined as: |
| |
| include::../api/structs/VkExportFenceWin32HandleInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:pAttributes is a pointer to a Windows code:SECURITY_ATTRIBUTES |
| structure specifying security attributes of the handle. |
| * pname:dwAccess is a code:DWORD specifying access rights of the handle. |
| * pname:name is a NULL-terminated UTF-16 string to associate with the |
| underlying synchronization primitive referenced by NT handles exported |
| from the created fence. |
| |
| If this structure is not present, or if pname:pAttributes is set to `NULL`, |
| default security descriptor values will be used, and child processes created |
| by the application will not inherit the handle, as described in the MSDN |
| documentation for "`Synchronization Object Security and Access Rights`"^1^. |
| Further, if the structure is not present, the access rights will be |
| |
| code:DXGI_SHARED_RESOURCE_READ | code:DXGI_SHARED_RESOURCE_WRITE |
| |
| for handles of the following types: |
| |
| ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT |
| |
| 1:: |
| https://msdn.microsoft.com/en-us/library/windows/desktop/ms686670.aspx |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkExportFenceWin32HandleInfoKHR-handleTypes-01447]] |
| If slink:VkExportFenceCreateInfo::pname:handleTypes does not include |
| ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT, |
| sname:VkExportFenceWin32HandleInfoKHR must: not be in the pname:pNext |
| chain of slink:VkFenceCreateInfo. |
| **** |
| |
| include::../validity/structs/VkExportFenceWin32HandleInfoKHR.txt[] |
| -- |
| |
| [open,refpage='vkGetFenceWin32HandleKHR',desc='Get a Windows HANDLE for a fence',type='protos'] |
| -- |
| |
| To export a Windows handle representing the state of a fence, call: |
| |
| include::../api/protos/vkGetFenceWin32HandleKHR.txt[] |
| |
| * pname:device is the logical device that created the fence being |
| exported. |
| * pname:pGetWin32HandleInfo is a pointer to an instance of the |
| slink:VkFenceGetWin32HandleInfoKHR structure containing parameters of |
| the export operation. |
| * pname:pHandle will return the Windows handle representing the fence |
| state. |
| |
| For handle types defined as NT handles, the handles returned by |
| fname:vkGetFenceWin32HandleKHR are owned by the application. |
| To avoid leaking resources, the application must: release ownership of them |
| using the fname:CloseHandle system call when they are no longer needed. |
| |
| Exporting a Windows handle from a fence may: have side effects depending on |
| the transference of the specified handle type, as described in |
| <<synchronization-fences-importing,Importing Fence Payloads>>. |
| |
| include::../validity/protos/vkGetFenceWin32HandleKHR.txt[] |
| -- |
| |
| [open,refpage='VkFenceGetWin32HandleInfoKHR',desc='Structure describing a Win32 handle fence export operation',type='structs'] |
| -- |
| |
| The sname:VkFenceGetWin32HandleInfoKHR structure is defined as: |
| |
| include::../api/structs/VkFenceGetWin32HandleInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:fence is the fence from which state will be exported. |
| * pname:handleType is the type of handle requested. |
| |
| The properties of the handle returned depend on the value of |
| pname:handleType. |
| See elink:VkExternalFenceHandleTypeFlagBits for a description of the |
| properties of the defined external fence handle types. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkFenceGetWin32HandleInfoKHR-handleType-01448]] |
| pname:handleType must: have been included in |
| slink:VkExportFenceCreateInfo::pname:handleTypes when the pname:fence's |
| current payload was created. |
| * [[VUID-VkFenceGetWin32HandleInfoKHR-handleType-01449]] |
| If pname:handleType is defined as an NT handle, |
| flink:vkGetFenceWin32HandleKHR must: be called no more than once for |
| each valid unique combination of pname:fence and pname:handleType. |
| * [[VUID-VkFenceGetWin32HandleInfoKHR-fence-01450]] |
| pname:fence must: not currently have its payload replaced by an imported |
| payload as described below in |
| <<synchronization-fences-importing,Importing Fence Payloads>> unless |
| that imported payload's handle type was included in |
| slink:VkExternalFenceProperties::pname:exportFromImportedHandleTypes for |
| pname:handleType. |
| * [[VUID-VkFenceGetWin32HandleInfoKHR-handleType-01451]] |
| If pname:handleType refers to a handle type with copy payload |
| transference semantics, pname:fence must: be signaled, or have an |
| associated <<synchronization-fences-signaling,fence signal operation>> |
| pending execution. |
| * [[VUID-VkFenceGetWin32HandleInfoKHR-handleType-01452]] |
| pname:handleType must: be defined as an NT handle or a global share |
| handle. |
| **** |
| |
| include::../validity/structs/VkFenceGetWin32HandleInfoKHR.txt[] |
| -- |
| |
| endif::VK_KHR_external_fence_win32[] |
| |
| ifdef::VK_KHR_external_fence_fd[] |
| |
| [open,refpage='vkGetFenceFdKHR',desc='Get a POSIX file descriptor handle for a fence',type='protos'] |
| -- |
| |
| To export a POSIX file descriptor representing the payload of a fence, call: |
| |
| include::../api/protos/vkGetFenceFdKHR.txt[] |
| |
| * pname:device is the logical device that created the fence being |
| exported. |
| * pname:pGetFdInfo is a pointer to an instance of the |
| slink:VkFenceGetFdInfoKHR structure containing parameters of the export |
| operation. |
| * pname:pFd will return the file descriptor representing the fence |
| payload. |
| |
| Each call to fname:vkGetFenceFdKHR must: create a new file descriptor and |
| transfer ownership of it to the application. |
| To avoid leaking resources, the application must: release ownership of the |
| file descriptor when it is no longer needed. |
| |
| [NOTE] |
| .Note |
| ==== |
| Ownership can be released in many ways. |
| For example, the application can call code:close() on the file descriptor, |
| or transfer ownership back to Vulkan by using the file descriptor to import |
| a fence payload. |
| ==== |
| |
| If pname:pGetFdInfo\->pname:handleType is |
| ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT and the fence is signaled at |
| the time fname:vkGetFenceFdKHR is called, pname:pFd may: return the value |
| `-1` instead of a valid file descriptor. |
| |
| Where supported by the operating system, the implementation must: set the |
| file descriptor to be closed automatically when an code:execve system call |
| is made. |
| |
| Exporting a file descriptor from a fence may: have side effects depending on |
| the transference of the specified handle type, as described in |
| <<synchronization-fences-importing,Importing Fence State>>. |
| |
| include::../validity/protos/vkGetFenceFdKHR.txt[] |
| -- |
| |
| [open,refpage='VkFenceGetFdInfoKHR',desc='Structure describing a POSIX FD fence export operation',type='structs'] |
| -- |
| |
| The sname:VkFenceGetFdInfoKHR structure is defined as: |
| |
| include::../api/structs/VkFenceGetFdInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:fence is the fence from which state will be exported. |
| * pname:handleType is the type of handle requested. |
| |
| The properties of the file descriptor returned depend on the value of |
| pname:handleType. |
| See elink:VkExternalFenceHandleTypeFlagBits for a description of the |
| properties of the defined external fence handle types. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkFenceGetFdInfoKHR-handleType-01453]] |
| pname:handleType must: have been included in |
| slink:VkExportFenceCreateInfo::pname:handleTypes when pname:fence's |
| current payload was created. |
| * [[VUID-VkFenceGetFdInfoKHR-handleType-01454]] |
| If pname:handleType refers to a handle type with copy payload |
| transference semantics, pname:fence must: be signaled, or have an |
| associated <<synchronization-fences-signaling,fence signal operation>> |
| pending execution. |
| * [[VUID-VkFenceGetFdInfoKHR-fence-01455]] |
| pname:fence must: not currently have its payload replaced by an imported |
| payload as described below in |
| <<synchronization-fences-importing,Importing Fence Payloads>> unless |
| that imported payload's handle type was included in |
| slink:VkExternalFenceProperties::pname:exportFromImportedHandleTypes for |
| pname:handleType. |
| * [[VUID-VkFenceGetFdInfoKHR-handleType-01456]] |
| pname:handleType must: be defined as a POSIX file descriptor handle. |
| **** |
| |
| include::../validity/structs/VkFenceGetFdInfoKHR.txt[] |
| -- |
| |
| endif::VK_KHR_external_fence_fd[] |
| |
| [open,refpage='vkDestroyFence',desc='Destroy a fence object',type='protos'] |
| -- |
| |
| To destroy a fence, call: |
| |
| include::../api/protos/vkDestroyFence.txt[] |
| |
| * pname:device is the logical device that destroys the fence. |
| * pname:fence is the handle of the fence to destroy. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkDestroyFence-fence-01120]] |
| All <<devsandqueues-submission, queue submission>> commands that refer |
| to pname:fence must: have completed execution |
| * [[VUID-vkDestroyFence-fence-01121]] |
| If sname:VkAllocationCallbacks were provided when pname:fence was |
| created, a compatible set of callbacks must: be provided here |
| * [[VUID-vkDestroyFence-fence-01122]] |
| If no sname:VkAllocationCallbacks were provided when pname:fence was |
| created, pname:pAllocator must: be `NULL` |
| **** |
| |
| include::../validity/protos/vkDestroyFence.txt[] |
| -- |
| |
| [open,refpage='vkGetFenceStatus',desc='Return the status of a fence',type='protos'] |
| -- |
| |
| To query the status of a fence from the host, call: |
| |
| include::../api/protos/vkGetFenceStatus.txt[] |
| |
| * pname:device is the logical device that owns the fence. |
| * pname:fence is the handle of the fence to query. |
| |
| Upon success, fname:vkGetFenceStatus returns the status of the fence object, |
| with the following return codes: |
| |
| .Fence Object Status Codes |
| [width="80%",options="header"] |
| |==== |
| | Status | Meaning |
| | ename:VK_SUCCESS | The fence specified by pname:fence is signaled. |
| | ename:VK_NOT_READY | The fence specified by pname:fence is unsignaled. |
| | ename:VK_ERROR_DEVICE_LOST | The device has been lost. See <<devsandqueues-lost-device,Lost Device>>. |
| |==== |
| |
| If a <<devsandqueues-submission, queue submission>> command is pending |
| execution, then the value returned by this command may: immediately be out |
| of date. |
| |
| If the device has been lost (see <<devsandqueues-lost-device,Lost Device>>), |
| fname:vkGetFenceStatus may: return any of the above status codes. |
| If the device has been lost and fname:vkGetFenceStatus is called repeatedly, |
| it will eventually return either ename:VK_SUCCESS or |
| ename:VK_ERROR_DEVICE_LOST. |
| |
| include::../validity/protos/vkGetFenceStatus.txt[] |
| -- |
| |
| [[synchronization-fences-unsignaling]] |
| [open,refpage='vkResetFences',desc='Resets one or more fence objects',type='protos'] |
| -- |
| |
| To set the state of fences to unsignaled from the host, call: |
| |
| include::../api/protos/vkResetFences.txt[] |
| |
| * pname:device is the logical device that owns the fences. |
| * pname:fenceCount is the number of fences to reset. |
| * pname:pFences is a pointer to an array of fence handles to reset. |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_fence[] |
| |
| If any member of pname:pFences currently has its |
| <<synchronization-fences-importing, payload imported>> with temporary |
| permanence, that fence's prior permanent payload is first restored. |
| The remaining operations described therefore operate on the restored |
| payload. |
| |
| endif::VK_VERSION_1_1,VK_KHR_external_fence[] |
| |
| When flink:vkResetFences is executed on the host, it defines a _fence |
| unsignal operation_ for each fence, which resets the fence to the unsignaled |
| state. |
| |
| If any member of pname:pFences is already in the unsignaled state when |
| flink:vkResetFences is executed, then flink:vkResetFences has no effect on |
| that fence. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkResetFences-pFences-01123]] |
| Each element of pname:pFences must: not be currently associated with any |
| queue command that has not yet completed execution on that queue |
| **** |
| |
| include::../validity/protos/vkResetFences.txt[] |
| -- |
| |
| [[synchronization-fences-signaling]] |
| When a fence is submitted to a queue as part of a |
| <<devsandqueues-submission, queue submission>> command, it defines a memory |
| dependency on the batches that were submitted as part of that command, and |
| defines a _fence signal operation_ which sets the fence to the signaled |
| state. |
| |
| The first <<synchronization-dependencies-scopes, synchronization scope>> |
| includes every batch submitted in the same <<devsandqueues-submission, queue |
| submission>> command. |
| Fence signal operations that are defined by flink:vkQueueSubmit additionally |
| include in the first synchronization scope all commands that occur earlier |
| in <<synchronization-submission-order,submission order>>. |
| |
| The second <<synchronization-dependencies-scopes, synchronization scope>> |
| only includes the fence signal operation. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> |
| includes all memory access performed by the device. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> is |
| empty. |
| |
| [open,refpage='vkWaitForFences',desc='Wait for one or more fences to become signaled',type='protos'] |
| -- |
| |
| To wait for one or more fences to enter the signaled state on the host, |
| call: |
| |
| include::../api/protos/vkWaitForFences.txt[] |
| |
| * pname:device is the logical device that owns the fences. |
| * pname:fenceCount is the number of fences to wait on. |
| * pname:pFences is a pointer to an array of pname:fenceCount fence |
| handles. |
| * pname:waitAll is the condition that must: be satisfied to successfully |
| unblock the wait. |
| If pname:waitAll is ename:VK_TRUE, then the condition is that all fences |
| in pname:pFences are signaled. |
| Otherwise, the condition is that at least one fence in pname:pFences is |
| signaled. |
| * pname:timeout is the timeout period in units of nanoseconds. |
| pname:timeout is adjusted to the closest value allowed by the |
| implementation-dependent timeout accuracy, which may: be substantially |
| longer than one nanosecond, and may: be longer than the requested |
| period. |
| |
| If the condition is satisfied when fname:vkWaitForFences is called, then |
| fname:vkWaitForFences returns immediately. |
| If the condition is not satisfied at the time fname:vkWaitForFences is |
| called, then fname:vkWaitForFences will block and wait up to pname:timeout |
| nanoseconds for the condition to become satisfied. |
| |
| If pname:timeout is zero, then fname:vkWaitForFences does not wait, but |
| simply returns the current state of the fences. |
| ename:VK_TIMEOUT will be returned in this case if the condition is not |
| satisfied, even though no actual wait was performed. |
| |
| If the specified timeout period expires before the condition is satisfied, |
| fname:vkWaitForFences returns ename:VK_TIMEOUT. |
| If the condition is satisfied before pname:timeout nanoseconds has expired, |
| fname:vkWaitForFences returns ename:VK_SUCCESS. |
| |
| If device loss occurs (see <<devsandqueues-lost-device,Lost Device>>) before |
| the timeout has expired, fname:vkWaitForFences must: return in finite time |
| with either ename:VK_SUCCESS or ename:VK_ERROR_DEVICE_LOST. |
| |
| [NOTE] |
| .Note |
| ==== |
| While we guarantee that fname:vkWaitForFences must: return in finite time, |
| no guarantees are made that it returns immediately upon device loss. |
| However, the client can reasonably expect that the delay will be on the |
| order of seconds and that calling fname:vkWaitForFences will not result in a |
| permanently (or seemingly permanently) dead process. |
| ==== |
| |
| include::../validity/protos/vkWaitForFences.txt[] |
| -- |
| |
| [[synchronization-fences-waiting]] |
| An execution dependency is defined by waiting for a fence to become |
| signaled, either via flink:vkWaitForFences or by polling on |
| flink:vkGetFenceStatus. |
| |
| The first <<synchronization-dependencies-scopes, synchronization scope>> |
| includes only the fence signal operation. |
| |
| The second <<synchronization-dependencies-scopes, synchronization scope>> |
| includes the host operations of flink:vkWaitForFences or |
| flink:vkGetFenceStatus indicating that the fence has become signaled. |
| |
| [NOTE] |
| .Note |
| ==== |
| Signaling a fence and waiting on the host does not guarantee that the |
| results of memory accesses will be visible to the host, as the access scope |
| of a memory dependency defined by a fence only includes device access. |
| A <<synchronization-memory-barriers, memory barrier>> or other memory |
| dependency must: be used to guarantee this. |
| See the description of <<synchronization-host-access-types, host access |
| types>> for more information. |
| ==== |
| |
| ifdef::VK_EXT_display_control[] |
| include::VK_EXT_display_control/fence_events.txt[] |
| endif::VK_EXT_display_control[] |
| |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_fence[] |
| |
| [[synchronization-fences-importing]] |
| === Importing Fence Payloads |
| |
| Applications can: import a fence payload into an existing fence using an |
| external fence handle. |
| The effects of the import operation will be either temporary or permanent, |
| as specified by the application. |
| If the import is temporary, the fence will be _restored_ to its permanent |
| state the next time that fence is passed to flink:vkResetFences. |
| |
| [NOTE] |
| .Note |
| ==== |
| Restoring a fence to its prior permanent payload is a distinct operation |
| from resetting a fence payload. |
| See flink:vkResetFences for more detail. |
| ==== |
| |
| Performing a subsequent temporary import on a fence before resetting it has |
| no effect on this requirement; the next unsignal of the fence must: still |
| restore its last permanent state. |
| A permanent payload import behaves as if the target fence was destroyed, and |
| a new fence was created with the same handle but the imported payload. |
| Because importing a fence payload temporarily or permanently detaches the |
| existing payload from a fence, similar usage restrictions to those applied |
| to fname:vkDestroyFence are applied to any command that imports a fence |
| payload. |
| Which of these import types is used is referred to as the import operation's |
| _permanence_. |
| Each handle type supports either one or both types of permanence. |
| |
| The implementation must: perform the import operation by either referencing |
| or copying the payload referred to by the specified external fence handle, |
| depending on the handle's type. |
| The import method used is referred to as the handle type's _transference_. |
| When using handle types with reference transference, importing a payload to |
| a fence adds the fence to the set of all fences sharing that payload. |
| This set includes the fence from which the payload was exported. |
| Fence signaling, waiting, and resetting operations performed on any fence in |
| the set must: behave as if the set were a single fence. |
| Importing a payload using handle types with copy transference creates a |
| duplicate copy of the payload at the time of import, but makes no further |
| reference to it. |
| Fence signaling, waiting, and resetting operations performed on the target |
| of copy imports must: not affect any other fence or payload. |
| |
| Export operations have the same transference as the specified handle type's |
| import operations. |
| Additionally, exporting a fence payload to a handle with copy transference |
| has the same side effects on the source fence's payload as executing a fence |
| reset operation. |
| If the fence was using a temporarily imported payload, the fence's prior |
| permanent payload will be restored. |
| |
| ifdef::VK_KHR_external_fence_win32,VK_KHR_external_fence_fd[] |
| [NOTE] |
| .Note |
| ==== |
| The |
| ifdef::VK_KHR_external_fence_win32+VK_KHR_external_fence_fd[tables] |
| ifndef::VK_KHR_external_fence_win32+VK_KHR_external_fence_fd[table] |
| ifdef::VK_KHR_external_fence_win32[] |
| <<synchronization-fence-handletypes-win32,Handle Types Supported by |
| VkImportFenceWin32HandleInfoKHR>> |
| endif::VK_KHR_external_fence_win32[] |
| ifdef::VK_KHR_external_fence_win32+VK_KHR_external_fence_fd[and] |
| ifdef::VK_KHR_external_fence_fd[] |
| <<synchronization-fence-handletypes-fd,Handle Types Supported by |
| VkImportFenceFdInfoKHR>> |
| endif::VK_KHR_external_fence_fd[] |
| ifdef::VK_KHR_external_fence_win32+VK_KHR_external_fence_fd[define] |
| ifndef::VK_KHR_external_fence_win32+VK_KHR_external_fence_fd[defines] |
| the permanence and transference of each handle type. |
| ==== |
| endif::VK_KHR_external_fence_win32,VK_KHR_external_fence_fd[] |
| |
| <<fundamentals-threadingbehavior,External synchronization>> allows |
| implementations to modify an object's internal state, i.e. payload, without |
| internal synchronization. |
| However, for fences sharing a payload across processes, satisfying the |
| external synchronization requirements of fname:VkFence parameters as if all |
| fences in the set were the same object is sometimes infeasible. |
| Satisfying valid usage constraints on the state of a fence would similarly |
| require impractical coordination or levels of trust between processes. |
| Therefore, these constraints only apply to a specific fence handle, not to |
| its payload. |
| For distinct fence objects which share a payload: |
| |
| * If multiple commands which queue a signal operation, or which unsignal a |
| fence, are called concurrently, behavior will be as if the commands were |
| called in an arbitrary sequential order. |
| * If a queue submission command is called with a fence that is sharing a |
| payload, and the payload is already associated with another queue command |
| that has not yet completed execution, either one or both of the commands |
| will cause the fence to become signaled when they complete execution. |
| * If a fence payload is reset while it is associated with a queue command |
| that has not yet completed execution, the payload will become unsignaled, |
| but may: become signaled again when the command completes execution. |
| * In the preceding cases, any of the devices associated with the fences |
| sharing the payload may: be lost, or any of the queue submission or fence |
| reset commands may: return ename:VK_ERROR_INITIALIZATION_FAILED. |
| |
| Other than these non-deterministic results, behavior is well defined. |
| In particular: |
| |
| * The implementation must: not crash or enter an internally inconsistent |
| state where future valid Vulkan commands might cause undefined results, |
| * Timeouts on future wait commands on fences sharing the payload must: be |
| effective. |
| |
| [NOTE] |
| .Note |
| ==== |
| These rules allow processes to synchronize access to shared memory without |
| trusting each other. |
| However, such processes must still be cautious not to use the shared fence |
| for more than synchronizing access to the shared memory. |
| For example, a process should not use a fence with shared payload to tell |
| when commands it submitted to a queue have completed and objects used by |
| those commands may be destroyed, since the other process can accidentally or |
| maliciously cause the fence to signal before the commands actually complete. |
| ==== |
| |
| When a fence is using an imported payload, its |
| slink:VkExportFenceCreateInfo::pname:handleTypes value is that specified |
| when creating the fence from which the payload was exported, rather than |
| that specified when creating the fence. |
| Additionally, slink:VkExternalFenceProperties::exportFromImportedHandleTypes |
| restricts which handle types can: be exported from such a fence based on the |
| specific handle type used to import the current payload. |
| ifdef::VK_KHR_swapchain[] |
| Passing a fence to flink:vkAcquireNextImageKHR is equivalent to temporarily |
| importing a fence payload to that fence. |
| |
| [NOTE] |
| .Note |
| ==== |
| Because the exportable handle types of an imported fence correspond to its |
| current imported payload, and flink:vkAcquireNextImageKHR behaves the same |
| as a temporary import operation for which the source fence is opaque to the |
| application, applications have no way of determining whether any external |
| handle types can: be exported from a fence in this state. |
| Therefore, applications must: not attempt to export handles from fences |
| using a temporarily imported payload from flink:vkAcquireNextImageKHR. |
| ==== |
| endif::VK_KHR_swapchain[] |
| |
| When importing a fence payload, it is the responsibility of the application |
| to ensure the external handles meet all valid usage requirements. |
| However, implementations must: perform sufficient validation of external |
| handles to ensure that the operation results in a valid fence which will not |
| cause program termination, device loss, queue stalls, host thread stalls, or |
| corruption of other resources when used as allowed according to its import |
| parameters. |
| If the external handle provided does not meet these requirements, the |
| implementation must: fail the fence payload import operation with the error |
| code ename:VK_ERROR_INVALID_EXTERNAL_HANDLE. |
| |
| endif::VK_VERSION_1_1,VK_KHR_external_fence[] |
| |
| ifdef::VK_KHR_external_fence_win32[] |
| |
| [open,refpage='vkImportFenceWin32HandleKHR',desc='Import a fence from a Windows HANDLE',type='protos'] |
| -- |
| |
| To import a fence payload from a Windows handle, call: |
| |
| include::../api/protos/vkImportFenceWin32HandleKHR.txt[] |
| |
| * pname:device is the logical device that created the fence. |
| * pname:pImportFenceWin32HandleInfo points to a |
| slink:VkImportFenceWin32HandleInfoKHR structure specifying the fence and |
| import parameters. |
| |
| Importing a fence payload from Windows handles does not transfer ownership |
| of the handle to the Vulkan implementation. |
| For handle types defined as NT handles, the application must: release |
| ownership using the fname:CloseHandle system call when the handle is no |
| longer needed. |
| |
| Applications can: import the same fence payload into multiple instances of |
| Vulkan, into the same instance from which it was exported, and multiple |
| times into a given Vulkan instance. |
| |
| include::../validity/protos/vkImportFenceWin32HandleKHR.txt[] |
| -- |
| |
| [open,refpage='VkImportFenceWin32HandleInfoKHR',desc='(None)',type='structs'] |
| -- |
| The sname:VkImportFenceWin32HandleInfoKHR structure is defined as: |
| |
| include::../api/structs/VkImportFenceWin32HandleInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:fence is the fence into which the state will be imported. |
| * pname:flags is a bitmask of elink:VkFenceImportFlagBits specifying |
| additional parameters for the fence payload import operation. |
| * pname:handleType specifies the type of pname:handle. |
| * pname:handle is the external handle to import, or `NULL`. |
| * pname:name is the NULL-terminated UTF-16 string naming the underlying |
| synchronization primitive to import, or `NULL`. |
| |
| The handle types supported by pname:handleType are: |
| |
| [[synchronization-fence-handletypes-win32]] |
| .Handle Types Supported by VkImportFenceWin32HandleInfoKHR |
| [width="80%",options="header"] |
| |==== |
| | Handle Type | Transference | Permanence Supported |
| | ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT | Reference | Temporary,Permanent |
| | ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | Reference | Temporary,Permanent |
| |==== |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkImportFenceWin32HandleInfoKHR-handleType-01457]] |
| pname:handleType must: be a value included in the |
| <<synchronization-fence-handletypes-win32, Handle Types Supported by |
| VkImportFenceWin32HandleInfoKHR>> table. |
| * [[VUID-VkImportFenceWin32HandleInfoKHR-handleType-01459]] |
| If pname:handleType is not |
| ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT, pname:name must: |
| be `NULL`. |
| * [[VUID-VkImportFenceWin32HandleInfoKHR-handleType-01460]] |
| If pname:handleType is not `0` and pname:handle is `NULL`, pname:name |
| must: name a valid synchronization primitive of the type specified by |
| pname:handleType. |
| * [[VUID-VkImportFenceWin32HandleInfoKHR-handleType-01461]] |
| If pname:handleType is not `0` and pname:name is `NULL`, pname:handle |
| must: be a valid handle of the type specified by pname:handleType. |
| * [[VUID-VkImportFenceWin32HandleInfoKHR-handle-01462]] |
| If pname:handle is not `NULL`, pname:name must be `NULL`. |
| * [[VUID-VkImportFenceWin32HandleInfoKHR-handle-01539]] |
| If pname:handle is not `NULL`, it must: obey any requirements listed for |
| pname:handleType in <<external-fence-handle-types-compatibility,external |
| fence handle types compatibility>>. |
| * [[VUID-VkImportFenceWin32HandleInfoKHR-name-01540]] |
| If pname:name is not `NULL`, it must: obey any requirements listed for |
| pname:handleType in <<external-fence-handle-types-compatibility,external |
| fence handle types compatibility>>. |
| **** |
| |
| include::../validity/structs/VkImportFenceWin32HandleInfoKHR.txt[] |
| -- |
| |
| endif::VK_KHR_external_fence_win32[] |
| |
| ifdef::VK_KHR_external_fence_fd[] |
| |
| [open,refpage='vkImportFenceFdKHR',desc='Import a fence from a POSIX file descriptor',type='protos'] |
| -- |
| |
| To import a fence payload from a POSIX file descriptor, call: |
| |
| include::../api/protos/vkImportFenceFdKHR.txt[] |
| |
| * pname:device is the logical device that created the fence. |
| * pname:pImportFenceFdInfo points to a slink:VkImportFenceFdInfoKHR |
| structure specifying the fence and import parameters. |
| |
| Importing a fence payload from a file descriptor transfers ownership of the |
| file descriptor from the application to the Vulkan implementation. |
| The application must: not perform any operations on the file descriptor |
| after a successful import. |
| |
| Applications can: import the same fence payload into multiple instances of |
| Vulkan, into the same instance from which it was exported, and multiple |
| times into a given Vulkan instance. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkImportFenceFdKHR-fence-01463]] |
| pname:fence must: not be associated with any queue command that has not |
| yet completed execution on that queue |
| **** |
| |
| include::../validity/protos/vkImportFenceFdKHR.txt[] |
| -- |
| |
| [open,refpage='VkImportFenceFdInfoKHR',desc='(None)',type='structs'] |
| -- |
| The sname:VkImportFenceFdInfoKHR structure is defined as: |
| |
| include::../api/structs/VkImportFenceFdInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:fence is the fence into which the payload will be imported. |
| * pname:flags is a bitmask of elink:VkFenceImportFlagBits specifying |
| additional parameters for the fence payload import operation. |
| * pname:handleType specifies the type of pname:fd. |
| * pname:fd is the external handle to import. |
| |
| The handle types supported by pname:handleType are: |
| |
| [[synchronization-fence-handletypes-fd]] |
| .Handle Types Supported by VkImportFenceFdInfoKHR |
| [width="80%",options="header"] |
| |==== |
| | Handle Type | Transference | Permanence Supported |
| | ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT | Reference | Temporary,Permanent |
| | ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT | Copy | Temporary |
| |==== |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkImportFenceFdInfoKHR-handleType-01464]] |
| pname:handleType must: be a value included in the |
| <<synchronization-fence-handletypes-fd, Handle Types Supported by |
| VkImportFenceFdInfoKHR>> table. |
| * [[VUID-VkImportFenceFdInfoKHR-fd-01541]] |
| pname:fd must: obey any requirements listed for pname:handleType in |
| <<external-fence-handle-types-compatibility,external fence handle types |
| compatibility>>. |
| **** |
| |
| If pname:handleType is ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, the |
| special value `-1` for pname:fd is treated like a valid sync file descriptor |
| referring to an object that has already signaled. |
| The import operation will succeed and the sname:VkFence will have a |
| temporarily imported payload as if a valid file descriptor had been |
| provided. |
| |
| [NOTE] |
| .Note |
| ==== |
| This special behavior for importing an invalid sync file descriptor allows |
| easier interoperability with other system APIs which use the convention that |
| an invalid sync file descriptor represents work that has already completed |
| and does not need to be waited for. |
| It is consistent with the option for implementations to return a `-1` file |
| descriptor when exporting a ename:VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT |
| from a sname:VkFence which is signaled. |
| ==== |
| |
| include::../validity/structs/VkImportFenceFdInfoKHR.txt[] |
| -- |
| |
| endif::VK_KHR_external_fence_fd[] |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_fence[] |
| ifdef::VK_KHR_external_fence_win32,VK_KHR_external_fence_fd[] |
| |
| [open,refpage='VkFenceImportFlagBits',desc='Bitmask specifying additional parameters of fence payload import',type='enums'] |
| -- |
| |
| Bits which can: be set in |
| ifdef::VK_KHR_external_fence_win32[] |
| slink:VkImportFenceWin32HandleInfoKHR::pname:flags |
| endif::VK_KHR_external_fence_win32[] |
| ifdef::VK_KHR_external_fence_win32+VK_KHR_external_fence_fd[and] |
| ifdef::VK_KHR_external_fence_fd[] |
| slink:VkImportFenceFdInfoKHR::pname:flags |
| endif::VK_KHR_external_fence_fd[] |
| specifying additional parameters of a fence import operation are: |
| |
| include::../api/enums/VkFenceImportFlagBits.txt[] |
| |
| ifdef::VK_KHR_external_fence[] |
| or the equivalent |
| |
| include::../api/enums/VkFenceImportFlagBitsKHR.txt[] |
| endif::VK_KHR_external_fence[] |
| |
| * ename:VK_FENCE_IMPORT_TEMPORARY_BIT specifies that the fence payload |
| will be imported only temporarily, as described in |
| <<synchronization-fences-importing,Importing Fence Payloads>>, |
| regardless of the permanence of pname:handleType. |
| |
| -- |
| |
| [open,refpage='VkFenceImportFlags',desc='Bitmask of VkFenceImportFlagBits',type='enums'] |
| -- |
| include::../api/flags/VkFenceImportFlags.txt[] |
| |
| ifdef::VK_KHR_external_fence[] |
| or the equivalent |
| |
| include::../api/flags/VkFenceImportFlagsKHR.txt[] |
| endif::VK_KHR_external_fence[] |
| |
| sname:VkFenceImportFlags is a bitmask type for setting a mask of zero or |
| more slink:VkFenceImportFlagBits. |
| -- |
| |
| endif::VK_KHR_external_fence_win32,VK_KHR_external_fence_fd[] |
| endif::VK_VERSION_1_1,VK_KHR_external_fence[] |
| |
| |
| [[synchronization-semaphores]] |
| == Semaphores |
| |
| [open,refpage='VkSemaphore',desc='Opaque handle to a semaphore object',type='handles'] |
| -- |
| |
| Semaphores are a synchronization primitive that can: be used to insert a |
| dependency between batches submitted to queues. |
| Semaphores have two states - signaled and unsignaled. |
| The state of a semaphore can: be signaled after execution of a batch of |
| commands is completed. |
| A batch can: wait for a semaphore to become signaled before it begins |
| execution, and the semaphore is also unsignaled before the batch begins |
| execution. |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_semaphore[] |
| [[synchronization-semaphores-payloads]] |
| As with most objects in Vulkan, semaphores are an interface to internal data |
| which is typically opaque to applications. |
| This internal data is referred to as a semaphore's _payload_. |
| |
| However, in order to enable communication with agents outside of the current |
| device, it is necessary to be able to export that payload to a commonly |
| understood format, and subsequently import from that format as well. |
| |
| The internal data of a semaphore may: include a reference to any resources |
| and pending work associated with signal or unsignal operations performed on |
| that semaphore object. |
| Mechanisms to import and export that internal data to and from semaphores |
| are provided <<VkExportSemaphoreCreateInfo, below>>. |
| These mechanisms indirectly enable applications to share semaphore state |
| between two or more semaphores and other synchronization primitives across |
| process and API boundaries. |
| |
| endif::VK_VERSION_1_1,VK_KHR_external_semaphore[] |
| |
| Semaphores are represented by sname:VkSemaphore handles: |
| |
| include::../api/handles/VkSemaphore.txt[] |
| |
| -- |
| |
| [open,refpage='vkCreateSemaphore',desc='Create a new queue semaphore object',type='protos'] |
| -- |
| |
| To create a semaphore, call: |
| |
| include::../api/protos/vkCreateSemaphore.txt[] |
| |
| * pname:device is the logical device that creates the semaphore. |
| * pname:pCreateInfo is a pointer to an instance of the |
| sname:VkSemaphoreCreateInfo structure which contains information about |
| how the semaphore is to be created. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| * pname:pSemaphore points to a handle in which the resulting semaphore |
| object is returned. |
| |
| When created, the semaphore is in the unsignaled state. |
| |
| include::../validity/protos/vkCreateSemaphore.txt[] |
| -- |
| |
| [open,refpage='VkSemaphoreCreateInfo',desc='Structure specifying parameters of a newly created semaphore',type='structs'] |
| -- |
| |
| The sname:VkSemaphoreCreateInfo structure is defined as: |
| |
| include::../api/structs/VkSemaphoreCreateInfo.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:flags is reserved for future use. |
| |
| include::../validity/structs/VkSemaphoreCreateInfo.txt[] |
| -- |
| |
| [open,refpage='VkSemaphoreCreateFlags',desc='Reserved for future use',type='enums'] |
| -- |
| include::../api/flags/VkSemaphoreCreateFlags.txt[] |
| |
| sname:VkSemaphoreCreateFlags is a bitmask type for setting a mask, but is |
| currently reserved for future use. |
| -- |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_semaphore[] |
| |
| [open,refpage='VkExportSemaphoreCreateInfo',desc='Structure specifying handle types that can be exported from a semaphore',type='structs'] |
| -- |
| |
| To create a semaphore whose payload can: be exported to external handles, |
| add the slink:VkExportSemaphoreCreateInfo structure to the pname:pNext chain |
| of the slink:VkSemaphoreCreateInfo structure. |
| The sname:VkExportSemaphoreCreateInfo structure is defined as: |
| |
| include::../api/structs/VkExportSemaphoreCreateInfo.txt[] |
| |
| ifdef::VK_KHR_external_semaphore[] |
| or the equivalent |
| |
| include::../api/structs/VkExportSemaphoreCreateInfoKHR.txt[] |
| endif::VK_KHR_external_semaphore[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:handleTypes is a bitmask of |
| elink:VkExternalSemaphoreHandleTypeFlagBits specifying one or more |
| semaphore handle types the application can: export from the resulting |
| semaphore. |
| The application can: request multiple handle types for the same |
| semaphore. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkExportSemaphoreCreateInfo-handleTypes-01124]] |
| The bits in pname:handleTypes must: be supported and compatible, as |
| reported by slink:VkExternalSemaphoreProperties. |
| **** |
| |
| include::../validity/structs/VkExportSemaphoreCreateInfo.txt[] |
| -- |
| |
| endif::VK_VERSION_1_1,VK_KHR_external_semaphore[] |
| |
| ifdef::VK_KHR_external_semaphore_win32[] |
| |
| [open,refpage='VkExportSemaphoreWin32HandleInfoKHR',desc='Structure specifying additional attributes of Windows handles exported from a semaphore',type='structs'] |
| -- |
| |
| To specify additional attributes of NT handles exported from a semaphore, |
| add the sname:VkExportSemaphoreWin32HandleInfoKHR structure to the |
| pname:pNext chain of the slink:VkSemaphoreCreateInfo structure. |
| The sname:VkExportSemaphoreWin32HandleInfoKHR structure is defined as: |
| |
| include::../api/structs/VkExportSemaphoreWin32HandleInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:pAttributes is a pointer to a Windows code:SECURITY_ATTRIBUTES |
| structure specifying security attributes of the handle. |
| * pname:dwAccess is a code:DWORD specifying access rights of the handle. |
| * pname:name is a NULL-terminated UTF-16 string to associate with the |
| underlying synchronization primitive referenced by NT handles exported |
| from the created semaphore. |
| |
| If this structure is not present, or if pname:pAttributes is set to `NULL`, |
| default security descriptor values will be used, and child processes created |
| by the application will not inherit the handle, as described in the MSDN |
| documentation for "`Synchronization Object Security and Access Rights`"^1^. |
| Further, if the structure is not present, the access rights will be |
| |
| code:DXGI_SHARED_RESOURCE_READ | code:DXGI_SHARED_RESOURCE_WRITE |
| |
| for handles of the following types: |
| |
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT |
| |
| And |
| |
| code:GENERIC_ALL |
| |
| for handles of the following types: |
| |
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT |
| |
| 1:: |
| https://msdn.microsoft.com/en-us/library/windows/desktop/ms686670.aspx |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkExportSemaphoreWin32HandleInfoKHR-handleTypes-01125]] |
| If slink:VkExportSemaphoreCreateInfo::pname:handleTypes does not include |
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT or |
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, |
| sname:VkExportSemaphoreWin32HandleInfoKHR must: not be in the |
| pname:pNext chain of slink:VkSemaphoreCreateInfo. |
| **** |
| |
| include::../validity/structs/VkExportSemaphoreWin32HandleInfoKHR.txt[] |
| -- |
| |
| [open,refpage='vkGetSemaphoreWin32HandleKHR',desc='Get a Windows HANDLE for a semaphore',type='protos'] |
| -- |
| |
| To export a Windows handle representing the payload of a semaphore, call: |
| |
| include::../api/protos/vkGetSemaphoreWin32HandleKHR.txt[] |
| |
| * pname:device is the logical device that created the semaphore being |
| exported. |
| * pname:pGetWin32HandleInfo is a pointer to an instance of the |
| slink:VkSemaphoreGetWin32HandleInfoKHR structure containing parameters |
| of the export operation. |
| * pname:pHandle will return the Windows handle representing the semaphore |
| state. |
| |
| For handle types defined as NT handles, the handles returned by |
| fname:vkGetSemaphoreWin32HandleKHR are owned by the application. |
| To avoid leaking resources, the application must: release ownership of them |
| using the fname:CloseHandle system call when they are no longer needed. |
| |
| Exporting a Windows handle from a semaphore may: have side effects depending |
| on the transference of the specified handle type, as described in |
| <<synchronization-semaphores-importing,Importing Semaphore Payloads>>. |
| |
| include::../validity/protos/vkGetSemaphoreWin32HandleKHR.txt[] |
| -- |
| |
| [open,refpage='VkSemaphoreGetWin32HandleInfoKHR',desc='Structure describing a Win32 handle semaphore export operation',type='structs'] |
| -- |
| |
| The sname:VkSemaphoreGetWin32HandleInfoKHR structure is defined as: |
| |
| include::../api/structs/VkSemaphoreGetWin32HandleInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:semaphore is the semaphore from which state will be exported. |
| * pname:handleType is the type of handle requested. |
| |
| The properties of the handle returned depend on the value of |
| pname:handleType. |
| See elink:VkExternalSemaphoreHandleTypeFlagBits for a description of the |
| properties of the defined external semaphore handle types. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01126]] |
| pname:handleType must: have been included in |
| slink:VkExportSemaphoreCreateInfo::pname:handleTypes when the |
| pname:semaphore's current payload was created. |
| * [[VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01127]] |
| If pname:handleType is defined as an NT handle, |
| flink:vkGetSemaphoreWin32HandleKHR must: be called no more than once for |
| each valid unique combination of pname:semaphore and pname:handleType. |
| * [[VUID-VkSemaphoreGetWin32HandleInfoKHR-semaphore-01128]] |
| pname:semaphore must: not currently have its payload replaced by an |
| imported payload as described below in |
| <<synchronization-semaphores-importing,Importing Semaphore Payloads>> |
| unless that imported payload's handle type was included in |
| slink:VkExternalSemaphoreProperties::pname:exportFromImportedHandleTypes |
| for pname:handleType. |
| * [[VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01129]] |
| If pname:handleType refers to a handle type with copy payload |
| transference semantics, as defined below in |
| <<synchronization-semaphores-importing,Importing Semaphore Payloads>>, |
| there must: be no queue waiting on pname:semaphore. |
| * [[VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01130]] |
| If pname:handleType refers to a handle type with copy payload |
| transference semantics, pname:semaphore must: be signaled, or have an |
| associated <<synchronization-semaphores-signaling,semaphore signal |
| operation>> pending execution. |
| * [[VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01131]] |
| pname:handleType must: be defined as an NT handle or a global share |
| handle. |
| **** |
| |
| include::../validity/structs/VkSemaphoreGetWin32HandleInfoKHR.txt[] |
| -- |
| |
| endif::VK_KHR_external_semaphore_win32[] |
| |
| ifdef::VK_KHR_external_semaphore_fd[] |
| |
| [open,refpage='vkGetSemaphoreFdKHR',desc='Get a POSIX file descriptor handle for a semaphore',type='protos'] |
| -- |
| |
| To export a POSIX file descriptor representing the payload of a semaphore, |
| call: |
| |
| include::../api/protos/vkGetSemaphoreFdKHR.txt[] |
| |
| * pname:device is the logical device that created the semaphore being |
| exported. |
| * pname:pGetFdInfo is a pointer to an instance of the |
| slink:VkSemaphoreGetFdInfoKHR structure containing parameters of the |
| export operation. |
| * pname:pFd will return the file descriptor representing the semaphore |
| payload. |
| |
| Each call to fname:vkGetSemaphoreFdKHR must: create a new file descriptor |
| and transfer ownership of it to the application. |
| To avoid leaking resources, the application must: release ownership of the |
| file descriptor when it is no longer needed. |
| |
| [NOTE] |
| .Note |
| ==== |
| Ownership can be released in many ways. |
| For example, the application can call code:close() on the file descriptor, |
| or transfer ownership back to Vulkan by using the file descriptor to import |
| a semaphore payload. |
| ==== |
| Where supported by the operating system, the implementation must: set the |
| file descriptor to be closed automatically when an code:execve system call |
| is made. |
| |
| Exporting a file descriptor from a semaphore may: have side effects |
| depending on the transference of the specified handle type, as described in |
| <<synchronization-semaphores-importing,Importing Semaphore State>>. |
| |
| include::../validity/protos/vkGetSemaphoreFdKHR.txt[] |
| -- |
| |
| [open,refpage='VkSemaphoreGetFdInfoKHR',desc='Structure describing a POSIX FD semaphore export operation',type='structs'] |
| -- |
| |
| The sname:VkSemaphoreGetFdInfoKHR structure is defined as: |
| |
| include::../api/structs/VkSemaphoreGetFdInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:semaphore is the semaphore from which state will be exported. |
| * pname:handleType is the type of handle requested. |
| |
| The properties of the file descriptor returned depend on the value of |
| pname:handleType. |
| See elink:VkExternalSemaphoreHandleTypeFlagBits for a description of the |
| properties of the defined external semaphore handle types. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkSemaphoreGetFdInfoKHR-handleType-01132]] |
| pname:handleType must: have been included in |
| slink:VkExportSemaphoreCreateInfo::pname:handleTypes when |
| pname:semaphore's current payload was created. |
| * [[VUID-VkSemaphoreGetFdInfoKHR-semaphore-01133]] |
| pname:semaphore must: not currently have its payload replaced by an |
| imported payload as described below in |
| <<synchronization-semaphores-importing,Importing Semaphore Payloads>> |
| unless that imported payload's handle type was included in |
| slink:VkExternalSemaphoreProperties::pname:exportFromImportedHandleTypes |
| for pname:handleType. |
| * [[VUID-VkSemaphoreGetFdInfoKHR-handleType-01134]] |
| If pname:handleType refers to a handle type with copy payload |
| transference semantics, as defined below in |
| <<synchronization-semaphores-importing,Importing Semaphore Payloads>>, |
| there must: be no queue waiting on pname:semaphore. |
| * [[VUID-VkSemaphoreGetFdInfoKHR-handleType-01135]] |
| If pname:handleType refers to a handle type with copy payload |
| transference semantics, pname:semaphore must: be signaled, or have an |
| associated <<synchronization-semaphores-signaling,semaphore signal |
| operation>> pending execution. |
| * [[VUID-VkSemaphoreGetFdInfoKHR-handleType-01136]] |
| pname:handleType must: be defined as a POSIX file descriptor handle. |
| **** |
| |
| include::../validity/structs/VkSemaphoreGetFdInfoKHR.txt[] |
| -- |
| |
| endif::VK_KHR_external_semaphore_fd[] |
| |
| [open,refpage='vkDestroySemaphore',desc='Destroy a semaphore object',type='protos'] |
| -- |
| |
| To destroy a semaphore, call: |
| |
| include::../api/protos/vkDestroySemaphore.txt[] |
| |
| * pname:device is the logical device that destroys the semaphore. |
| * pname:semaphore is the handle of the semaphore to destroy. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkDestroySemaphore-semaphore-01137]] |
| All submitted batches that refer to pname:semaphore must: have completed |
| execution |
| * [[VUID-vkDestroySemaphore-semaphore-01138]] |
| If sname:VkAllocationCallbacks were provided when pname:semaphore was |
| created, a compatible set of callbacks must: be provided here |
| * [[VUID-vkDestroySemaphore-semaphore-01139]] |
| If no sname:VkAllocationCallbacks were provided when pname:semaphore was |
| created, pname:pAllocator must: be `NULL` |
| **** |
| |
| include::../validity/protos/vkDestroySemaphore.txt[] |
| -- |
| |
| |
| [[synchronization-semaphores-signaling]] |
| === Semaphore Signaling |
| |
| When a batch is submitted to a queue via a <<devsandqueues-submission, queue |
| submission>>, and it includes semaphores to be signaled, it defines a memory |
| dependency on the batch, and defines _semaphore signal operations_ which set |
| the semaphores to the signaled state. |
| |
| The first <<synchronization-dependencies-scopes, synchronization scope>> |
| includes every command submitted in the same batch. |
| Semaphore signal operations that are defined by flink:vkQueueSubmit |
| additionally include all commands that occur earlier in |
| <<synchronization-submission-order,submission order>>. |
| |
| The second <<synchronization-dependencies-scopes, synchronization scope>> |
| includes only the semaphore signal operation. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> |
| includes all memory access performed by the device. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> is |
| empty. |
| |
| |
| [[synchronization-semaphores-waiting]] |
| === Semaphore Waiting & Unsignaling |
| |
| When a batch is submitted to a queue via a <<devsandqueues-submission, queue |
| submission>>, and it includes semaphores to be waited on, it defines a |
| memory dependency between prior semaphore signal operations and the batch, |
| and defines _semaphore unsignal operations_ which set the semaphores to the |
| unsignaled state. |
| |
| The first synchronization scope includes all semaphore signal operations |
| that operate on semaphores waited on in the same batch, and that |
| happen-before the wait completes. |
| |
| The second <<synchronization-dependencies-scopes, synchronization scope>> |
| includes every command submitted in the same batch. |
| In the case of flink:vkQueueSubmit, the second synchronization scope is |
| limited to operations on the pipeline stages determined by the |
| <<synchronization-pipeline-stages-masks, destination stage mask>> specified |
| by the corresponding element of pname:pWaitDstStageMask. |
| Also, in the case of flink:vkQueueSubmit, the second synchronization scope |
| additionally includes all commands that occur later in |
| <<synchronization-submission-order,submission order>>. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> is |
| empty. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> |
| includes all memory access performed by the device. |
| |
| The semaphore unsignal operation happens-after the first set of operations |
| in the execution dependency, and happens-before the second set of operations |
| in the execution dependency. |
| |
| [NOTE] |
| .Note |
| ==== |
| Unlike fences or events, the act of waiting for a semaphore also unsignals |
| that semaphore. |
| If two operations are separately specified to wait for the same semaphore, |
| and there are no other execution dependencies between those operations, |
| behaviour is undefined. |
| An execution dependency must: be present that guarantees that the semaphore |
| unsignal operation for the first of those waits, happens-before the |
| semaphore is signalled again, and before the second unsignal operation. |
| Semaphore waits and signals should thus occur in discrete 1:1 pairs. |
| ==== |
| |
| ifdef::VK_KHR_swapchain[] |
| [NOTE] |
| .Note |
| ==== |
| A common scenario for using pname:pWaitDstStageMask with values other than |
| ename:VK_PIPELINE_STAGE_ALL_COMMANDS_BIT is when synchronizing a window |
| system presentation operation against subsequent command buffers which |
| render the next frame. |
| In this case, a presentation image must: not be overwritten until the |
| presentation operation completes, but other pipeline stages can: execute |
| without waiting. |
| A mask of ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT prevents |
| subsequent color attachment writes from executing until the semaphore |
| signals. |
| Some implementations may: be able to execute transfer operations and/or |
| vertex processing work before the semaphore is signaled. |
| |
| If an image layout transition needs to be performed on a presentable image |
| before it is used in a framebuffer, that can: be performed as the first |
| operation submitted to the queue after acquiring the image, and should: not |
| prevent other work from overlapping with the presentation operation. |
| For example, a sname:VkImageMemoryBarrier could use: |
| |
| * pname:srcStageMask = ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| * pname:srcAccessMask = 0 |
| * pname:dstStageMask = ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
| * pname:dstAccessMask = ename:VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | |
| ename:VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT. |
| * pname:oldLayout = ename:VK_IMAGE_LAYOUT_PRESENT_SRC_KHR |
| * pname:newLayout = ename:VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL |
| |
| Alternatively, pname:oldLayout can: be ename:VK_IMAGE_LAYOUT_UNDEFINED, if |
| the image's contents need not be preserved. |
| |
| This barrier accomplishes a dependency chain between previous presentation |
| operations and subsequent color attachment output operations, with the |
| layout transition performed in between, and does not introduce a dependency |
| between previous work and any vertex processing stages. |
| More precisely, the semaphore signals after the presentation operation |
| completes, the semaphore wait stalls the |
| ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage, and there is a |
| dependency from that same stage to itself with the layout transition |
| performed in between. |
| ==== |
| endif::VK_KHR_swapchain[] |
| |
| |
| [[synchronization-semaphores-waiting-state]] |
| === Semaphore State Requirements For Wait Operations |
| |
| Before waiting on a semaphore, the application must: ensure the semaphore is |
| in a valid state for a wait operation. |
| Specifically, when a <<synchronization-semaphores-waiting,semaphore wait and |
| unsignal operation>> is submitted to a queue: |
| |
| * The semaphore must: be signaled, or have an associated |
| <<synchronization-semaphores-signaling,semaphore signal operation>> that |
| is pending execution. |
| * There must: be no other queue waiting on the same semaphore when the |
| operation executes. |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_semaphore[] |
| |
| [[synchronization-semaphores-importing]] |
| === Importing Semaphore Payloads |
| |
| Applications can: import a semaphore payload into an existing semaphore |
| using an external semaphore handle. |
| The effects of the import operation will be either temporary or permanent, |
| as specified by the application. |
| If the import is temporary, the implementation must: restore the semaphore |
| to its prior permanent state after submitting the next semaphore wait |
| operation. |
| Performing a subsequent temporary import on a semaphore before performing a |
| semaphore wait has no effect on this requirement; the next wait submitted on |
| the semaphore must: still restore its last permanent state. |
| A permanent payload import behaves as if the target semaphore was destroyed, |
| and a new semaphore was created with the same handle but the imported |
| payload. |
| Because importing a semaphore payload temporarily or permanently detaches |
| the existing payload from a semaphore, similar usage restrictions to those |
| applied to fname:vkDestroySemaphore are applied to any command that imports |
| a semaphore payload. |
| Which of these import types is used is referred to as the import operation's |
| _permanence_. |
| Each handle type supports either one or both types of permanence. |
| |
| The implementation must: perform the import operation by either referencing |
| or copying the payload referred to by the specified external semaphore |
| handle, depending on the handle's type. |
| The import method used is referred to as the handle type's _transference_. |
| When using handle types with reference transference, importing a payload to |
| a semaphore adds the semaphore to the set of all semaphores sharing that |
| payload. |
| This set includes the semaphore from which the payload was exported. |
| Semaphore signaling and waiting operations performed on any semaphore in the |
| set must: behave as if the set were a single semaphore. |
| Importing a payload using handle types with copy transference creates a |
| duplicate copy of the payload at the time of import, but makes no further |
| reference to it. |
| Semaphore signaling and waiting operations performed on the target of copy |
| imports must: not affect any other semaphore or payload. |
| |
| Export operations have the same transference as the specified handle type's |
| import operations. |
| Additionally, exporting a semaphore payload to a handle with copy |
| transference has the same side effects on the source semaphore's payload as |
| executing a semaphore wait operation. |
| If the semaphore was using a temporarily imported payload, the semaphore's |
| prior permanent payload will be restored. |
| |
| ifdef::VK_KHR_external_semaphore_win32,VK_KHR_external_semaphore_fd[] |
| [NOTE] |
| .Note |
| ==== |
| The |
| ifdef::VK_KHR_external_semaphore_win32+VK_KHR_external_semaphore_fd[tables] |
| ifndef::VK_KHR_external_semaphore_win32+VK_KHR_external_semaphore_fd[table] |
| ifdef::VK_KHR_external_semaphore_win32[] |
| <<synchronization-semaphore-handletypes-win32,Handle Types Supported by |
| VkImportSemaphoreWin32HandleInfoKHR>> |
| endif::VK_KHR_external_semaphore_win32[] |
| ifdef::VK_KHR_external_semaphore_win32+VK_KHR_external_semaphore_fd[and] |
| ifdef::VK_KHR_external_semaphore_fd[] |
| <<synchronization-semaphore-handletypes-fd,Handle Types Supported by |
| VkImportSemaphoreFdInfoKHR>> |
| endif::VK_KHR_external_semaphore_fd[] |
| ifdef::VK_KHR_external_semaphore_win32+VK_KHR_external_semaphore_fd[define] |
| ifndef::VK_KHR_external_semaphore_win32+VK_KHR_external_semaphore_fd[defines] |
| the permanence and transference of each handle type. |
| ==== |
| endif::VK_KHR_external_semaphore_win32,VK_KHR_external_semaphore_fd[] |
| |
| <<fundamentals-threadingbehavior,External synchronization>> allows |
| implementations to modify an object's internal state, i.e. payload, without |
| internal synchronization. |
| However, for semaphores sharing a payload across processes, satisfying the |
| external synchronization requirements of fname:VkSemaphore parameters as if |
| all semaphores in the set were the same object is sometimes infeasible. |
| Satisfying the <<synchronization-semaphores-waiting-state,wait operation |
| state requirements>> would similarly require impractical coordination or |
| levels of trust between processes. |
| Therefore, these constraints only apply to a specific semaphore handle, not |
| to its payload. |
| For distinct semaphore objects which share a payload, if the semaphores are |
| passed to separate queue submission commands concurrently, behavior will be |
| as if the commands were called in an arbitrary sequential order. |
| If the <<synchronization-semaphores-waiting-state,wait operation state |
| requirements>> are violated for the shared payload by a queue submission |
| command, or if a signal operation is queued for a shared payload that is |
| already signaled or has a pending signal operation, effects must: be limited |
| to one or more of the following: |
| |
| * Returning ename:VK_ERROR_INITIALIZATION_FAILED from the command which |
| resulted in the violation. |
| * Losing the logical device on which the violation occured immediately or |
| at a future time, resulting in a ename:VK_ERROR_DEVICE_LOST error from |
| subsequent commands, including the one causing the violation. |
| * Continuing execution of the violating command or operation as if the |
| semaphore wait completed successfully after an implementation-dependent |
| timeout. |
| In this case, the state of the payload becomes undefined, and future |
| operations on semaphores sharing the payload will be subject to these |
| same rules. |
| The semaphore must: be destroyed or have its payload replaced by an |
| import operation to again have a well-defined state. |
| |
| [NOTE] |
| .Note |
| ==== |
| These rules allow processes to synchronize access to shared memory without |
| trusting each other. |
| However, such processes must still be cautious not to use the shared |
| semaphore for more than synchronizing access to the shared memory. |
| For example, a process should not use a shared semaphore as part of an |
| execution dependency chain that, when complete, leads to objects being |
| destroyed, if it does not trust other processes sharing the semaphore |
| payload. |
| ==== |
| |
| When a semaphore is using an imported payload, its |
| slink:VkExportSemaphoreCreateInfo::pname:handleTypes value is that specified |
| when creating the semaphore from which the payload was exported, rather than |
| that specified when creating the semaphore. |
| Additionally, |
| slink:VkExternalSemaphoreProperties::exportFromImportedHandleTypes restricts |
| which handle types can: be exported from such a semaphore based on the |
| specific handle type used to import the current payload. |
| ifdef::VK_KHR_swapchain[] |
| Passing a semaphore to flink:vkAcquireNextImageKHR is equivalent to |
| temporarily importing a semaphore payload to that semaphore. |
| |
| [NOTE] |
| .Note |
| ==== |
| Because the exportable handle types of an imported semaphore correspond to |
| its current imported payload, and flink:vkAcquireNextImageKHR behaves the |
| same as a temporary import operation for which the source semaphore is |
| opaque to the application, applications have no way of determining whether |
| any external handle types can: be exported from a semaphore in this state. |
| Therefore, applications must: not attempt to export external handles from |
| semaphores using a temporarily imported payload from |
| flink:vkAcquireNextImageKHR. |
| ==== |
| endif::VK_KHR_swapchain[] |
| |
| When importing a semaphore payload, it is the responsibility of the |
| application to ensure the external handles meet all valid usage |
| requirements. |
| However, implementations must: perform sufficient validation of external |
| handles to ensure that the operation results in a valid semaphore which will |
| not cause program termination, device loss, queue stalls, or corruption of |
| other resources when used as allowed according to its import parameters, and |
| excepting those side effects allowed for violations of the |
| <<synchronization-semaphores-waiting-state,valid semaphore state for wait |
| operations>> rules. |
| If the external handle provided does not meet these requirements, the |
| implementation must: fail the semaphore payload import operation with the |
| error code ename:VK_ERROR_INVALID_EXTERNAL_HANDLE. |
| |
| endif::VK_VERSION_1_1,VK_KHR_external_semaphore[] |
| |
| ifdef::VK_KHR_external_semaphore_win32[] |
| |
| [open,refpage='vkImportSemaphoreWin32HandleKHR',desc='Import a semaphore from a Windows HANDLE',type='protos'] |
| -- |
| |
| To import a semaphore payload from a Windows handle, call: |
| |
| include::../api/protos/vkImportSemaphoreWin32HandleKHR.txt[] |
| |
| * pname:device is the logical device that created the semaphore. |
| * pname:pImportSemaphoreWin32HandleInfo points to a |
| slink:VkImportSemaphoreWin32HandleInfoKHR structure specifying the |
| semaphore and import parameters. |
| |
| Importing a semaphore payload from Windows handles does not transfer |
| ownership of the handle to the Vulkan implementation. |
| For handle types defined as NT handles, the application must: release |
| ownership using the fname:CloseHandle system call when the handle is no |
| longer needed. |
| |
| Applications can: import the same semaphore payload into multiple instances |
| of Vulkan, into the same instance from which it was exported, and multiple |
| times into a given Vulkan instance. |
| |
| include::../validity/protos/vkImportSemaphoreWin32HandleKHR.txt[] |
| -- |
| |
| [open,refpage='VkImportSemaphoreWin32HandleInfoKHR',desc='Structure specifying Windows handle to import to a semaphore',type='structs'] |
| -- |
| |
| The sname:VkImportSemaphoreWin32HandleInfoKHR structure is defined as: |
| |
| include::../api/structs/VkImportSemaphoreWin32HandleInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:semaphore is the semaphore into which the payload will be |
| imported. |
| * pname:flags is a bitmask of elink:VkSemaphoreImportFlagBits specifying |
| additional parameters for the semaphore payload import operation. |
| * pname:handleType specifies the type of pname:handle. |
| * pname:handle is the external handle to import, or `NULL`. |
| * pname:name is a NULL-terminated UTF-16 string naming the underlying |
| synchronization primitive to import, or `NULL`. |
| |
| The handle types supported by pname:handleType are: |
| |
| [[synchronization-semaphore-handletypes-win32]] |
| .Handle Types Supported by VkImportSemaphoreWin32HandleInfoKHR |
| [width="80%",options="header"] |
| |==== |
| | Handle Type | Transference | Permanence Supported |
| | ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT | Reference | Temporary,Permanent |
| | ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | Reference | Temporary,Permanent |
| | ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT | Reference | Temporary,Permanent |
| |==== |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01140]] |
| pname:handleType must: be a value included in the |
| <<synchronization-semaphore-handletypes-win32,Handle Types Supported by |
| VkImportSemaphoreWin32HandleInfoKHR>> table. |
| * [[VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01466]] |
| If pname:handleType is not |
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT or |
| ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, pname:name |
| must: be `NULL`. |
| * [[VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01467]] |
| If pname:handleType is not `0` and pname:handle is `NULL`, pname:name |
| must: name a valid synchronization primitive of the type specified by |
| pname:handleType. |
| * [[VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01468]] |
| If pname:handleType is not `0` and pname:name is `NULL`, pname:handle |
| must: be a valid handle of the type specified by pname:handleType. |
| * [[VUID-VkImportSemaphoreWin32HandleInfoKHR-handle-01469]] |
| If pname:handle is not `NULL`, pname:name must be `NULL`. |
| * [[VUID-VkImportSemaphoreWin32HandleInfoKHR-handle-01542]] |
| If pname:handle is not `NULL`, it must: obey any requirements listed for |
| pname:handleType in |
| <<external-semaphore-handle-types-compatibility,external semaphore |
| handle types compatibility>>. |
| * [[VUID-VkImportSemaphoreWin32HandleInfoKHR-name-01543]] |
| If pname:name is not `NULL`, it must: obey any requirements listed for |
| pname:handleType in |
| <<external-semaphore-handle-types-compatibility,external semaphore |
| handle types compatibility>>. |
| **** |
| |
| include::../validity/structs/VkImportSemaphoreWin32HandleInfoKHR.txt[] |
| -- |
| |
| endif::VK_KHR_external_semaphore_win32[] |
| |
| ifdef::VK_KHR_external_semaphore_fd[] |
| |
| [open,refpage='vkImportSemaphoreFdKHR',desc='Import a semaphore from a POSIX file descriptor',type='protos'] |
| -- |
| |
| To import a semaphore payload from a POSIX file descriptor, call: |
| |
| include::../api/protos/vkImportSemaphoreFdKHR.txt[] |
| |
| * pname:device is the logical device that created the semaphore. |
| * pname:pImportSemaphoreFdInfo points to a |
| slink:VkImportSemaphoreFdInfoKHR structure specifying the semaphore and |
| import parameters. |
| |
| Importing a semaphore payload from a file descriptor transfers ownership of |
| the file descriptor from the application to the Vulkan implementation. |
| The application must: not perform any operations on the file descriptor |
| after a successful import. |
| |
| Applications can: import the same semaphore payload into multiple instances |
| of Vulkan, into the same instance from which it was exported, and multiple |
| times into a given Vulkan instance. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkImportSemaphoreFdKHR-semaphore-01142]] |
| pname:semaphore must: not be associated with any queue command that has |
| not yet completed execution on that queue |
| **** |
| |
| include::../validity/protos/vkImportSemaphoreFdKHR.txt[] |
| -- |
| |
| [open,refpage='VkImportSemaphoreFdInfoKHR',desc='Structure specifying POSIX file descriptor to import to a semaphore',type='structs'] |
| -- |
| |
| The sname:VkImportSemaphoreFdInfoKHR structure is defined as: |
| |
| include::../api/structs/VkImportSemaphoreFdInfoKHR.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:semaphore is the semaphore into which the payload will be |
| imported. |
| * pname:flags is a bitmask of elink:VkSemaphoreImportFlagBits specifying |
| additional parameters for the semaphore payload import operation. |
| * pname:handleType specifies the type of pname:fd. |
| * pname:fd is the external handle to import. |
| |
| The handle types supported by pname:handleType are: |
| |
| [[synchronization-semaphore-handletypes-fd]] |
| .Handle Types Supported by VkImportSemaphoreFdInfoKHR |
| [width="80%",options="header"] |
| |==== |
| | Handle Type | Transference | Permanence Supported |
| | ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | Reference | Temporary,Permanent |
| | ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT | Copy | Temporary |
| |==== |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkImportSemaphoreFdInfoKHR-handleType-01143]] |
| pname:handleType must: be a value included in the |
| <<synchronization-semaphore-handletypes-fd,Handle Types Supported by |
| VkImportSemaphoreFdInfoKHR>> table. |
| * [[VUID-VkImportSemaphoreFdInfoKHR-fd-01544]] |
| pname:fd must: obey any requirements listed for pname:handleType in |
| <<external-semaphore-handle-types-compatibility,external semaphore |
| handle types compatibility>>. |
| **** |
| |
| include::../validity/structs/VkImportSemaphoreFdInfoKHR.txt[] |
| -- |
| |
| endif::VK_KHR_external_semaphore_fd[] |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_external_semaphore[] |
| ifdef::VK_KHR_external_semaphore_win32,VK_KHR_external_semaphore_fd[] |
| |
| [open,refpage='VkSemaphoreImportFlagBits',desc='Bitmask specifying additional parameters of semaphore payload import',type='enums'] |
| -- |
| |
| Additional parameters of a semaphore import operation are specified by |
| ifdef::VK_KHR_external_semaphore_win32[] |
| slink:VkImportSemaphoreWin32HandleInfoKHR::pname:flags |
| endif::VK_KHR_external_semaphore_win32[] |
| ifdef::VK_KHR_external_semaphore_win32+VK_KHR_external_semaphore_fd[or] |
| ifdef::VK_KHR_external_semaphore_fd[] |
| slink:VkImportSemaphoreFdInfoKHR::pname:flags |
| endif::VK_KHR_external_semaphore_fd[] |
| . |
| Bits which can be set include: |
| |
| include::../api/enums/VkSemaphoreImportFlagBits.txt[] |
| |
| ifdef::VK_KHR_external_semaphore[] |
| or the equivalent |
| |
| include::../api/enums/VkSemaphoreImportFlagBitsKHR.txt[] |
| endif::VK_KHR_external_semaphore[] |
| |
| These bits have the following meanings: |
| |
| * ename:VK_SEMAPHORE_IMPORT_TEMPORARY_BIT specifies that the semaphore |
| payload will be imported only temporarily, as described in |
| <<synchronization-semaphores-importing,Importing Semaphore Payloads>>, |
| regardless of the permanence of pname:handleType. |
| |
| -- |
| |
| [open,refpage='VkSemaphoreImportFlags',desc='Bitmask of VkSemaphoreImportFlagBits',type='enums'] |
| -- |
| include::../api/flags/VkSemaphoreImportFlags.txt[] |
| |
| ifdef::VK_KHR_external_semaphore[] |
| or the equivalent |
| |
| include::../api/flags/VkSemaphoreImportFlagsKHR.txt[] |
| endif::VK_KHR_external_semaphore[] |
| |
| sname:VkSemaphoreImportFlags is a bitmask type for setting a mask of zero or |
| more slink:VkSemaphoreImportFlagBits. |
| -- |
| |
| endif::VK_KHR_external_semaphore_win32,VK_KHR_external_semaphore_fd[] |
| endif::VK_VERSION_1_1,VK_KHR_external_semaphore[] |
| |
| |
| [[synchronization-events]] |
| == Events |
| |
| [open,refpage='VkEvent',desc='Opaque handle to an event object',type='handles'] |
| -- |
| |
| Events are a synchronization primitive that can: be used to insert a |
| fine-grained dependency between commands submitted to the same queue, or |
| between the host and a queue. |
| Events must: not be used to insert a dependency between commands submitted |
| to different queues. |
| Events have two states - signaled and unsignaled. |
| An application can: signal an event, or unsignal it, on either the host or |
| the device. |
| A device can: wait for an event to become signaled before executing further |
| operations. |
| No command exists to wait for an event to become signaled on the host, but |
| the current state of an event can: be queried. |
| |
| Events are represented by sname:VkEvent handles: |
| |
| include::../api/handles/VkEvent.txt[] |
| |
| -- |
| |
| [open,refpage='vkCreateEvent',desc='Create a new event object',type='protos'] |
| -- |
| |
| To create an event, call: |
| |
| include::../api/protos/vkCreateEvent.txt[] |
| |
| * pname:device is the logical device that creates the event. |
| * pname:pCreateInfo is a pointer to an instance of the |
| sname:VkEventCreateInfo structure which contains information about how |
| the event is to be created. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| * pname:pEvent points to a handle in which the resulting event object is |
| returned. |
| |
| When created, the event object is in the unsignaled state. |
| |
| include::../validity/protos/vkCreateEvent.txt[] |
| -- |
| |
| [open,refpage='VkEventCreateInfo',desc='Structure specifying parameters of a newly created event',type='structs'] |
| -- |
| |
| The sname:VkEventCreateInfo structure is defined as: |
| |
| include::../api/structs/VkEventCreateInfo.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:flags is reserved for future use. |
| |
| include::../validity/structs/VkEventCreateInfo.txt[] |
| -- |
| |
| [open,refpage='VkEventCreateFlags',desc='Reserved for future use',type='enums'] |
| -- |
| include::../api/flags/VkEventCreateFlags.txt[] |
| |
| sname:VkEventCreateFlags is a bitmask type for setting a mask, but is |
| currently reserved for future use. |
| -- |
| |
| [open,refpage='vkDestroyEvent',desc='Destroy an event object',type='protos'] |
| -- |
| |
| To destroy an event, call: |
| |
| include::../api/protos/vkDestroyEvent.txt[] |
| |
| * pname:device is the logical device that destroys the event. |
| * pname:event is the handle of the event to destroy. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkDestroyEvent-event-01145]] |
| All submitted commands that refer to pname:event must: have completed |
| execution |
| * [[VUID-vkDestroyEvent-event-01146]] |
| If sname:VkAllocationCallbacks were provided when pname:event was |
| created, a compatible set of callbacks must: be provided here |
| * [[VUID-vkDestroyEvent-event-01147]] |
| If no sname:VkAllocationCallbacks were provided when pname:event was |
| created, pname:pAllocator must: be `NULL` |
| **** |
| |
| include::../validity/protos/vkDestroyEvent.txt[] |
| -- |
| |
| [open,refpage='vkGetEventStatus',desc='Retrieve the status of an event object',type='protos'] |
| -- |
| |
| To query the state of an event from the host, call: |
| |
| include::../api/protos/vkGetEventStatus.txt[] |
| |
| * pname:device is the logical device that owns the event. |
| * pname:event is the handle of the event to query. |
| |
| Upon success, fname:vkGetEventStatus returns the state of the event object |
| with the following return codes: |
| |
| .Event Object Status Codes |
| [width="80%",options="header"] |
| |==== |
| | Status | Meaning |
| | ename:VK_EVENT_SET | The event specified by pname:event is signaled. |
| | ename:VK_EVENT_RESET | The event specified by pname:event is unsignaled. |
| |==== |
| |
| If a fname:vkCmdSetEvent or fname:vkCmdResetEvent command is in a command |
| buffer that is in the <<commandbuffers-lifecycle, pending state>>, then the |
| value returned by this command may: immediately be out of date. |
| |
| The state of an event can: be updated by the host. |
| The state of the event is immediately changed, and subsequent calls to |
| fname:vkGetEventStatus will return the new state. |
| If an event is already in the requested state, then updating it to the same |
| state has no effect. |
| |
| include::../validity/protos/vkGetEventStatus.txt[] |
| -- |
| |
| [[synchronization-events-signaling-host]] |
| [open,refpage='vkSetEvent',desc='Set an event to signaled state',type='protos'] |
| -- |
| |
| To set the state of an event to signaled from the host, call: |
| |
| include::../api/protos/vkSetEvent.txt[] |
| |
| * pname:device is the logical device that owns the event. |
| * pname:event is the event to set. |
| |
| When flink:vkSetEvent is executed on the host, it defines an _event signal |
| operation_ which sets the event to the signaled state. |
| |
| If pname:event is already in the signaled state when flink:vkSetEvent is |
| executed, then flink:vkSetEvent has no effect, and no event signal operation |
| occurs. |
| |
| include::../validity/protos/vkSetEvent.txt[] |
| -- |
| |
| [[synchronization-events-unsignaling-host]] |
| [open,refpage='vkResetEvent',desc='Reset an event to non-signaled state',type='protos'] |
| -- |
| |
| To set the state of an event to unsignaled from the host, call: |
| |
| include::../api/protos/vkResetEvent.txt[] |
| |
| * pname:device is the logical device that owns the event. |
| * pname:event is the event to reset. |
| |
| When flink:vkResetEvent is executed on the host, it defines an _event |
| unsignal operation_ which resets the event to the unsignaled state. |
| |
| If pname:event is already in the unsignaled state when flink:vkResetEvent is |
| executed, then flink:vkResetEvent has no effect, and no event unsignal |
| operation occurs. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkResetEvent-event-01148]] |
| pname:event must: not be waited on by a fname:vkCmdWaitEvents command |
| that is currently executing |
| **** |
| |
| include::../validity/protos/vkResetEvent.txt[] |
| -- |
| |
| |
| The state of an event can: also be updated on the device by commands |
| inserted in command buffers. |
| |
| [[synchronization-events-signaling-device]] |
| [open,refpage='vkCmdSetEvent',desc='Set an event object to signaled state',type='protos'] |
| -- |
| |
| To set the state of an event to signaled from a device, call: |
| |
| include::../api/protos/vkCmdSetEvent.txt[] |
| |
| * pname:commandBuffer is the command buffer into which the command is |
| recorded. |
| * pname:event is the event that will be signaled. |
| * pname:stageMask specifies the <<synchronization-pipeline-stages,source |
| stage mask>> used to determine when the pname:event is signaled. |
| |
| When flink:vkCmdSetEvent is submitted to a queue, it defines an execution |
| dependency on commands that were submitted before it, and defines an event |
| signal operation which sets the event to the signaled state. |
| |
| The first <<synchronization-dependencies-scopes, synchronization scope>> |
| includes all commands that occur earlier in |
| <<synchronization-submission-order,submission order>>. |
| The synchronization scope is limited to operations on the pipeline stages |
| determined by the <<synchronization-pipeline-stages-masks, source stage |
| mask>> specified by pname:stageMask. |
| |
| The second <<synchronization-dependencies-scopes, synchronization scope>> |
| includes only the event signal operation. |
| |
| If pname:event is already in the signaled state when flink:vkCmdSetEvent is |
| executed on the device, then flink:vkCmdSetEvent has no effect, no event |
| signal operation occurs, and no execution dependency is generated. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCmdSetEvent-stageMask-01149]] |
| pname:stageMask must: not include ename:VK_PIPELINE_STAGE_HOST_BIT |
| * [[VUID-vkCmdSetEvent-stageMask-01150]] |
| If the <<features-features-geometryShader,geometry shaders>> feature is |
| not enabled, pname:stageMask must: not contain |
| ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
| * [[VUID-vkCmdSetEvent-stageMask-01151]] |
| If the <<features-features-tessellationShader,tessellation shaders>> |
| feature is not enabled, pname:stageMask must: not contain |
| ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or |
| ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| * [[VUID-vkCmdSetEvent-commandBuffer-01152]] |
| pname:commandBuffer's current device mask must: include exactly one |
| physical device. |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| **** |
| |
| include::../validity/protos/vkCmdSetEvent.txt[] |
| -- |
| |
| [[synchronization-events-unsignaling-device]] |
| [open,refpage='vkCmdResetEvent',desc='Reset an event object to non-signaled state',type='protos'] |
| -- |
| |
| To set the state of an event to unsignaled from a device, call: |
| |
| include::../api/protos/vkCmdResetEvent.txt[] |
| |
| * pname:commandBuffer is the command buffer into which the command is |
| recorded. |
| * pname:event is the event that will be unsignaled. |
| * pname:stageMask is a bitmask of elink:VkPipelineStageFlagBits specifying |
| the <<synchronization-pipeline-stages, source stage mask>> used to |
| determine when the pname:event is unsignaled. |
| |
| When flink:vkCmdResetEvent is submitted to a queue, it defines an execution |
| dependency on commands that were submitted before it, and defines an event |
| unsignal operation which resets the event to the unsignaled state. |
| |
| The first <<synchronization-dependencies-scopes, synchronization scope>> |
| includes all commands that occur earlier in |
| <<synchronization-submission-order,submission order>>. |
| The synchronization scope is limited to operations on the pipeline stages |
| determined by the <<synchronization-pipeline-stages-masks, source stage |
| mask>> specified by pname:stageMask. |
| |
| The second <<synchronization-dependencies-scopes, synchronization scope>> |
| includes only the event unsignal operation. |
| |
| If pname:event is already in the unsignaled state when flink:vkCmdResetEvent |
| is executed on the device, then flink:vkCmdResetEvent has no effect, no |
| event unsignal operation occurs, and no execution dependency is generated. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCmdResetEvent-stageMask-01153]] |
| pname:stageMask must: not include ename:VK_PIPELINE_STAGE_HOST_BIT |
| * [[VUID-vkCmdResetEvent-stageMask-01154]] |
| If the <<features-features-geometryShader,geometry shaders>> feature is |
| not enabled, pname:stageMask must: not contain |
| ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
| * [[VUID-vkCmdResetEvent-stageMask-01155]] |
| If the <<features-features-tessellationShader,tessellation shaders>> |
| feature is not enabled, pname:stageMask must: not contain |
| ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or |
| ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| * [[VUID-vkCmdResetEvent-event-01156]] |
| When this command executes, pname:event must: not be waited on by a |
| fname:vkCmdWaitEvents command that is currently executing |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| * [[VUID-vkCmdResetEvent-commandBuffer-01157]] |
| pname:commandBuffer's current device mask must: include exactly one |
| physical device. |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| **** |
| |
| include::../validity/protos/vkCmdResetEvent.txt[] |
| -- |
| |
| [open,refpage='vkCmdWaitEvents',desc='Wait for one or more events and insert a set of memory',type='protos'] |
| -- |
| |
| To wait for one or more events to enter the signaled state on a device, |
| call: |
| |
| [[synchronization-events-waiting-device]] |
| include::../api/protos/vkCmdWaitEvents.txt[] |
| |
| * pname:commandBuffer is the command buffer into which the command is |
| recorded. |
| * pname:eventCount is the length of the pname:pEvents array. |
| * pname:pEvents is an array of event object handles to wait on. |
| * pname:srcStageMask is a bitmask of elink:VkPipelineStageFlagBits |
| specifying the <<synchronization-pipeline-stages, source stage mask>>. |
| * pname:dstStageMask is a bitmask of elink:VkPipelineStageFlagBits |
| specifying the <<synchronization-pipeline-stages, destination stage |
| mask>>. |
| * pname:memoryBarrierCount is the length of the pname:pMemoryBarriers |
| array. |
| * pname:pMemoryBarriers is a pointer to an array of slink:VkMemoryBarrier |
| structures. |
| * pname:bufferMemoryBarrierCount is the length of the |
| pname:pBufferMemoryBarriers array. |
| * pname:pBufferMemoryBarriers is a pointer to an array of |
| slink:VkBufferMemoryBarrier structures. |
| * pname:imageMemoryBarrierCount is the length of the |
| pname:pImageMemoryBarriers array. |
| * pname:pImageMemoryBarriers is a pointer to an array of |
| slink:VkImageMemoryBarrier structures. |
| |
| When fname:vkCmdWaitEvents is submitted to a queue, it defines a memory |
| dependency between prior event signal operations on the same queue or the |
| host, and subsequent commands. |
| fname:vkCmdWaitEvents must: not be used to wait on event signal operations |
| occuring on other queues. |
| |
| The first synchronization scope only includes event signal operations that |
| operate on members of pname:pEvents, and the operations that happened-before |
| the event signal operations. |
| Event signal operations performed by flink:vkCmdSetEvent that occur earlier |
| in <<synchronization-submission-order,submission order>> are included in the |
| first synchronization scope, if the <<synchronization-pipeline-stages-order, |
| logically latest>> pipeline stage in their pname:stageMask parameter is |
| <<synchronization-pipeline-stages-order, logically earlier>> than or equal |
| to the <<synchronization-pipeline-stages-order, logically latest>> pipeline |
| stage in pname:srcStageMask. |
| Event signal operations performed by flink:vkSetEvent are only included in |
| the first synchronization scope if ename:VK_PIPELINE_STAGE_HOST_BIT is |
| included in pname:srcStageMask. |
| |
| The second <<synchronization-dependencies-scopes, synchronization scope>> |
| includes all commands that occur later in |
| <<synchronization-submission-order,submission order>>. |
| The second synchronization scope is limited to operations on the pipeline |
| stages determined by the <<synchronization-pipeline-stages-masks, |
| destination stage mask>> specified by pname:dstStageMask. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access in the pipeline stages determined by the |
| <<synchronization-pipeline-stages-masks, source stage mask>> specified by |
| pname:srcStageMask. |
| Within that, the first access scope only includes the first access scopes |
| defined by elements of the pname:pMemoryBarriers, |
| pname:pBufferMemoryBarriers and pname:pImageMemoryBarriers arrays, which |
| each define a set of <<synchronization-memory-barriers, memory barriers>>. |
| If no memory barriers are specified, then the first access scope includes no |
| accesses. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access in the pipeline stages determined by the |
| <<synchronization-pipeline-stages-masks, destination stage mask>> specified |
| by pname:dstStageMask. |
| Within that, the second access scope only includes the second access scopes |
| defined by elements of the pname:pMemoryBarriers, |
| pname:pBufferMemoryBarriers and pname:pImageMemoryBarriers arrays, which |
| each define a set of <<synchronization-memory-barriers, memory barriers>>. |
| If no memory barriers are specified, then the second access scope includes |
| no accesses. |
| |
| [NOTE] |
| .Note |
| ==== |
| flink:vkCmdWaitEvents is used with flink:vkCmdSetEvent to define a memory |
| dependency between two sets of action commands, roughly in the same way as |
| pipeline barriers, but split into two commands such that work between the |
| two may: execute unhindered. |
| ==== |
| |
| [NOTE] |
| .Note |
| ==== |
| Applications should: be careful to avoid race conditions when using events. |
| There is no direct ordering guarantee between a flink:vkCmdResetEvent |
| command and a flink:vkCmdWaitEvents command submitted after it, so some |
| other execution dependency must: be included between these commands (e.g. a |
| semaphore). |
| ==== |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCmdWaitEvents-srcStageMask-01158]] |
| pname:srcStageMask must: be the bitwise OR of the pname:stageMask |
| parameter used in previous calls to fname:vkCmdSetEvent with any of the |
| members of pname:pEvents and ename:VK_PIPELINE_STAGE_HOST_BIT if any of |
| the members of pname:pEvents was set using fname:vkSetEvent |
| * [[VUID-vkCmdWaitEvents-srcStageMask-01159]] |
| If the <<features-features-geometryShader,geometry shaders>> feature is |
| not enabled, pname:srcStageMask must: not contain |
| ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
| * [[VUID-vkCmdWaitEvents-dstStageMask-01160]] |
| If the <<features-features-geometryShader,geometry shaders>> feature is |
| not enabled, pname:dstStageMask must: not contain |
| ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
| * [[VUID-vkCmdWaitEvents-srcStageMask-01161]] |
| If the <<features-features-tessellationShader,tessellation shaders>> |
| feature is not enabled, pname:srcStageMask must: not contain |
| ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or |
| ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| * [[VUID-vkCmdWaitEvents-dstStageMask-01162]] |
| If the <<features-features-tessellationShader,tessellation shaders>> |
| feature is not enabled, pname:dstStageMask must: not contain |
| ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or |
| ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| * [[VUID-vkCmdWaitEvents-pEvents-01163]] |
| If pname:pEvents includes one or more events that will be signaled by |
| fname:vkSetEvent after pname:commandBuffer has been submitted to a |
| queue, then fname:vkCmdWaitEvents must: not be called inside a render |
| pass instance |
| * [[VUID-vkCmdWaitEvents-srcStageMask-01164]] |
| Any pipeline stage included in pname:srcStageMask or pname:dstStageMask |
| must: be supported by the capabilities of the queue family specified by |
| the pname:queueFamilyIndex member of the slink:VkCommandPoolCreateInfo |
| structure that was used to create the sname:VkCommandPool that |
| pname:commandBuffer was allocated from, as specified in the |
| <<synchronization-pipeline-stages-supported, table of supported pipeline |
| stages>>. |
| * [[VUID-vkCmdWaitEvents-pMemoryBarriers-01165]] |
| Each element of pname:pMemoryBarriers, pname:pBufferMemoryBarriers or |
| pname:pImageMemoryBarriers must: not have any access flag included in |
| its pname:srcAccessMask member if that bit is not supported by any of |
| the pipeline stages in pname:srcStageMask, as specified in the |
| <<synchronization-access-types-supported, table of supported access |
| types>>. |
| * [[VUID-vkCmdWaitEvents-pMemoryBarriers-01166]] |
| Each element of pname:pMemoryBarriers, pname:pBufferMemoryBarriers or |
| pname:pImageMemoryBarriers must: not have any access flag included in |
| its pname:dstAccessMask member if that bit is not supported by any of |
| the pipeline stages in pname:dstStageMask, as specified in the |
| <<synchronization-access-types-supported, table of supported access |
| types>>. |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| * [[VUID-vkCmdWaitEvents-commandBuffer-01167]] |
| pname:commandBuffer's current device mask must: include exactly one |
| physical device. |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| **** |
| |
| include::../validity/protos/vkCmdWaitEvents.txt[] |
| -- |
| |
| |
| [[synchronization-pipeline-barriers]] |
| == Pipeline Barriers |
| |
| flink:vkCmdPipelineBarrier is a synchronization command that inserts a |
| dependency between commands submitted to the same queue, or between commands |
| in the same subpass. |
| |
| [open,refpage='vkCmdPipelineBarrier',desc='Insert a memory dependency',type='protos'] |
| -- |
| |
| To record a pipeline barrier, call: |
| |
| include::../api/protos/vkCmdPipelineBarrier.txt[] |
| |
| * pname:commandBuffer is the command buffer into which the command is |
| recorded. |
| * pname:srcStageMask is a bitmask of elink:VkPipelineStageFlagBits |
| specifying the <<synchronization-pipeline-stages-masks, source stage |
| mask>>. |
| * pname:dstStageMask is a bitmask of elink:VkPipelineStageFlagBits |
| specifying the <<synchronization-pipeline-stages-masks, destination |
| stage mask>>. |
| * pname:dependencyFlags is a bitmask of elink:VkDependencyFlagBits |
| specifying how execution and memory dependencies are formed. |
| * pname:memoryBarrierCount is the length of the pname:pMemoryBarriers |
| array. |
| * pname:pMemoryBarriers is a pointer to an array of slink:VkMemoryBarrier |
| structures. |
| * pname:bufferMemoryBarrierCount is the length of the |
| pname:pBufferMemoryBarriers array. |
| * pname:pBufferMemoryBarriers is a pointer to an array of |
| slink:VkBufferMemoryBarrier structures. |
| * pname:imageMemoryBarrierCount is the length of the |
| pname:pImageMemoryBarriers array. |
| * pname:pImageMemoryBarriers is a pointer to an array of |
| slink:VkImageMemoryBarrier structures. |
| |
| When flink:vkCmdPipelineBarrier is submitted to a queue, it defines a memory |
| dependency between commands that were submitted before it, and those |
| submitted after it. |
| |
| If flink:vkCmdPipelineBarrier was recorded outside a render pass instance, |
| the first <<synchronization-dependencies-scopes, synchronization scope>> |
| includes all commands that occur earlier in |
| <<synchronization-submission-order,submission order>>. |
| If flink:vkCmdPipelineBarrier was recorded inside a render pass instance, |
| the first synchronization scope includes only commands that occur earlier in |
| <<synchronization-submission-order,submission order>> within the same |
| subpass. |
| In either case, the first synchronization scope is limited to operations on |
| the pipeline stages determined by the |
| <<synchronization-pipeline-stages-masks, source stage mask>> specified by |
| pname:srcStageMask. |
| |
| If flink:vkCmdPipelineBarrier was recorded outside a render pass instance, |
| the second <<synchronization-dependencies-scopes, synchronization scope>> |
| includes all commands that occur later in |
| <<synchronization-submission-order,submission order>>. |
| If flink:vkCmdPipelineBarrier was recorded inside a render pass instance, |
| the second synchronization scope includes only commands that occur later in |
| <<synchronization-submission-order,submission order>> within the same |
| subpass. |
| In either case, the second synchronization scope is limited to operations on |
| the pipeline stages determined by the |
| <<synchronization-pipeline-stages-masks, destination stage mask>> specified |
| by pname:dstStageMask. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access in the pipeline stages determined by the |
| <<synchronization-pipeline-stages-masks, source stage mask>> specified by |
| pname:srcStageMask. |
| Within that, the first access scope only includes the first access scopes |
| defined by elements of the pname:pMemoryBarriers, |
| pname:pBufferMemoryBarriers and pname:pImageMemoryBarriers arrays, which |
| each define a set of <<synchronization-memory-barriers, memory barriers>>. |
| If no memory barriers are specified, then the first access scope includes no |
| accesses. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access in the pipeline stages determined by the |
| <<synchronization-pipeline-stages-masks, destination stage mask>> specified |
| by pname:dstStageMask. |
| Within that, the second access scope only includes the second access scopes |
| defined by elements of the pname:pMemoryBarriers, |
| pname:pBufferMemoryBarriers and pname:pImageMemoryBarriers arrays, which |
| each define a set of <<synchronization-memory-barriers, memory barriers>>. |
| If no memory barriers are specified, then the second access scope includes |
| no accesses. |
| |
| If pname:dependencyFlags includes ename:VK_DEPENDENCY_BY_REGION_BIT, then |
| any dependency between <<synchronization-framebuffer-regions, |
| framebuffer-space>> pipeline stages is |
| <<synchronization-framebuffer-regions, framebuffer-local>> - otherwise it is |
| <<synchronization-framebuffer-regions, framebuffer-global>>. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCmdPipelineBarrier-srcStageMask-01168]] |
| If the <<features-features-geometryShader,geometry shaders>> feature is |
| not enabled, pname:srcStageMask must: not contain |
| ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
| * [[VUID-vkCmdPipelineBarrier-dstStageMask-01169]] |
| If the <<features-features-geometryShader,geometry shaders>> feature is |
| not enabled, pname:dstStageMask must: not contain |
| ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
| * [[VUID-vkCmdPipelineBarrier-srcStageMask-01170]] |
| If the <<features-features-tessellationShader,tessellation shaders>> |
| feature is not enabled, pname:srcStageMask must: not contain |
| ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or |
| ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| * [[VUID-vkCmdPipelineBarrier-dstStageMask-01171]] |
| If the <<features-features-tessellationShader,tessellation shaders>> |
| feature is not enabled, pname:dstStageMask must: not contain |
| ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or |
| ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
| * [[VUID-vkCmdPipelineBarrier-pDependencies-02024]] |
| If fname:vkCmdPipelineBarrier is called within a render pass instance, |
| the render pass must: have been created with at least one |
| sname:VkSubpassDependency instance in |
| sname:VkRenderPassCreateInfo::pname:pDependencies that expresses a |
| dependency from the current subpass to itself, and for which |
| pname:srcStageMask contains a subset of the bit values in |
| sname:VkSubpassDependency::pname:srcStageMask, pname:dstStageMask |
| contains a subset of the bit values in |
| sname:VkSubpassDependency::pname:dstStageMask, and pname:dependencyFlags |
| is equal to sname:VkSubpassDependency::pname:dependencyFlags. |
| * [[VUID-vkCmdPipelineBarrier-pMemoryBarriers-02026]] |
| If fname:vkCmdPipelineBarrier is called within a render pass instance, |
| for each element of pname:pMemoryBarriers and |
| pname:pImageMemoryBarriers, the render pass must: have been defined with |
| a sname:VkSubpassDependency self-dependency for the current subpass with |
| valid pname:srcStageMask, pname:dstStageMask, and pname:dependencyFlags |
| values such that stext:Vk*Barrier::pname:srcAccessMask contains a subset |
| of the bit values in sname:VkSubpassDependency::pname:srcAccessMask and |
| stext:Vk*Barrier::pname:dstAccessMask contains a subset of the bit |
| values in sname:VkSubpassDependency::pname:dstAccessMask. |
| * [[VUID-vkCmdPipelineBarrier-bufferMemoryBarrierCount-01178]] |
| If fname:vkCmdPipelineBarrier is called within a render pass instance, |
| pname:bufferMemoryBarrierCount must: be `0` |
| * [[VUID-vkCmdPipelineBarrier-image-01179]] |
| If fname:vkCmdPipelineBarrier is called within a render pass instance, |
| the pname:image member of any element of pname:pImageMemoryBarriers |
| must: be equal to one of the elements of pname:pAttachments that the |
| current pname:framebuffer was created with, that is also referred to by |
| one of the elements of the pname:pColorAttachments, |
| pname:pResolveAttachments or pname:pDepthStencilAttachment members of |
| the sname:VkSubpassDescription instance that the current subpass was |
| created with |
| * [[VUID-vkCmdPipelineBarrier-oldLayout-01180]] |
| If fname:vkCmdPipelineBarrier is called within a render pass instance, |
| the pname:oldLayout and pname:newLayout members of any element of |
| pname:pImageMemoryBarriers must: be equal to the pname:layout member of |
| an element of the pname:pColorAttachments, pname:pResolveAttachments or |
| pname:pDepthStencilAttachment members of the sname:VkSubpassDescription |
| instance that the current subpass was created with, that refers to the |
| same pname:image |
| * [[VUID-vkCmdPipelineBarrier-oldLayout-01181]] |
| If fname:vkCmdPipelineBarrier is called within a render pass instance, |
| the pname:oldLayout and pname:newLayout members of an element of |
| pname:pImageMemoryBarriers must: be equal |
| * [[VUID-vkCmdPipelineBarrier-srcQueueFamilyIndex-01182]] |
| If fname:vkCmdPipelineBarrier is called within a render pass instance, |
| the pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex members of |
| any element of pname:pImageMemoryBarriers must: be |
| ename:VK_QUEUE_FAMILY_IGNORED |
| * [[VUID-vkCmdPipelineBarrier-srcStageMask-01183]] |
| Any pipeline stage included in pname:srcStageMask or pname:dstStageMask |
| must: be supported by the capabilities of the queue family specified by |
| the pname:queueFamilyIndex member of the slink:VkCommandPoolCreateInfo |
| structure that was used to create the sname:VkCommandPool that |
| pname:commandBuffer was allocated from, as specified in the |
| <<synchronization-pipeline-stages-supported, table of supported pipeline |
| stages>>. |
| * [[VUID-vkCmdPipelineBarrier-pMemoryBarriers-01184]] |
| Each element of pname:pMemoryBarriers, pname:pBufferMemoryBarriers and |
| pname:pImageMemoryBarriers must: not have any access flag included in |
| its pname:srcAccessMask member if that bit is not supported by any of |
| the pipeline stages in pname:srcStageMask, as specified in the |
| <<synchronization-access-types-supported, table of supported access |
| types>>. |
| * [[VUID-vkCmdPipelineBarrier-pMemoryBarriers-01185]] |
| Each element of pname:pMemoryBarriers, pname:pBufferMemoryBarriers and |
| pname:pImageMemoryBarriers must: not have any access flag included in |
| its pname:dstAccessMask member if that bit is not supported by any of |
| the pipeline stages in pname:dstStageMask, as specified in the |
| <<synchronization-access-types-supported, table of supported access |
| types>>. |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| * [[VUID-vkCmdPipelineBarrier-dependencyFlags-01186]] |
| If fname:vkCmdPipelineBarrier is called outside of a render pass |
| instance, pname:dependencyFlags must: not include |
| ename:VK_DEPENDENCY_VIEW_LOCAL_BIT |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| **** |
| |
| include::../validity/protos/vkCmdPipelineBarrier.txt[] |
| -- |
| |
| [open,refpage='VkDependencyFlagBits',desc='Bitmask specifying how execution and memory dependencies are formed',type='enums'] |
| -- |
| |
| Bits which can: be set in fname:vkCmdPipelineBarrier::pname:dependencyFlags, |
| specifying how execution and memory dependencies are formed, are: |
| |
| include::../api/enums/VkDependencyFlagBits.txt[] |
| |
| * ename:VK_DEPENDENCY_BY_REGION_BIT specifies that dependencies will be |
| <<synchronization-framebuffer-regions, framebuffer-local>>. |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| * ename:VK_DEPENDENCY_VIEW_LOCAL_BIT specifies that a |
| <<synchronization-pipeline-barriers-subpass-self-dependencies, subpass |
| has more than one view>>. |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| * ename:VK_DEPENDENCY_DEVICE_GROUP_BIT specifies that dependencies are |
| <<synchronization-device-local-dependencies, non-device-local |
| dependency>>. |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| |
| -- |
| |
| [open,refpage='VkDependencyFlags',desc='Bitmask of VkDependencyFlagBits',type='enums'] |
| -- |
| include::../api/flags/VkDependencyFlags.txt[] |
| |
| sname:VkDependencyFlags is a bitmask type for setting a mask of zero or more |
| slink:VkDependencyFlagBits. |
| -- |
| |
| |
| [[synchronization-pipeline-barriers-subpass-self-dependencies]] |
| === Subpass Self-dependency |
| |
| If fname:vkCmdPipelineBarrier is called inside a render pass instance, the |
| following restrictions apply. |
| For a given subpass to allow a pipeline barrier, the render pass must: |
| declare a _self-dependency_ from that subpass to itself. |
| That is, there must: exist a sname:VkSubpassDependency in the subpass |
| dependency list for the render pass with pname:srcSubpass and |
| pname:dstSubpass equal to that subpass index. |
| More than one self-dependency can: be declared for each subpass. |
| Self-dependencies must: only include pipeline stage bits that are graphics |
| stages. |
| Self-dependencies must: not have any earlier pipeline stages depend on any |
| later pipeline stages (according to the order of |
| <<synchronization-pipeline-stages-types,graphics pipeline stages>>), unless |
| all of the stages are |
| <<synchronization-framebuffer-regions,framebuffer-space stages>>. |
| If the source and destination stage masks both include framebuffer-space |
| stages, then pname:dependencyFlags must: include |
| ename:VK_DEPENDENCY_BY_REGION_BIT. |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| If the subpass has more than one view, then pname:dependencyFlags must: |
| include ename:VK_DEPENDENCY_VIEW_LOCAL_BIT. |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| |
| A fname:vkCmdPipelineBarrier command inside a render pass instance must: be |
| a _subset_ of one of the self-dependencies of the subpass it is used in, |
| meaning that the stage masks and access masks must: each include only a |
| subset of the bits of the corresponding mask in that self-dependency. |
| If the self-dependency has ename:VK_DEPENDENCY_BY_REGION_BIT |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| or ename:VK_DEPENDENCY_VIEW_LOCAL_BIT |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| set, then so must: the pipeline barrier. |
| Pipeline barriers within a render pass instance can: only be types |
| sname:VkMemoryBarrier or sname:VkImageMemoryBarrier. |
| If a sname:VkImageMemoryBarrier is used, the image and image subresource |
| range specified in the barrier must: be a subset of one of the image views |
| used by the framebuffer in the current subpass. |
| Additionally, pname:oldLayout must: be equal to pname:newLayout, and both |
| the pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex must: be |
| ename:VK_QUEUE_FAMILY_IGNORED. |
| |
| |
| [[synchronization-memory-barriers]] |
| == Memory Barriers |
| |
| _Memory barriers_ are used to explicitly control access to buffer and image |
| subresource ranges. |
| Memory barriers are used to <<synchronization-queue-transfers, transfer |
| ownership between queue families>>, |
| <<synchronization-image-layout-transitions, change image layouts>>, and |
| define <<synchronization-dependencies-available-and-visible, availability |
| and visibility operations>>. |
| They explicitly define the <<synchronization-access-types, access types>> |
| and buffer and image subresource ranges that are included in the |
| <<synchronization-dependencies-access-scopes, access scopes>> of a memory |
| dependency that is created by a synchronization command that includes them. |
| |
| |
| [[synchronization-global-memory-barriers]] |
| === Global Memory Barriers |
| |
| Global memory barriers apply to memory accesses involving all memory objects |
| that exist at the time of its execution. |
| |
| [open,refpage='VkMemoryBarrier',desc='Structure specifying a global memory barrier',type='structs'] |
| -- |
| |
| The sname:VkMemoryBarrier structure is defined as: |
| |
| include::../api/structs/VkMemoryBarrier.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:srcAccessMask is a bitmask of elink:VkAccessFlagBits specifying a |
| <<synchronization-access-masks, source access mask>>. |
| * pname:dstAccessMask is a bitmask of elink:VkAccessFlagBits specifying a |
| <<synchronization-access-masks, destination access mask>>. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access types in the <<synchronization-access-masks, source access |
| mask>> specified by pname:srcAccessMask. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access types in the <<synchronization-access-masks, destination |
| access mask>> specified by pname:dstAccessMask. |
| |
| include::../validity/structs/VkMemoryBarrier.txt[] |
| -- |
| |
| |
| [[synchronization-buffer-memory-barriers]] |
| === Buffer Memory Barriers |
| |
| Buffer memory barriers only apply to memory accesses involving a specific |
| buffer range. |
| That is, a memory dependency formed from a buffer memory barrier is |
| <<synchronization-dependencies-access-scopes, scoped>> to access via the |
| specified buffer range. |
| Buffer memory barriers can: also be used to define a |
| <<synchronization-queue-transfers, queue family ownership transfer>> for the |
| specified buffer range. |
| |
| [open,refpage='VkBufferMemoryBarrier',desc='Structure specifying a buffer memory barrier',type='structs'] |
| -- |
| |
| The sname:VkBufferMemoryBarrier structure is defined as: |
| |
| include::../api/structs/VkBufferMemoryBarrier.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:srcAccessMask is a bitmask of elink:VkAccessFlagBits specifying a |
| <<synchronization-access-masks, source access mask>>. |
| * pname:dstAccessMask is a bitmask of elink:VkAccessFlagBits specifying a |
| <<synchronization-access-masks, destination access mask>>. |
| * pname:srcQueueFamilyIndex is the source queue family for a |
| <<synchronization-queue-transfers, queue family ownership transfer>>. |
| * pname:dstQueueFamilyIndex is the destination queue family for a |
| <<synchronization-queue-transfers, queue family ownership transfer>>. |
| * pname:buffer is a handle to the buffer whose backing memory is affected |
| by the barrier. |
| * pname:offset is an offset in bytes into the backing memory for |
| pname:buffer; this is relative to the base offset as bound to the buffer |
| (see flink:vkBindBufferMemory). |
| * pname:size is a size in bytes of the affected area of backing memory for |
| pname:buffer, or ename:VK_WHOLE_SIZE to use the range from pname:offset |
| to the end of the buffer. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access to memory through the specified buffer range, via access |
| types in the <<synchronization-access-masks, source access mask>> specified |
| by pname:srcAccessMask. |
| If pname:srcAccessMask includes ename:VK_ACCESS_HOST_WRITE_BIT, memory |
| writes performed by that access type are also made visible, as that access |
| type is not performed through a resource. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access to memory through the specified buffer range, via access |
| types in the <<synchronization-access-masks, destination access mask>>. |
| specified by pname:dstAccessMask. |
| If pname:dstAccessMask includes ename:VK_ACCESS_HOST_WRITE_BIT or |
| ename:VK_ACCESS_HOST_READ_BIT, available memory writes are also made visible |
| to accesses of those types, as those access types are not performed through |
| a resource. |
| |
| If pname:srcQueueFamilyIndex is not equal to pname:dstQueueFamilyIndex, and |
| pname:srcQueueFamilyIndex is equal to the current queue family, then the |
| memory barrier defines a <<synchronization-queue-transfers-release, queue |
| family release operation>> for the specified buffer range, and the second |
| access scope includes no access, as if pname:dstAccessMask was `0`. |
| |
| If pname:dstQueueFamilyIndex is not equal to pname:srcQueueFamilyIndex, and |
| pname:dstQueueFamilyIndex is equal to the current queue family, then the |
| memory barrier defines a <<synchronization-queue-transfers-acquire, queue |
| family acquire operation>> for the specified buffer range, and the first |
| access scope includes no access, as if pname:srcAccessMask was `0`. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkBufferMemoryBarrier-offset-01187]] |
| pname:offset must: be less than the size of pname:buffer |
| * [[VUID-VkBufferMemoryBarrier-size-01188]] |
| If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be |
| greater than `0` |
| * [[VUID-VkBufferMemoryBarrier-size-01189]] |
| If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be |
| less than or equal to than the size of pname:buffer minus pname:offset |
| ifndef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkBufferMemoryBarrier-buffer-01190]] |
| If pname:buffer was created with a sharing mode of |
| ename:VK_SHARING_MODE_CONCURRENT, pname:srcQueueFamilyIndex and |
| pname:dstQueueFamilyIndex must: both be ename:VK_QUEUE_FAMILY_IGNORED |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| ifdef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkBufferMemoryBarrier-buffer-01191]] |
| If pname:buffer was created with a sharing mode of |
| ename:VK_SHARING_MODE_CONCURRENT, at least one of |
| pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex must: be |
| ename:VK_QUEUE_FAMILY_IGNORED |
| * [[VUID-VkBufferMemoryBarrier-buffer-01763]] |
| If pname:buffer was created with a sharing mode of |
| ename:VK_SHARING_MODE_CONCURRENT, and one of pname:srcQueueFamilyIndex |
| and pname:dstQueueFamilyIndex is ename:VK_QUEUE_FAMILY_IGNORED, the |
| other must: be ename:VK_QUEUE_FAMILY_IGNORED or a special queue family |
| reserved for external memory ownership transfers, as described in |
| <<synchronization-queue-transfers>>. |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| ifndef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkBufferMemoryBarrier-buffer-01192]] |
| If pname:buffer was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE, pname:srcQueueFamilyIndex and |
| pname:dstQueueFamilyIndex must: either both be |
| ename:VK_QUEUE_FAMILY_IGNORED, or both be a valid queue family (see |
| <<devsandqueues-queueprops>>) |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| ifdef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkBufferMemoryBarrier-buffer-01193]] |
| If pname:buffer was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE and pname:srcQueueFamilyIndex is |
| ename:VK_QUEUE_FAMILY_IGNORED, pname:dstQueueFamilyIndex must: also be |
| ename:VK_QUEUE_FAMILY_IGNORED |
| * [[VUID-VkBufferMemoryBarrier-buffer-01764]] |
| If pname:buffer was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE and pname:srcQueueFamilyIndex is not |
| ename:VK_QUEUE_FAMILY_IGNORED, it must: be a valid queue family or a |
| special queue family reserved for external memory transfers, as |
| described in <<synchronization-queue-transfers>>. |
| * [[VUID-VkBufferMemoryBarrier-buffer-01765]] |
| If pname:buffer was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE and pname:dstQueueFamilyIndex is not |
| ename:VK_QUEUE_FAMILY_IGNORED, it must: be a valid queue family or a |
| special queue family reserved for external memory transfers, as |
| described in <<synchronization-queue-transfers>>. |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkBufferMemoryBarrier-buffer-01196]] |
| If pname:buffer was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE, and pname:srcQueueFamilyIndex and |
| pname:dstQueueFamilyIndex are not ename:VK_QUEUE_FAMILY_IGNORED, at |
| least one of them must: be the same as the family of the queue that will |
| execute this barrier |
| * [[VUID-VkBufferMemoryBarrier-buffer-01931]] |
| If pname:buffer is non-sparse then it must: be bound completely and |
| contiguously to a single sname:VkDeviceMemory object |
| **** |
| |
| include::../validity/structs/VkBufferMemoryBarrier.txt[] |
| -- |
| |
| |
| [[synchronization-image-memory-barriers]] |
| === Image Memory Barriers |
| |
| Image memory barriers only apply to memory accesses involving a specific |
| image subresource range. |
| That is, a memory dependency formed from an image memory barrier is |
| <<synchronization-dependencies-access-scopes, scoped>> to access via the |
| specified image subresource range. |
| Image memory barriers can: also be used to define |
| <<synchronization-image-layout-transitions, image layout transitions>> or a |
| <<synchronization-queue-transfers, queue family ownership transfer>> for the |
| specified image subresource range. |
| |
| [open,refpage='VkImageMemoryBarrier',desc='Structure specifying the parameters of an image memory barrier',type='structs'] |
| -- |
| |
| The sname:VkImageMemoryBarrier structure is defined as: |
| |
| include::../api/structs/VkImageMemoryBarrier.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:srcAccessMask is a bitmask of elink:VkAccessFlagBits specifying a |
| <<synchronization-access-masks, source access mask>>. |
| * pname:dstAccessMask is a bitmask of elink:VkAccessFlagBits specifying a |
| <<synchronization-access-masks, destination access mask>>. |
| * pname:oldLayout is the old layout in an |
| <<synchronization-image-layout-transitions, image layout transition>>. |
| * pname:newLayout is the new layout in an |
| <<synchronization-image-layout-transitions, image layout transition>>. |
| * pname:srcQueueFamilyIndex is the source queue family for a |
| <<synchronization-queue-transfers, queue family ownership transfer>>. |
| * pname:dstQueueFamilyIndex is the destination queue family for a |
| <<synchronization-queue-transfers, queue family ownership transfer>>. |
| * pname:image is a handle to the image affected by this barrier. |
| * pname:subresourceRange describes the <<resources-image-views, image |
| subresource range>> within pname:image that is affected by this barrier. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access to memory through the specified image subresource range, |
| via access types in the <<synchronization-access-masks, source access mask>> |
| specified by pname:srcAccessMask. |
| If pname:srcAccessMask includes ename:VK_ACCESS_HOST_WRITE_BIT, memory |
| writes performed by that access type are also made visible, as that access |
| type is not performed through a resource. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> is |
| limited to access to memory through the specified image subresource range, |
| via access types in the <<synchronization-access-masks, destination access |
| mask>> specified by pname:dstAccessMask. |
| If pname:dstAccessMask includes ename:VK_ACCESS_HOST_WRITE_BIT or |
| ename:VK_ACCESS_HOST_READ_BIT, available memory writes are also made visible |
| to accesses of those types, as those access types are not performed through |
| a resource. |
| |
| If pname:srcQueueFamilyIndex is not equal to pname:dstQueueFamilyIndex, and |
| pname:srcQueueFamilyIndex is equal to the current queue family, then the |
| memory barrier defines a <<synchronization-queue-transfers-release, queue |
| family release operation>> for the specified image subresource range, and |
| the second access scope includes no access, as if pname:dstAccessMask was |
| `0`. |
| |
| If pname:dstQueueFamilyIndex is not equal to pname:srcQueueFamilyIndex, and |
| pname:dstQueueFamilyIndex is equal to the current queue family, then the |
| memory barrier defines a <<synchronization-queue-transfers-acquire, queue |
| family acquire operation>> for the specified image subresource range, and |
| the first access scope includes no access, as if pname:srcAccessMask was |
| `0`. |
| |
| If pname:oldLayout is not equal to pname:newLayout, then the memory barrier |
| defines an <<synchronization-image-layout-transitions, image layout |
| transition>> for the specified image subresource range. |
| |
| [[synchronization-image-barrier-layout-transition-order]] |
| Layout transitions that are performed via image memory barriers execute in |
| their entirety in <<synchronization-submission-order, submission order>>, |
| relative to other image layout transitions submitted to the same queue, |
| including those performed by <<renderpass, render passes>>. |
| In effect there is an implicit execution dependency from each such layout |
| transition to all layout transitions previously submitted to the same queue. |
| |
| ifdef::VK_EXT_sample_locations[] |
| |
| The image layout of each image subresource of a depth/stencil image created |
| with ename:VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT is |
| dependent on the last sample locations used to render to the image |
| subresource as a depth/stencil attachment, thus when the pname:image member |
| of an sname:VkImageMemoryBarrier is an image created with this flag the |
| application can: chain a slink:VkSampleLocationsInfoEXT structure to the |
| pname:pNext chain of sname:VkImageMemoryBarrier to specify the sample |
| locations to use during the image layout transition. |
| |
| If the sname:VkSampleLocationsInfoEXT structure in the pname:pNext chain of |
| sname:VkImageMemoryBarrier does not match the sample location state last |
| used to render to the image subresource range specified by |
| pname:subresourceRange or if no sname:VkSampleLocationsInfoEXT structure is |
| in the pname:pNext chain of sname:VkImageMemoryBarrier then the contents of |
| the given image subresource range becomes undefined as if pname:oldLayout |
| would equal ename:VK_IMAGE_LAYOUT_UNDEFINED. |
| |
| endif::VK_EXT_sample_locations[] |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[] |
| |
| If pname:image has a multi-planar format and the image is _disjoint_, then |
| including ename:VK_IMAGE_ASPECT_COLOR_BIT in the pname:aspectMask member of |
| pname:subresourceRange is equivalent to including |
| ename:VK_IMAGE_ASPECT_PLANE_0_BIT, ename:VK_IMAGE_ASPECT_PLANE_1_BIT, and |
| (for three-plane formats only) ename:VK_IMAGE_ASPECT_PLANE_2_BIT. |
| |
| endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[] |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01197]] |
| pname:oldLayout must: be ename:VK_IMAGE_LAYOUT_UNDEFINED or the current |
| layout of the image subresources affected by the barrier |
| * [[VUID-VkImageMemoryBarrier-newLayout-01198]] |
| pname:newLayout must: not be ename:VK_IMAGE_LAYOUT_UNDEFINED or |
| ename:VK_IMAGE_LAYOUT_PREINITIALIZED |
| ifndef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkImageMemoryBarrier-image-01199]] |
| If pname:image was created with a sharing mode of |
| ename:VK_SHARING_MODE_CONCURRENT, pname:srcQueueFamilyIndex and |
| pname:dstQueueFamilyIndex must: both be ename:VK_QUEUE_FAMILY_IGNORED |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| ifdef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkImageMemoryBarrier-image-01381]] |
| If pname:image was created with a sharing mode of |
| ename:VK_SHARING_MODE_CONCURRENT, at least one of |
| pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex must: be |
| ename:VK_QUEUE_FAMILY_IGNORED |
| * [[VUID-VkImageMemoryBarrier-image-01766]] |
| If pname:image was created with a sharing mode of |
| ename:VK_SHARING_MODE_CONCURRENT, and one of pname:srcQueueFamilyIndex |
| and pname:dstQueueFamilyIndex is ename:VK_QUEUE_FAMILY_IGNORED, the |
| other must: be ename:VK_QUEUE_FAMILY_IGNORED or a special queue family |
| reserved for external memory transfers, as described in |
| <<synchronization-queue-transfers>>. |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| ifndef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkImageMemoryBarrier-image-01200]] |
| If pname:image was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE, pname:srcQueueFamilyIndex and |
| pname:dstQueueFamilyIndex must: either both be |
| ename:VK_QUEUE_FAMILY_IGNORED, or both be a valid queue family (see |
| <<devsandqueues-queueprops>>). |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| ifdef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkImageMemoryBarrier-image-01201]] |
| If pname:image was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE and pname:srcQueueFamilyIndex is |
| ename:VK_QUEUE_FAMILY_IGNORED, pname:dstQueueFamilyIndex must: also be |
| ename:VK_QUEUE_FAMILY_IGNORED. |
| * [[VUID-VkImageMemoryBarrier-image-01767]] |
| If pname:image was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE and pname:srcQueueFamilyIndex is not |
| ename:VK_QUEUE_FAMILY_IGNORED, it must: be a valid queue family or a |
| special queue family reserved for external memory transfers, as |
| described in <<synchronization-queue-transfers>>. |
| * [[VUID-VkImageMemoryBarrier-image-01768]] |
| If pname:image was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE and pname:dstQueueFamilyIndex is not |
| ename:VK_QUEUE_FAMILY_IGNORED, it must: be a valid queue family or a |
| special queue family reserved for external memory transfers, as |
| described in <<synchronization-queue-transfers>>. |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| * [[VUID-VkImageMemoryBarrier-image-01205]] |
| If pname:image was created with a sharing mode of |
| ename:VK_SHARING_MODE_EXCLUSIVE, and pname:srcQueueFamilyIndex and |
| pname:dstQueueFamilyIndex are not ename:VK_QUEUE_FAMILY_IGNORED, at |
| least one of them must: be the same as the family of the queue that will |
| execute this barrier |
| * [[VUID-VkImageMemoryBarrier-subresourceRange-01486]] |
| pname:subresourceRange.baseMipLevel must: be less than the |
| pname:mipLevels specified in slink:VkImageCreateInfo when pname:image |
| was created |
| * [[VUID-VkImageMemoryBarrier-subresourceRange-01724]] |
| If pname:subresourceRange.levelCount is not |
| ename:VK_REMAINING_MIP_LEVELS, [eq]#pname:subresourceRange.baseMipLevel |
| {plus} pname:subresourceRange.levelCount# must: be less than or equal to |
| the pname:mipLevels specified in slink:VkImageCreateInfo when |
| pname:image was created |
| * [[VUID-VkImageMemoryBarrier-subresourceRange-01488]] |
| pname:subresourceRange.baseArrayLayer must: be less than the |
| pname:arrayLayers specified in slink:VkImageCreateInfo when pname:image |
| was created |
| * [[VUID-VkImageMemoryBarrier-subresourceRange-01725]] |
| If pname:subresourceRange.layerCount is not |
| ename:VK_REMAINING_ARRAY_LAYERS, |
| [eq]#pname:subresourceRange.baseArrayLayer {plus} |
| pname:subresourceRange.layerCount# must: be less than or equal to the |
| pname:arrayLayers specified in slink:VkImageCreateInfo when pname:image |
| was created |
| * [[VUID-VkImageMemoryBarrier-image-01207]] |
| If pname:image has a depth/stencil format with both depth and stencil |
| components, then the pname:aspectMask member of pname:subresourceRange |
| must: include both ename:VK_IMAGE_ASPECT_DEPTH_BIT and |
| ename:VK_IMAGE_ASPECT_STENCIL_BIT |
| ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[] |
| * [[VUID-VkImageMemoryBarrier-image-01671]] |
| If pname:image has a single-plane color format or is not _disjoint_, |
| then the pname:aspectMask member of pname:subresourceRange must: be |
| ename:VK_IMAGE_ASPECT_COLOR_BIT |
| * [[VUID-VkImageMemoryBarrier-image-01672]] |
| If pname:image has a multi-planar format and the image is _disjoint_, |
| then the pname:aspectMask member of pname:subresourceRange must: include |
| either at least one of ename:VK_IMAGE_ASPECT_PLANE_0_BIT, |
| ename:VK_IMAGE_ASPECT_PLANE_1_BIT, and |
| ename:VK_IMAGE_ASPECT_PLANE_2_BIT; or must: include |
| ename:VK_IMAGE_ASPECT_COLOR_BIT |
| * [[VUID-VkImageMemoryBarrier-image-01673]] |
| If pname:image has a multi-planar format with only two planes, then the |
| pname:aspectMask member of pname:subresourceRange must: not include |
| ename:VK_IMAGE_ASPECT_PLANE_2_BIT |
| endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[] |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01208]] |
| If either pname:oldLayout or pname:newLayout is |
| ename:VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL then pname:image must: |
| have been created with ename:VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT set |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01209]] |
| If either pname:oldLayout or pname:newLayout is |
| ename:VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL then pname:image |
| must: have been created with |
| ename:VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01210]] |
| If either pname:oldLayout or pname:newLayout is |
| ename:VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL then pname:image |
| must: have been created with |
| ename:VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set |
| ifdef::VK_VERSION_1_1,VK_KHR_maintenance2[] |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01658]] |
| If either pname:oldLayout or pname:newLayout is |
| ename:VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL then |
| pname:image must: have been created with |
| ename:VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01659]] |
| If either pname:oldLayout or pname:newLayout is |
| ename:VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL then |
| pname:image must: have been created with |
| ename:VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set |
| endif::VK_VERSION_1_1,VK_KHR_maintenance2[] |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01211]] |
| If either pname:oldLayout or pname:newLayout is |
| ename:VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL then pname:image must: |
| have been created with ename:VK_IMAGE_USAGE_SAMPLED_BIT or |
| ename:VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT set |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01212]] |
| If either pname:oldLayout or pname:newLayout is |
| ename:VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL then pname:image must: have |
| been created with ename:VK_IMAGE_USAGE_TRANSFER_SRC_BIT set |
| * [[VUID-VkImageMemoryBarrier-oldLayout-01213]] |
| If either pname:oldLayout or pname:newLayout is |
| ename:VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL then pname:image must: have |
| been created with ename:VK_IMAGE_USAGE_TRANSFER_DST_BIT set |
| * [[VUID-VkImageMemoryBarrier-image-01932]] |
| If pname:image is non-sparse then it must: be bound completely and |
| contiguously to a single sname:VkDeviceMemory object |
| **** |
| |
| include::../validity/structs/VkImageMemoryBarrier.txt[] |
| -- |
| |
| |
| [[synchronization-queue-transfers]] |
| === Queue Family Ownership Transfer |
| |
| Resources created with a elink:VkSharingMode of |
| ename:VK_SHARING_MODE_EXCLUSIVE must: have their ownership explicitly |
| transferred from one queue family to another in order to access their |
| content in a well-defined manner on a queue in a different queue family. |
| ifdef::VK_VERSION_1_1,VK_KHR_external_memory[] |
| Resources shared with external APIs or instances using external memory must: |
| also explicitly manage ownership transfers between local and external queues |
| (or equivalent constructs in external APIs) regardless of the |
| elink:VkSharingMode specified when creating them. |
| The special queue family index ename:VK_QUEUE_FAMILY_EXTERNAL represents any |
| queue external to the resource's current Vulkan instance, as long as the |
| queue uses the same underlying physical device |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| or device group |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| and uses the same driver version as the resource's slink:VkDevice, as |
| indicated by slink:VkPhysicalDeviceIDProperties::pname:deviceUUID and |
| slink:VkPhysicalDeviceIDProperties::pname:driverUUID. |
| ifdef::VK_EXT_queue_family_foreign[] |
| The special queue family index ename:VK_QUEUE_FAMILY_FOREIGN_EXT represents |
| any queue external to the resource's current Vulkan instance, regardless of |
| the queue's underlying physical device or driver version. |
| This includes, for example, queues for fixed-function image processing |
| devices, media codec devices, and display devices, as well as all queues |
| that use the same underlying physical device |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| (or device group) |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| and driver version as the resource's slink:VkDevice. |
| endif::VK_EXT_queue_family_foreign[] |
| endif::VK_VERSION_1_1,VK_KHR_external_memory[] |
| If memory dependencies are correctly expressed between uses of such a |
| resource between two queues in different families, but no ownership transfer |
| is defined, the contents of that resource are undefined for any read |
| accesses performed by the second queue family. |
| |
| [NOTE] |
| .Note |
| ==== |
| If an application does not need the contents of a resource to remain valid |
| when transferring from one queue family to another, then the ownership |
| transfer should: be skipped. |
| ==== |
| |
| ifdef::VK_EXT_queue_family_foreign[] |
| [NOTE] |
| .Note |
| ==== |
| Applications should expect transfers to/from |
| ename:VK_QUEUE_FAMILY_FOREIGN_EXT to be more expensive than transfers |
| to/from ename:VK_QUEUE_FAMILY_EXTERNAL_KHR. |
| ==== |
| endif::VK_EXT_queue_family_foreign[] |
| |
| A queue family ownership transfer consists of two distinct parts: |
| |
| . Release exclusive ownership from the source queue family |
| . Acquire exclusive ownership for the destination queue family |
| |
| An application must: ensure that these operations occur in the correct order |
| by defining an execution dependency between them, e.g. using a semaphore. |
| |
| [[synchronization-queue-transfers-release]] A _release operation_ is used to |
| release exclusive ownership of a range of a buffer or image subresource |
| range. |
| A release operation is defined by executing a |
| <<synchronization-buffer-memory-barriers, buffer memory barrier>> (for a |
| buffer range) or an <<synchronization-image-memory-barriers, image memory |
| barrier>> (for an image subresource range), on a queue from the source queue |
| family. |
| The pname:srcQueueFamilyIndex parameter of the barrier must: be set to the |
| source queue family index, and the pname:dstQueueFamilyIndex parameter to |
| the destination queue family index. |
| pname:dstStageMask is ignored for such a barrier, such that no visibility |
| operation is executed - the value of this mask does not affect the validity |
| of the barrier. |
| The release operation happens-after the availability operation. |
| |
| [[synchronization-queue-transfers-acquire]] An _acquire operation_ is used |
| to acquire exclusive ownership of a range of a buffer or image subresource |
| range. |
| An acquire operation is defined by executing a |
| <<synchronization-buffer-memory-barriers, buffer memory barrier>> (for a |
| buffer range) or an <<synchronization-image-memory-barriers, image memory |
| barrier>> (for an image subresource range), on a queue from the destination |
| queue family. |
| The buffer range or image subresource range specified in an acquire |
| operation must: match exactly that of a previous release operation. |
| The pname:srcQueueFamilyIndex parameter of the barrier must: be set to the |
| source queue family index, and the pname:dstQueueFamilyIndex parameter to |
| the destination queue family index. |
| pname:srcStageMask is ignored for such a barrier, such that no availability |
| operation is executed - the value of this mask does not affect the validity |
| of the barrier. |
| The acquire operation happens-before the visibility operation. |
| |
| [NOTE] |
| .Note |
| ==== |
| Whilst it is not invalid to provide destination or source access masks for |
| memory barriers used for release or acquire operations, respectively, they |
| have no practical effect. |
| Access after a release operation has undefined results, and so visibility |
| for those accesses has no practical effect. |
| Similarly, write access before an acquire operation will produce undefined |
| results for future access, so availability of those writes has no practical |
| use. |
| In an earlier version of the specification, these were required to match on |
| both sides - but this was subsequently relaxed. |
| These masks should: be set to 0. |
| ==== |
| |
| If the transfer is via an image memory barrier, and an |
| <<synchronization-image-layout-transitions, image layout transition>> is |
| desired, then the values of pname:oldLayout and pname:newLayout in the |
| release memory barrier must: be equal to values of pname:oldLayout and |
| pname:newLayout in the acquire memory barrier. |
| Although the image layout transition is submitted twice, it will only be |
| executed once. |
| A layout transition specified in this way happens-after the release |
| operation and happens-before the acquire operation. |
| |
| If the values of pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex are |
| equal, no ownership transfer is performed, and the barrier operates as if |
| they were both set to ename:VK_QUEUE_FAMILY_IGNORED. |
| |
| Queue family ownership transfers may: perform read and write accesses on all |
| memory bound to the image subresource or buffer range, so applications must: |
| ensure that all memory writes have been made |
| <<synchronization-dependencies-available-and-visible, available>> before a |
| queue family ownership transfer is executed. |
| Available memory is automatically made visible to queue family release and |
| acquire operations, and writes performed by those operations are |
| automatically made available. |
| |
| Once a queue family has acquired ownership of a buffer range or image |
| subresource range of an ename:VK_SHARING_MODE_EXCLUSIVE resource, its |
| contents are undefined to other queue families unless ownership is |
| transferred. |
| The contents of any portion of another resource which aliases memory that is |
| bound to the transferred buffer or image subresource range are undefined |
| after a release or acquire operation. |
| |
| |
| [[synchronization-wait-idle]] |
| == Wait Idle Operations |
| |
| [open,refpage='vkQueueWaitIdle',desc='Wait for a queue to become idle',type='protos'] |
| -- |
| |
| To wait on the host for the completion of outstanding queue operations for a |
| given queue, call: |
| |
| include::../api/protos/vkQueueWaitIdle.txt[] |
| |
| * pname:queue is the queue on which to wait. |
| |
| fname:vkQueueWaitIdle is equivalent to submitting a fence to a queue and |
| waiting with an infinite timeout for that fence to signal. |
| |
| include::../validity/protos/vkQueueWaitIdle.txt[] |
| -- |
| |
| [open,refpage='vkDeviceWaitIdle',desc='Wait for a device to become idle',type='protos'] |
| -- |
| |
| To wait on the host for the completion of outstanding queue operations for |
| all queues on a given logical device, call: |
| |
| include::../api/protos/vkDeviceWaitIdle.txt[] |
| |
| * pname:device is the logical device to idle. |
| |
| fname:vkDeviceWaitIdle is equivalent to calling fname:vkQueueWaitIdle for |
| all queues owned by pname:device. |
| |
| include::../validity/protos/vkDeviceWaitIdle.txt[] |
| -- |
| |
| |
| [[synchronization-submission-host-writes]] |
| == Host Write Ordering Guarantees |
| |
| When batches of command buffers are submitted to a queue via |
| flink:vkQueueSubmit, it defines a memory dependency with prior host |
| operations, and execution of command buffers submitted to the queue. |
| |
| The first <<synchronization-dependencies-scopes, synchronization scope>> is |
| defined by the host execution model, but includes execution of |
| flink:vkQueueSubmit on the host and anything that happened-before it. |
| |
| The second <<synchronization-dependencies-scopes, synchronization scope>> |
| includes all commands submitted in the same <<devsandqueues-submission, |
| queue submission>>, and all commands that occur later in |
| <<synchronization-submission-order,submission order>>. |
| |
| The first <<synchronization-dependencies-access-scopes, access scope>> |
| includes all host writes to mappable device memory that are either coherent, |
| or have been flushed with flink:vkFlushMappedMemoryRanges. |
| |
| The second <<synchronization-dependencies-access-scopes, access scope>> |
| includes all memory access performed by the device. |
| |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| |
| [[synchronization-device-group]] |
| == Synchronization and Multiple Physical Devices |
| |
| If a logical device includes more than one physical device, then fences, |
| semaphores, and events all still have a single instance of the signaled |
| state. |
| |
| A fence becomes signaled when all physical devices complete the necessary |
| queue operations. |
| |
| Semaphore wait and signal operations all include a device index that is the |
| sole physical device that performs the operation. |
| These indices are provided in the slink:VkDeviceGroupSubmitInfo and |
| slink:VkDeviceGroupBindSparseInfo structures. |
| Semaphores are not exclusively owned by any physical device. |
| For example, a semaphore can be signaled by one physical device and then |
| waited on by a different physical device. |
| |
| An event can: only be waited on by the same physical device that signaled it |
| (or the host). |
| |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |