@@ -520,7 +520,7 @@ back to this once we've figured out which transitions we're going to use.
520520``` c++
521521vkCmdPipelineBarrier (
522522 commandBuffer,
523- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ,
523+ 0 /* TODO */, 0 /* TODO */ ,
524524 0,
525525 0, nullptr,
526526 0, nullptr,
@@ -529,10 +529,19 @@ vkCmdPipelineBarrier(
529529```
530530
531531All types of pipeline barriers are submitted using the same function. The first
532- parameter specifies in which pipeline stage the operations occur that should
533- happen before the barrier. The second parameter specifies the pipeline stage in
534- which operations will wait on the barrier. We want it to happen immediately, so
535- we're going with the top of the pipeline.
532+ parameter after the command buffer specifies in which pipeline stage the
533+ operations occur that should happen before the barrier. The second parameter
534+ specifies the pipeline stage in which operations will wait on the barrier. The
535+ pipeline stages that you are allowed to specify before and after the barrier
536+ depend on how you use the resource before and after the barrier. The allowed
537+ values are listed in [ this table] ( https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-access-types-supported )
538+ of the specification. For example, if you're going to read from a uniform after
539+ the barrier, you would specify a usage of ` VK_ACCESS_UNIFORM_READ_BIT ` and the
540+ earliest shader that will read from the uniform as pipeline stage, for example
541+ ` VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT ` . It would not make sense to specify
542+ a non-shader pipeline stage for this type of usage and the validation layers
543+ will warn you when you specify a pipeline stage that does not match the type of
544+ usage.
536545
537546The third parameter is either ` 0 ` or ` VK_DEPENDENCY_BY_REGION_BIT ` . The latter
538547turns the barrier into a per-region condition. That means that the
@@ -641,29 +650,59 @@ transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TR
641650## Transition barrier masks
642651
643652If run your application with validation layers enabled now, then you'll see that
644- it complains about the access masks in ` transitionImageLayout ` being invalid.
645- We still need to set those based on the layouts in the transition.
653+ it complains about the access masks and pipeline stages in
654+ ` transitionImageLayout ` being invalid. We still need to set those based on the
655+ layouts in the transition.
646656
647657There are two transitions we need to handle:
648658
649- * Undefined → transfer destination: transfer writes that don't need to wait
659+ * Undefined → transfer destination: transfer writes that don't need to wait on
660+ anything
650661* Transfer destination → shader reading: shader reads should wait on transfer
651- writes
662+ writes, specifically the shader reads in the fragment shader, because that's
663+ where we're going to use the texture
652664
653- These rules are specified using the following access masks:
665+ These rules are specified using the following access masks and pipeline stages :
654666
655667``` c++
668+ VkPipelineStageFlags sourceStage;
669+ VkPipelineStageFlags destinationStage;
670+
656671if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
657672 barrier.srcAccessMask = 0;
658673 barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
674+
675+ sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
676+ destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
659677} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
660678 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
661679 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
680+
681+ sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
682+ destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
662683} else {
663684 throw std::invalid_argument("unsupported layout transition!");
664685}
686+
687+ vkCmdPipelineBarrier (
688+ commandBuffer,
689+ sourceStage, destinationStage,
690+ 0,
691+ 0, nullptr,
692+ 0, nullptr,
693+ 1, &barrier
694+ );
665695```
666696
697+ As you can see in the aforementioned table, transfer writes must occur in the
698+ pipeline transfer stage. Since the writes don't have to wait on anything, you
699+ may specify an empty access mask and the earliest possible pipeline stage
700+ ` VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ` for the pre-barrier operations.
701+
702+ The image will be written in the same pipeline stage and subsequently read by
703+ the fragment shader, which is why we specify shader reading access in the
704+ fragment shader pipeline stage.
705+
667706If we need to do more transitions in the future, then we'll extend the function.
668707The application should now run successfully, although there are of course no
669708visual changes yet.
0 commit comments