In an effort to make Vulkan synchronization more accessible, I created this stb-inspired single-header library in order to somewhat simplify the core synchronization mechanisms in Vulkan - pipeline barriers and events.
Rather than the complex maze of enums and bitflags in Vulkan - many combinations of which are invalid or nonsensical - this library collapses this to a much shorter list of 40 distinct usage types, and a couple of options for handling image layouts.
Use of other synchonization mechanisms such as semaphores, fences and render passes are not addressed in this API at present.
#define the symbol THSVS_SIMPLER_VULKAN_SYNCHRONIZATION_IMPLEMENTATION in one C/C++ file before the #include of the header; the implementation will be generated in that file.
alpha.9
Alpha.9 adds the thsvsGetAccessInfo function to translate access types into a thsvsVkAccessInfo.
alpha.8
Alpha.8 adds a host preinitialization state for linear images, as well as a number of new access sets for extensions released since the last update.
alpha.7
Alpha.7 incorporates a number of fixes from @gwihlidal, and fixes handling of pipeline stages in the presence of multiple access types or barriers in light of other recent changes.
alpha.6
Alpha.6 fixes a typo (VK_ACCESS_TYPE_MEMORY_READ|WRITE_BIT should have been VK_ACCESS_MEMORY_READ|WRITE_BIT), and sets the pipeline stage src and dst flag bits to VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT and VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT during initialization, not 0 as per alpha.5
alpha.5
Alpha.5 now correctly zeroes out the pipeline stage flags before trying to incrementally set bits on them... common theme here, whoops.
alpha.4
Alpha.4 now correctly zeroes out the access types before trying to incrementally set bits on them (!)
alpha.3
Alpha.3 changes the following:
Uniform and vertex buffer access in one enum, matching D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER:
- THSVS_ACCESS_ANY_SHADER_READ_UNIFORM_BUFFER_OR_VERTEX_BUFFER
Color read and write access, matching D3D12_RESOURCE_STATE_RENDER_TARGET:
- THSVS_ACCESS_COLOR_ATTACHMENT_READ_WRITE
Also the "THSVS_ACCESS_*_SHADER_READ_SAMPLED_IMAGE" enums have been renamed to the form "THSVS_ACCESS_*_SHADER_READ_SAMPLED_IMAGE_OR_UNIFORM_TEXEL_BUFFER"
alpha.2
Alpha.2 adds four new resource states for "ANY SHADER ACCESS":
- THSVS_ACCESS_ANY_SHADER_READ_UNIFORM_BUFFER
- THSVS_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE
- THSVS_ACCESS_ANY_SHADER_READ_OTHER
- THSVS_ACCESS_ANY_SHADER_WRITE
alpha.1
Alpha.1 adds three new resource states:
- THSVS_ACCESS_GENERAL (Any access on the device)
- THSVS_ACCESS_DEPTH_ATTACHMENT_WRITE_STENCIL_READ_ONLY (Write access to only the depth aspect of a depth/stencil attachment)
- THSVS_ACCESS_STENCIL_ATTACHMENT_WRITE_DEPTH_READ_ONLY (Write access to only the stencil aspect of a depth/stencil attachment)
It also fixes a couple of typos, and adds clarification as to when extensions need to be enabled to use a feature.
alpha.0
This is the very first public release of this library; future revisions of this API may change the API in an incompatible manner as feedback is received. Once the version becomes stable, incompatible changes will only be made to major revisions of the API - minor revisions will only contain bugfixes or minor additions.
The thsvsCmdPipelineBarrier and thsvsCmdWaitEvents commands allocate temporary storage for the Vulkan barrier equivalents in order to pass them to the respective Vulkan commands.
These use the THSVS_TEMP_ALLOC(size)
and THSVS_TEMP_FREE(x)
macros,
which are by default set to alloca(size) and ((void)(x)), respectively.
If you don't want to use stack space or would rather use your own
allocation strategy, these can be overridden by defining these macros
in before #include-ing the header file with
THSVS_SIMPLER_VULKAN_SYNCHRONIZATION_IMPLEMENTATION defined.
I'd rather avoid the need for these allocations in what are likely to be high-traffic commands, but currently just want to ship something - may revisit this at a future date based on feedback.
Despite the fact that this API is fairly simple, it expresses 99% of what you'd actually ever want to do in practice. Adding the missing expressiveness would result in increased complexity which didn't seem worth the tradeoff - however I would consider adding something for them in future if it becomes an issue.
Here's a list of known things you can't express:
- Execution only dependencies cannot be expressed. These are occasionally useful in conjunction with semaphores, or when trying to be clever with scheduling - but their usage is both limited and fairly tricky to get right anyway.
- Depth/Stencil Input Attachments can be read in a shader using either VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL or VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL - this library always uses VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL. It's possible (though highly unlikely) when aliasing images that this results in unnecessary transitions.
By default, as with the Vulkan API, this library does NOT check for
errors.
However, a number of optional error checks (THSVS_ERROR_CHECK_*
) can be
enabled by uncommenting the relevant #defines.
Currently, error checks simply assert at the point a failure is detected
and do not output an error message.
I certainly do not claim they capture all possible errors, but they
capture what should be some of the more common ones.
Use of the Vulkan Validation Layers in tandem with this library is
strongly recommended:
https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers
This header was clean of warnings using -Wall as of time of publishing on both gcc 4.8.4 and clang 3.5, using the c99 standard.
There's a potential pitfall in thsvsCmdPipelineBarrier and thsvsCmdWaitEvents where alloca is used for temporary allocations. See Memory Allocation for more information.
Testing of this library is so far extremely limited with no immediate plans to add to that - so there's bound to be some amount of bugs. Please raise these issues on the repo issue tracker, or provide a fix via a pull request yourself if you're so inclined.