Vulkan: Use explicit barriers instead of dependancies

At least on NV, some of these don't seem to have the intended effect. One
known instance of this is in texture conversion.
This commit is contained in:
Stenzek 2016-11-21 01:59:19 +10:00
parent a475792163
commit 9736198c3b
5 changed files with 77 additions and 178 deletions

View File

@ -183,24 +183,12 @@ bool FramebufferManager::CreateEFBRenderPass()
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
// Ensure all reads have finished from the resolved texture before overwriting it.
VkSubpassDependency dependencies[] = {
{VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT},
{0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}};
subpass_description.pDepthStencilAttachment = nullptr;
pass_info.pAttachments = &resolve_attachment;
pass_info.attachmentCount = 1;
pass_info.dependencyCount = static_cast<u32>(ArraySize(dependencies));
pass_info.pDependencies = dependencies;
res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
&m_depth_resolve_render_pass);
@ -696,6 +684,9 @@ bool FramebufferManager::PopulateColorReadbackTexture()
if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT)
{
m_color_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
m_copy_color_render_pass, g_object_cache->GetScreenQuadVertexShader(),
@ -720,7 +711,6 @@ bool FramebufferManager::PopulateColorReadbackTexture()
}
// Use this as a source texture now.
m_color_copy_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
src_texture = m_color_copy_texture.get();
}
@ -777,6 +767,9 @@ bool FramebufferManager::PopulateDepthReadbackTexture()
}
if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT)
{
m_depth_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
m_copy_depth_render_pass, g_object_cache->GetScreenQuadVertexShader(),
@ -801,7 +794,6 @@ bool FramebufferManager::PopulateDepthReadbackTexture()
}
// Use this as a source texture now.
m_depth_copy_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
src_texture = m_depth_copy_texture.get();
src_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
}
@ -840,15 +832,15 @@ void FramebufferManager::InvalidatePeekCache()
bool FramebufferManager::CreateReadbackRenderPasses()
{
VkAttachmentDescription copy_attachment = {
0, // VkAttachmentDescriptionFlags flags
EFB_COLOR_TEXTURE_FORMAT, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout initialLayout
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout
0, // VkAttachmentDescriptionFlags flags
EFB_COLOR_TEXTURE_FORMAT, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
};
VkAttachmentReference copy_attachment_ref = {
0, // uint32_t attachment
@ -866,14 +858,6 @@ bool FramebufferManager::CreateReadbackRenderPasses()
0, // uint32_t preserveAttachmentCount
nullptr // const uint32_t* pPreserveAttachments
};
VkSubpassDependency copy_dependency = {
0,
VK_SUBPASS_EXTERNAL,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
VK_DEPENDENCY_BY_REGION_BIT};
VkRenderPassCreateInfo copy_pass = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext
@ -882,8 +866,8 @@ bool FramebufferManager::CreateReadbackRenderPasses()
&copy_attachment, // const VkAttachmentDescription* pAttachments
1, // uint32_t subpassCount
&copy_subpass, // const VkSubpassDescription* pSubpasses
1, // uint32_t dependencyCount
&copy_dependency // const VkSubpassDependency* pDependencies
0, // uint32_t dependencyCount
nullptr // const VkSubpassDependency* pDependencies
};
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &copy_pass, nullptr,
@ -1023,12 +1007,6 @@ bool FramebufferManager::CreateReadbackTextures()
return false;
}
// Transition to TRANSFER_SRC, as this is expected by the render pass.
m_color_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_depth_copy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
return true;
}

View File

@ -613,6 +613,9 @@ void Renderer::DrawVirtualXFB(VkRenderPass render_pass, const TargetRectangle& t
for (u32 i = 0; i < xfb_count; ++i)
{
const XFBSource* xfb_source = static_cast<const XFBSource*>(xfb_sources[i]);
xfb_source->GetTexture()->GetTexture()->TransitionToLayout(
g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
TargetRectangle source_rect = xfb_source->sourceRc;
TargetRectangle draw_rect;
@ -646,6 +649,9 @@ void Renderer::DrawRealXFB(VkRenderPass render_pass, const TargetRectangle& targ
for (u32 i = 0; i < xfb_count; ++i)
{
const XFBSource* xfb_source = static_cast<const XFBSource*>(xfb_sources[i]);
xfb_source->GetTexture()->GetTexture()->TransitionToLayout(
g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
TargetRectangle source_rect = xfb_source->sourceRc;
TargetRectangle draw_rect = target_rect;
source_rect.right -= fb_stride - fb_width;

View File

@ -36,10 +36,8 @@ TextureCache::TextureCache()
TextureCache::~TextureCache()
{
if (m_initialize_render_pass != VK_NULL_HANDLE)
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_initialize_render_pass, nullptr);
if (m_update_render_pass != VK_NULL_HANDLE)
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_update_render_pass, nullptr);
if (m_render_pass != VK_NULL_HANDLE)
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_render_pass, nullptr);
TextureCache::DeleteShaders();
}
@ -87,11 +85,7 @@ void TextureCache::ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase*
TCacheEntry* entry = static_cast<TCacheEntry*>(base_entry);
TCacheEntry* unconverted = static_cast<TCacheEntry*>(base_unconverted);
m_texture_converter->ConvertTexture(
entry, unconverted, GetRenderPassForTextureUpdate(entry->GetTexture()), palette, format);
// Render pass transitions to SHADER_READ_ONLY.
entry->GetTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_texture_converter->ConvertTexture(entry, unconverted, m_render_pass, palette, format);
}
static bool IsDepthCopyFormat(PEControl::PixelFormat format)
@ -203,11 +197,10 @@ void TextureCache::ScaleTextureRectangle(TCacheEntry* dst_texture,
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
dst_texture->GetTexture()->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
GetRenderPassForTextureUpdate(dst_texture->GetTexture()),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), m_render_pass,
g_object_cache->GetPassthroughVertexShader(),
g_object_cache->GetPassthroughGeometryShader(), m_copy_shader);
@ -221,9 +214,6 @@ void TextureCache::ScaleTextureRectangle(TCacheEntry* dst_texture,
static_cast<int>(src_texture->GetWidth()),
static_cast<int>(src_texture->GetHeight()));
draw.EndRenderPass();
// Render pass transitions destination texture to SHADER_READ_ONLY.
dst_texture->GetTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config)
@ -251,7 +241,7 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
nullptr,
0,
m_initialize_render_pass,
m_render_pass,
static_cast<u32>(ArraySize(framebuffer_attachments)),
framebuffer_attachments,
texture->GetWidth(),
@ -281,17 +271,6 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry
bool TextureCache::CreateRenderPasses()
{
static constexpr VkAttachmentDescription initialize_attachment = {
0,
TEXTURECACHE_TEXTURE_FORMAT,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
static constexpr VkAttachmentDescription update_attachment = {
0,
TEXTURECACHE_TEXTURE_FORMAT,
@ -300,8 +279,8 @@ bool TextureCache::CreateRenderPasses()
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
static constexpr VkAttachmentReference color_attachment_reference = {
0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
@ -313,36 +292,6 @@ bool TextureCache::CreateRenderPasses()
nullptr, nullptr,
0, nullptr};
static constexpr VkSubpassDependency initialize_dependancies[] = {
{VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT},
{0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}};
static constexpr VkSubpassDependency update_dependancies[] = {
{VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT},
{0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}};
VkRenderPassCreateInfo initialize_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
1,
&initialize_attachment,
1,
&subpass_description,
static_cast<u32>(ArraySize(initialize_dependancies)),
initialize_dependancies};
VkRenderPassCreateInfo update_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
@ -350,44 +299,20 @@ bool TextureCache::CreateRenderPasses()
&update_attachment,
1,
&subpass_description,
static_cast<u32>(ArraySize(update_dependancies)),
update_dependancies};
0,
nullptr};
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &initialize_info, nullptr,
&m_initialize_render_pass);
VkResult res =
vkCreateRenderPass(g_vulkan_context->GetDevice(), &update_info, nullptr, &m_render_pass);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreateRenderPass (initialize) failed: ");
return false;
}
res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &update_info, nullptr,
&m_update_render_pass);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreateRenderPass (update) failed: ");
LOG_VULKAN_ERROR(res, "vkCreateRenderPass failed: ");
return false;
}
return true;
}
VkRenderPass TextureCache::GetRenderPassForTextureUpdate(const Texture2D* texture) const
{
// EFB copies can be re-used as part of the texture pool. If this is the case, we need to insert
// a pipeline barrier to ensure that all reads from the texture expecting the old data have
// completed before overwriting the texture's contents. New textures will be in TRANSFER_DST
// due to the clear after creation.
// These two render passes are compatible, so even though the framebuffer was created with
// the initialize render pass it's still allowed.
if (texture->GetLayout() == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
return m_initialize_render_pass;
else
return m_update_render_pass;
}
TextureCache::TCacheEntry::TCacheEntry(const TCacheEntryConfig& config_,
std::unique_ptr<Texture2D> texture,
VkFramebuffer framebuffer)
@ -410,27 +335,23 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
width = std::max(1u, std::min(width, m_texture->GetWidth() >> level));
height = std::max(1u, std::min(height, m_texture->GetHeight() >> level));
// We don't care about the existing contents of the texture, so we set the image layout to
// VK_IMAGE_LAYOUT_UNDEFINED here. However, if this texture is being re-used from the texture
// pool, it may still be in use. We assume that it's not, as non-efb-copy textures are only
// returned to the pool when the frame number is different, furthermore, we're doing this
// on the initialize command buffer, so a texture being re-used mid-frame would have undesirable
// effects regardless.
VkImageMemoryBarrier barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
nullptr, // const void* pNext
0, // VkAccessFlags srcAccessMask
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
m_texture->GetImage(), // VkImage image
{VK_IMAGE_ASPECT_COLOR_BIT, level, 1, 0, 1}, // VkImageSubresourceRange subresourceRange
};
vkCmdPipelineBarrier(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 0, nullptr, 1, &barrier);
// We don't care about the existing contents of the texture, so we could the image layout to
// VK_IMAGE_LAYOUT_UNDEFINED here. However, under section 2.2.1, Queue Operation of the Vulkan
// specification, it states:
//
// Command buffer submissions to a single queue must always adhere to command order and
// API order, but otherwise may overlap or execute out of order.
//
// Therefore, if a previous frame's command buffer is still sampling from this texture, and we
// overwrite it without a pipeline barrier, a texture sample could occur in parallel with the
// texture upload/copy. I'm not sure if any drivers currently take advantage of this, but we
// should insert an explicit pipeline barrier just in case (done by TransitionToLayout).
//
// We transition to TRANSFER_DST, ready for the image copy, and leave the texture in this state.
// This is so that the remaining mip levels can be uploaded without barriers, and then when the
// texture is used, it can be transitioned to SHADER_READ_ONLY (see TCacheEntry::Bind).
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
// Does this texture data fit within the streaming buffer?
u32 upload_width = width;
@ -513,16 +434,6 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
m_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, width,
height, level, 0);
}
// Transition to shader read only.
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
vkCmdPipelineBarrier(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0,
nullptr, 0, nullptr, 1, &barrier);
m_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat src_format,
@ -559,11 +470,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat
scale_by_half ? g_object_cache->GetLinearSampler() : g_object_cache->GetPointSampler();
VkImageLayout original_layout = src_texture->GetLayout();
src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
UtilityShaderDraw draw(
command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
TextureCache::GetInstance()->GetRenderPassForTextureUpdate(m_texture.get()),
g_object_cache->GetPassthroughVertexShader(), g_object_cache->GetPassthroughGeometryShader(),
TextureCache::GetInstance()->m_render_pass, g_object_cache->GetPassthroughVertexShader(),
g_object_cache->GetPassthroughGeometryShader(),
is_depth_copy ? TextureCache::GetInstance()->m_efb_depth_to_tex_shader :
TextureCache::GetInstance()->m_efb_color_to_tex_shader);
@ -587,7 +499,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat
src_texture->TransitionToLayout(command_buffer, original_layout);
// Render pass transitions texture to SHADER_READ_ONLY.
m_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase* source,
@ -607,6 +519,8 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
void TextureCache::TCacheEntry::Bind(unsigned int stage)
{
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
StateTracker::GetInstance()->SetTexture(stage, m_texture->GetView());
}

View File

@ -68,7 +68,6 @@ public:
private:
bool CreateRenderPasses();
VkRenderPass GetRenderPassForTextureUpdate(const Texture2D* texture) const;
// Copies the contents of a texture using vkCmdCopyImage
void CopyTextureRectangle(TCacheEntry* dst_texture, const MathUtil::Rectangle<int>& dst_rect,
@ -78,8 +77,7 @@ private:
void ScaleTextureRectangle(TCacheEntry* dst_texture, const MathUtil::Rectangle<int>& dst_rect,
Texture2D* src_texture, const MathUtil::Rectangle<int>& src_rect);
VkRenderPass m_initialize_render_pass = VK_NULL_HANDLE;
VkRenderPass m_update_render_pass = VK_NULL_HANDLE;
VkRenderPass m_render_pass = VK_NULL_HANDLE;
std::unique_ptr<StreamBuffer> m_texture_upload_buffer;

View File

@ -180,6 +180,10 @@ void TextureConverter::ConvertTexture(TextureCache::TCacheEntry* dst_entry,
m_texel_buffer->CommitMemory(palette_size);
VkCommandBuffer command_buffer = GetCommandBufferForTextureConversion(src_entry);
src_entry->GetTexture()->TransitionToLayout(command_buffer,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
dst_entry->GetTexture()->TransitionToLayout(command_buffer,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Bind and draw to the destination.
UtilityShaderDraw draw(command_buffer,
@ -216,6 +220,9 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p
// Can't do our own draw within a render pass.
StateTracker::GetInstance()->EndRenderPass();
m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
m_encoding_render_pass, g_object_cache->GetScreenQuadVertexShader(),
@ -242,7 +249,8 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p
draw.EndRenderPass();
// Transition the image before copying
m_encoding_render_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_encoding_download_texture->CopyFromImage(
g_command_buffer_mgr->GetCurrentCommandBuffer(), m_encoding_render_texture->GetImage(),
VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, render_width, render_height, 0, 0);
@ -286,7 +294,8 @@ void TextureConverter::EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u
draw.EndRenderPass();
// Render pass transitions to TRANSFER_SRC.
m_encoding_render_texture->OverrideImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_encoding_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
// Copy from encoding texture to download buffer.
m_encoding_download_texture->CopyFromImage(command_buffer, m_encoding_render_texture->GetImage(),
@ -530,8 +539,8 @@ bool TextureConverter::CreateEncodingRenderPass()
VkAttachmentDescription attachments[] = {
{0, ENCODING_TEXTURE_FORMAT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL}};
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
VkAttachmentReference color_attachment_references[] = {
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
@ -540,12 +549,6 @@ bool TextureConverter::CreateEncodingRenderPass()
color_attachment_references, nullptr, nullptr, 0,
nullptr}};
VkSubpassDependency dependancies[] = {
{0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT, VK_DEPENDENCY_BY_REGION_BIT}};
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
nullptr,
0,
@ -553,8 +556,8 @@ bool TextureConverter::CreateEncodingRenderPass()
attachments,
static_cast<u32>(ArraySize(subpass_descriptions)),
subpass_descriptions,
static_cast<u32>(ArraySize(dependancies)),
dependancies};
0,
nullptr};
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
&m_encoding_render_pass);