mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Chore] (MG_Backend/DirectVulkan): move TransitionImageLayout to VkTextureManager
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "VkRenderTargetManager.h"
|
||||
|
||||
#include "VkTextureManager.h"
|
||||
|
||||
#include <MG_State/GLState/RenderbufferState/RenderbufferObject.h>
|
||||
#include <MG_State/GLState/TextureState/TextureEnum.h>
|
||||
|
||||
@@ -68,7 +70,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
continue;
|
||||
}
|
||||
const Bool fromUndefined = (target.layout == VK_IMAGE_LAYOUT_UNDEFINED);
|
||||
return TransitionImageLayout(
|
||||
return VkTextureManager::TransitionImageLayout(
|
||||
commandBuffer, target.image, target.layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
fromUndefined
|
||||
? VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
|
||||
@@ -90,7 +92,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (resource == TransitionResource::OffscreenColor) {
|
||||
switch (usage) {
|
||||
case TransitionUsage::Attachment: {
|
||||
if (!TransitionImageLayout(
|
||||
if (!VkTextureManager::TransitionImageLayout(
|
||||
commandBuffer, target.image, target.layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
@@ -101,7 +103,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return true;
|
||||
}
|
||||
const VkImageAspectFlags aspectMask = resolveDepthStencilAspectMask(target.depthStencilFormat);
|
||||
return TransitionImageLayout(
|
||||
return VkTextureManager::TransitionImageLayout(
|
||||
commandBuffer, target.depthStencilImage, target.depthStencilLayout,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0,
|
||||
@@ -109,22 +111,22 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
aspectMask);
|
||||
}
|
||||
case TransitionUsage::TransferSrc:
|
||||
return TransitionImageLayout(commandBuffer, target.image, target.layout,
|
||||
return VkTextureManager::TransitionImageLayout(commandBuffer, target.image, target.layout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
case TransitionUsage::TransferDst:
|
||||
return TransitionImageLayout(commandBuffer, target.image, target.layout,
|
||||
return VkTextureManager::TransitionImageLayout(commandBuffer, target.image, target.layout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
case TransitionUsage::General:
|
||||
return TransitionImageLayout(commandBuffer, target.image, target.layout, VK_IMAGE_LAYOUT_GENERAL,
|
||||
return VkTextureManager::TransitionImageLayout(commandBuffer, target.image, target.layout, VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
case TransitionUsage::ShaderRead:
|
||||
return TransitionImageLayout(commandBuffer, target.image, target.layout,
|
||||
return VkTextureManager::TransitionImageLayout(commandBuffer, target.image, target.layout,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
@@ -140,22 +142,22 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const VkImageAspectFlags aspectMask = resolveDepthStencilAspectMask(target.depthStencilFormat);
|
||||
switch (usage) {
|
||||
case TransitionUsage::TransferSrc:
|
||||
return TransitionImageLayout(commandBuffer, target.depthStencilImage, target.depthStencilLayout,
|
||||
return VkTextureManager::TransitionImageLayout(commandBuffer, target.depthStencilImage, target.depthStencilLayout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
VK_ACCESS_TRANSFER_READ_BIT, aspectMask);
|
||||
case TransitionUsage::TransferDst:
|
||||
return TransitionImageLayout(commandBuffer, target.depthStencilImage, target.depthStencilLayout,
|
||||
return VkTextureManager::TransitionImageLayout(commandBuffer, target.depthStencilImage, target.depthStencilLayout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, aspectMask);
|
||||
case TransitionUsage::General:
|
||||
return TransitionImageLayout(commandBuffer, target.depthStencilImage, target.depthStencilLayout,
|
||||
return VkTextureManager::TransitionImageLayout(commandBuffer, target.depthStencilImage, target.depthStencilLayout,
|
||||
VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, aspectMask);
|
||||
case TransitionUsage::Attachment:
|
||||
return TransitionImageLayout(
|
||||
return VkTextureManager::TransitionImageLayout(
|
||||
commandBuffer, target.depthStencilImage, target.depthStencilLayout,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0,
|
||||
@@ -369,38 +371,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
target.colorTextureExternalIndex = 0;
|
||||
}
|
||||
|
||||
Bool VkRenderTargetManager::TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image,
|
||||
VkImageLayout& trackedLayout, VkImageLayout newLayout,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask,
|
||||
VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask) {
|
||||
if (image == VK_NULL_HANDLE) {
|
||||
return false;
|
||||
}
|
||||
if (trackedLayout == newLayout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier{};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.srcAccessMask = srcAccessMask;
|
||||
barrier.dstAccessMask = dstAccessMask;
|
||||
barrier.oldLayout = trackedLayout;
|
||||
barrier.newLayout = newLayout;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = image;
|
||||
barrier.subresourceRange.aspectMask = aspectMask;
|
||||
barrier.subresourceRange.baseMipLevel = 0;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
|
||||
trackedLayout = newLayout;
|
||||
return true;
|
||||
}
|
||||
|
||||
VkFormat VkRenderTargetManager::ResolveColorFormat(
|
||||
const MG_State::GLState::FramebufferAttachmentObject& colorAttachment) {
|
||||
TextureInternalFormat internalFormat = TextureInternalFormat::Unknown;
|
||||
|
||||
@@ -75,10 +75,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const MG_State::GLState::FramebufferAttachmentObject& colorAttachment,
|
||||
Uint16 glObjectVersion);
|
||||
void DestroyOffscreenColorTarget(OffscreenColorTarget& target);
|
||||
static Bool TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout& trackedLayout,
|
||||
VkImageLayout newLayout, VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask,
|
||||
VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask);
|
||||
static VkFormat ResolveColorFormat(const MG_State::GLState::FramebufferAttachmentObject& colorAttachment);
|
||||
static VkFormat ResolveDepthStencilFormat(
|
||||
const MG_State::GLState::FramebufferAttachmentObject& depthAttachment,
|
||||
|
||||
@@ -65,6 +65,36 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
outImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
return true;
|
||||
}
|
||||
Bool VkTextureManager::TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image,
|
||||
VkImageLayout& trackedLayout, VkImageLayout newLayout,
|
||||
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
|
||||
VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
|
||||
VkImageAspectFlags aspectMask) {
|
||||
MOBILEGL_ASSERT(image != VK_NULL_HANDLE, "TransitionImageLayout: m_image == VK_NULL_HANDLE");
|
||||
|
||||
if (trackedLayout == newLayout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier{};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.srcAccessMask = srcAccessMask;
|
||||
barrier.dstAccessMask = dstAccessMask;
|
||||
barrier.oldLayout = trackedLayout;
|
||||
barrier.newLayout = newLayout;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = image;
|
||||
barrier.subresourceRange.aspectMask = aspectMask;
|
||||
barrier.subresourceRange.baseMipLevel = 0;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
|
||||
trackedLayout = newLayout;
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool VkTextureManager::SyncTexture(MG_State::GLState::ITextureObject &texture,
|
||||
TextureResource &outResource) {
|
||||
@@ -234,26 +264,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
// TODO: Could be uploaded asynchronously?
|
||||
const Bool ok = ExecuteCmdBufImmediate([&](VkCommandBuffer commandBuffer) {
|
||||
VkImageMemoryBarrier toTransferDst{};
|
||||
toTransferDst.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
toTransferDst.srcAccessMask =
|
||||
outResource.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ? VK_ACCESS_SHADER_READ_BIT : 0;
|
||||
toTransferDst.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
toTransferDst.oldLayout = outResource.layout;
|
||||
toTransferDst.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
toTransferDst.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
toTransferDst.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
toTransferDst.image = outResource.image;
|
||||
toTransferDst.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
toTransferDst.subresourceRange.baseMipLevel = 0;
|
||||
toTransferDst.subresourceRange.levelCount = outResource.mipLevels;
|
||||
toTransferDst.subresourceRange.baseArrayLayer = 0;
|
||||
toTransferDst.subresourceRange.layerCount = 1;
|
||||
const VkPipelineStageFlags srcStage =
|
||||
outResource.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ? VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
||||
: VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
vkCmdPipelineBarrier(commandBuffer, srcStage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1,
|
||||
&toTransferDst);
|
||||
Bool ok = TransitionImageLayout(commandBuffer, outResource.image,
|
||||
outResource.layout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ? VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
outResource.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ? VK_ACCESS_SHADER_READ_BIT : 0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL failed");
|
||||
|
||||
for (const auto& item : uploadItems) {
|
||||
VkBufferImageCopy copy{};
|
||||
@@ -270,22 +289,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
1, ©);
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier toSampled{};
|
||||
toSampled.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
toSampled.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
toSampled.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
toSampled.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
toSampled.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
toSampled.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
toSampled.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
toSampled.image = outResource.image;
|
||||
toSampled.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
toSampled.subresourceRange.baseMipLevel = 0;
|
||||
toSampled.subresourceRange.levelCount = outResource.mipLevels;
|
||||
toSampled.subresourceRange.baseArrayLayer = 0;
|
||||
toSampled.subresourceRange.layerCount = 1;
|
||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
|
||||
0, nullptr, 0, nullptr, 1, &toSampled);
|
||||
ok = TransitionImageLayout(commandBuffer, outResource.image,
|
||||
outResource.layout,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL failed");
|
||||
return ok;
|
||||
});
|
||||
|
||||
vmaDestroyBuffer(m_allocator, stagingBuffer, stagingAllocation);
|
||||
|
||||
@@ -33,6 +33,11 @@ public:
|
||||
|
||||
Bool SyncTextureAndGetDescriptor(MG_State::GLState::ITextureObject& texture, VkDescriptorImageInfo& outImageInfo);
|
||||
|
||||
|
||||
static Bool TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout& trackedLayout,
|
||||
VkImageLayout newLayout, VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask,
|
||||
VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask);
|
||||
private:
|
||||
struct TextureResource {
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
|
||||
Reference in New Issue
Block a user