#include #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 }; } }