in RenderScriptMigrationSample/app/src/main/cpp/VulkanResources.cpp [318:372]
void Image::recordLayoutTransitionBarrier(VkCommandBuffer cmd, VkImageLayout newLayout,
bool preserveData) {
if (newLayout == mLayout) return;
if (!preserveData) mLayout = VK_IMAGE_LAYOUT_UNDEFINED;
const auto getAccessMask = [](VkImageLayout layout) -> VkAccessFlags {
switch (layout) {
case VK_IMAGE_LAYOUT_UNDEFINED:
return 0;
case VK_IMAGE_LAYOUT_GENERAL:
// In this sample app, we only use GENERAL layout for output storage images.
return VK_ACCESS_SHADER_WRITE_BIT;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
return VK_ACCESS_TRANSFER_READ_BIT;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
return VK_ACCESS_TRANSFER_WRITE_BIT;
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
return VK_ACCESS_SHADER_READ_BIT;
default:
LOGE("Undefined access mask for target image layout");
return 0;
}
};
const auto getStageFlag = [](VkImageLayout layout) -> VkPipelineStageFlags {
switch (layout) {
case VK_IMAGE_LAYOUT_UNDEFINED:
return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
case VK_IMAGE_LAYOUT_GENERAL:
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
return VK_PIPELINE_STAGE_TRANSFER_BIT;
default:
LOGE("Undefined stage flag for target image layout");
return 0;
}
};
const VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = getAccessMask(mLayout),
.dstAccessMask = getAccessMask(newLayout),
.oldLayout = mLayout,
.newLayout = newLayout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = mImage.handle(),
.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
};
vkCmdPipelineBarrier(cmd, getStageFlag(mLayout), getStageFlag(newLayout), 0, 0, nullptr, 0,
nullptr, 1, &barrier);
mLayout = newLayout;
}