adjust image layout

This commit is contained in:
Asuka 2022-07-11 01:39:35 +08:00
parent 9203064f5c
commit aafab46347
12 changed files with 93 additions and 127 deletions

View file

@ -168,8 +168,7 @@ namespace sce::Gnm
VkImageUsageFlags usage,
VkPipelineStageFlags2 stage,
VkAccessFlagBits2 access,
VkImageTiling tiling,
VkImageLayout layout)
VkImageTiling tiling)
{
GnmImageCreateInfo info;
info.tsharp = tsharp;
@ -177,7 +176,6 @@ namespace sce::Gnm
info.stage = stage | VK_PIPELINE_STAGE_TRANSFER_BIT;
info.access = access;
info.tiling = tiling;
info.layout = layout;
info.memoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
SceTexture texture = getResourceTexture(info);
@ -254,8 +252,7 @@ namespace sce::Gnm
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
stage,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VK_IMAGE_TILING_OPTIMAL);
updateMetaTextureInfo(stage, res.startRegister, false, tsharp);
}
@ -270,8 +267,7 @@ namespace sce::Gnm
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
stage,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_LAYOUT_GENERAL);
VK_IMAGE_TILING_OPTIMAL);
updateMetaTextureInfo(stage, res.startRegister, false, tsharp);
}

View file

@ -454,8 +454,7 @@ namespace sce::Gnm
VkImageUsageFlags usage,
VkPipelineStageFlags2 stage,
VkAccessFlagBits2 access,
VkImageTiling tiling,
VkImageLayout layout);
VkImageTiling tiling);
void bindResourceSampler(
const Sampler* ssharp,

View file

@ -650,28 +650,6 @@ namespace sce::Gnm
void GnmCommandBufferDraw::waitUntilSafeForRendering(uint32_t videoOutHandle, uint32_t displayBufferIndex)
{
// This cmd blocks command processor until the specified display buffer is no longer displayed.
// should we call vkAcquireNextImageKHR here to implement it?
// or should we create a new render target image and then bilt to swapchain like DXVK does?
// get render target from swapchain
auto& videoOut = GPU().videoOutGet(videoOutHandle);
auto dispBuffer = videoOut.getDisplayBuffer(displayBufferIndex);
auto res = m_tracker.find(dispBuffer.address);
if (res)
{
auto& image = res->renderTarget().image;
auto range = res->renderTarget().imageView->imageSubresources();
m_context->transformImage(
image,
range,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
0,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
}
}
void GnmCommandBufferDraw::prepareFlip()
@ -1425,7 +1403,7 @@ namespace sce::Gnm
result.color[slot] = VltAttachment{
targetView,
targetView->imageInfo().layout
VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL
};
}
@ -1436,7 +1414,7 @@ namespace sce::Gnm
result.depth = VltAttachment{
depthView,
depthView->imageInfo().layout
VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL
};
}

View file

@ -122,7 +122,7 @@ namespace sce::Gnm
VK_ACCESS_TRANSFER_WRITE_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.layout = VK_IMAGE_LAYOUT_GENERAL;
imageInfo.layout = optimizeLayout(imageInfo.usage);
VltImageViewCreateInfo viewInfo;
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
@ -225,7 +225,7 @@ namespace sce::Gnm
imageInfo.stages = createInfo.stage;
imageInfo.access = createInfo.access;
imageInfo.tiling = createInfo.tiling;
imageInfo.layout = createInfo.layout;
imageInfo.layout = optimizeLayout(imageInfo.usage);
VltImageViewCreateInfo viewInfo;
viewInfo.type = cvt::convertTextureTypeView(textureType);
@ -327,6 +327,39 @@ namespace sce::Gnm
return result;
}
VkImageLayout GnmResourceFactory::optimizeLayout(VkImageUsageFlags usage)
{
const VkImageUsageFlags usageFlags = usage;
// Filter out unnecessary flags. Transfer operations
// are handled by the backend in a transparent manner.
usage &= ~(VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
// If the image is used only as an attachment, we never
// have to transform the image back to a different layout
if (usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
usage &= ~(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
// If the image is used for reading but not as a storage
// image, we can optimize the image for texture access
if (usage == VK_IMAGE_USAGE_SAMPLED_BIT)
{
return usageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
// Otherwise, we have to stick with the default layout
return VK_IMAGE_LAYOUT_GENERAL;
}
} // namespace sce::Gnm

View file

@ -45,7 +45,6 @@ namespace sce
VkPipelineStageFlags2 stage;
VkAccessFlagBits2 access;
VkImageTiling tiling;
VkImageLayout layout;
VkMemoryPropertyFlags memoryType;
};
@ -79,6 +78,8 @@ namespace sce
vlt::Rc<vlt::VltSampler> createSampler(
const Sampler* ssharp);
VkImageLayout optimizeLayout(VkImageUsageFlags usage);
private:
vlt::VltDevice* m_device;
vlt::VltDebugUtil m_debugUtil;

View file

@ -54,15 +54,6 @@ namespace sce
// Get the render target which is draw to by commands from game.
auto& target = m_renderTargets[index];
// Transform render target to SHADER_READ layout
// so that we can copy it to swapchain.
// Note that the content must be preserved.
m_context->transformImage(
target.image,
target.image->getAvailableSubresources(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Record draw commands to copy render target image to swapchain image.
m_blitter->presentImage(m_context.ptr(),
m_imageViews.at(imageIndex), VkRect2D(),
@ -227,4 +218,51 @@ namespace sce
}
}
void SceSwapchain::transitionImageLayout()
{
// Transition swapchain image's layout to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.
// Because we are using dynamic rendering, the layout can not be
// transformed implicitly.
PresenterInfo info = m_presenter->info();
VltImageCreateInfo imageInfo;
imageInfo.type = VK_IMAGE_TYPE_2D;
imageInfo.format = info.format.format;
imageInfo.flags = 0;
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 };
imageInfo.numLayers = 1;
imageInfo.mipLevels = 1;
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imageInfo.stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
imageInfo.access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
auto& device = m_device.device;
m_context->beginRecording(
device->createCommandList(VltQueueType::Graphics));
for (uint32_t i = 0; i < info.imageCount; i++)
{
VkImage imageHandle = m_presenter->getImage(i).image;
Rc<VltImage> image =
m_device.device->createImageFromVkImage(imageInfo, imageHandle);
m_context->transformImage(image,
image->getAvailableSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED,
image->info().layout);
}
device->submitCommandList(
m_context->endRecording(),
VK_NULL_HANDLE,
VK_NULL_HANDLE);
device->syncSubmission();
}
} // namespace sce

View file

@ -53,6 +53,8 @@ namespace sce
void createSwapImageViews();
void transitionImageLayout();
private:
SceSwapchainDevice m_device;

View file

@ -165,11 +165,6 @@ namespace sce
ctx->clearRenderTarget(
dstView, VK_IMAGE_ASPECT_COLOR_BIT, VkClearValue());
ctx->transformImage(
dstView->image(),
dstView->subresources(),
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
ctx->bindResourceSampler(BindingIds::Image, m_samplerPresent);
ctx->bindResourceView(BindingIds::Image, srcView, nullptr);

View file

@ -1388,8 +1388,6 @@ namespace sce::vlt
if (!m_flags.test(VltContextFlag::GpRenderingActive) &&
framebuffer != nullptr)
{
framebuffer->prepareLayout(this);
m_execBarriers.recordCommands(m_cmd);
const VltFramebufferSize fbSize = framebuffer->size();

View file

@ -2,6 +2,7 @@
#include "VltContext.h"
#include "VltImage.h"
#include "VltSampler.h"
namespace sce::vlt
{
@ -112,70 +113,6 @@ namespace sce::vlt
return VltFramebufferSize{ extent.width, extent.height, layers };
}
void VltFramebuffer::prepareLayout(VltContext* ctx)
{
for (uint32_t i = 0; i < MaxNumRenderTargets; i++)
{
auto& colorView = m_renderTargets.color[i].view;
if (colorView == nullptr)
{
continue;
}
auto& colorImage = colorView->image();
if (colorImage->info().layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
{
continue;
}
ctx->transformImage(colorImage,
colorImage->getAvailableSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
auto& depthView = m_renderTargets.depth.view;
if (depthView != nullptr)
{
auto& depthImage = depthView->image();
if (depthImage->info().layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL)
{
ctx->transformImage(depthImage,
depthImage->getAvailableSubresources(),
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
}
}
}
void VltFramebuffer::restoreLayout(VltContext* ctx)
{
for (uint32_t i = 0; i < MaxNumRenderTargets; i++)
{
auto& colorView = m_renderTargets.color[i].view;
if (colorView == nullptr)
{
continue;
}
auto& colorImage = colorView->image();
ctx->transformImage(colorImage,
colorImage->getAvailableSubresources(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
colorImage->info().layout);
}
auto& depthView = m_renderTargets.depth.view;
if (depthView != nullptr)
{
auto& depthImage = depthView->image();
ctx->transformImage(depthImage,
depthImage->getAvailableSubresources(),
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
depthImage->info().layout);
}
}
int32_t VltFramebuffer::findAttachment(
const Rc<VltImageView>& view) const
{

View file

@ -149,16 +149,6 @@ namespace sce::vlt
&m_depthAttachment : nullptr;
}
/**
* \brief Transform attachment images to rendering-ready layout.
*/
void prepareLayout(VltContext* ctx);
/**
* \brief Restore attachment images to its' original layout
*/
void restoreLayout(VltContext* ctx);
/**
* \brief Checks whether the framebuffer's targets match
*

View file

@ -125,7 +125,6 @@ namespace sce::vlt
m_device(device),
m_info(info), m_image({ image })
{
m_viewFormats.resize(info.viewFormatCount);
for (uint32_t i = 0; i < info.viewFormatCount; i++)
m_viewFormats[i] = info.viewFormats[i];