zengine/engine/modules/render/vulkan/src/vulkan_api_help.cpp
2024-10-12 17:40:59 +08:00

145 lines
6.5 KiB
C++

#include <tuple>
#include "vkn/vulkan_api_help.h"
namespace vkn {
VkImageLayout GetVkLayout(ResourceState layout) {
switch (layout) {
case ResourceState::UNDEFINED:
return VK_IMAGE_LAYOUT_UNDEFINED;
case ResourceState::READ_WRITE:
return VK_IMAGE_LAYOUT_GENERAL;
case ResourceState::READ_ONLY:
return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case ResourceState::TRANSFER_SRC:
return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case ResourceState::TRANSFER_DST:
return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case ResourceState::DEPTH_ATTACHMENT:
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
case ResourceState::DEPTH_SAMPLER:
return VK_IMAGE_LAYOUT_GENERAL;
case ResourceState::PRESENT:
return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
// Filament sometimes samples from one miplevel while writing to another level in the
// same texture (e.g. bloom does this). Moreover we'd like to avoid lots of expensive
// layout transitions. So, keep it simple and use GENERAL for all color-attachable
// textures.
case ResourceState::COLOR_ATTACHMENT:
return VK_IMAGE_LAYOUT_GENERAL;
case ResourceState::COLOR_ATTACHMENT_RESOLVE:
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
}
VkImageMemoryBarrier GetVkTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags mDstStage, const TextureBarrier& barrier) {
VkAccessFlags srcAccessMask, dstAccessMask;
VkPipelineStageFlags srcStage, dstStage;
switch (barrier.mSrcState) {
case ResourceState::UNDEFINED:
srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
break;
case ResourceState::COLOR_ATTACHMENT:
srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
break;
case ResourceState::READ_WRITE:
srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case ResourceState::READ_ONLY:
srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case ResourceState::TRANSFER_SRC:
srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case ResourceState::TRANSFER_DST:
srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case ResourceState::DEPTH_ATTACHMENT:
srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
break;
case ResourceState::DEPTH_SAMPLER:
srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case ResourceState::COLOR_ATTACHMENT_RESOLVE:
srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case ResourceState::PRESENT:
srcAccessMask = VK_ACCESS_NONE;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
}
switch (barrier.mDstState) {
case ResourceState::COLOR_ATTACHMENT:
dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dstStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
break;
case ResourceState::READ_WRITE:
dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case ResourceState::READ_ONLY:
dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
break;
case ResourceState::TRANSFER_SRC:
dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case ResourceState::TRANSFER_DST:
dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case ResourceState::DEPTH_ATTACHMENT:
dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
break;
case ResourceState::DEPTH_SAMPLER:
dstAccessMask =
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
break;
case ResourceState::PRESENT:
case ResourceState::COLOR_ATTACHMENT_RESOLVE:
case ResourceState::UNDEFINED:
dstAccessMask = 0;
dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
break;
}
mSrcStage |= srcStage;
mDstStage |= dstStage;
VkImageSubresourceRange subresources{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
return VkImageMemoryBarrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = srcAccessMask,
.dstAccessMask = dstAccessMask,
.oldLayout = GetVkLayout(barrier.mSrcState),
.newLayout = GetVkLayout(barrier.mDstState),
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = (VkImage)barrier.mTexture.image,
.subresourceRange = subresources
};
}
}