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:
parent
a475792163
commit
9736198c3b
|
@ -183,24 +183,12 @@ bool FramebufferManager::CreateEFBRenderPass()
|
||||||
VK_ATTACHMENT_STORE_OP_STORE,
|
VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_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;
|
subpass_description.pDepthStencilAttachment = nullptr;
|
||||||
pass_info.pAttachments = &resolve_attachment;
|
pass_info.pAttachments = &resolve_attachment;
|
||||||
pass_info.attachmentCount = 1;
|
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,
|
res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
|
||||||
&m_depth_resolve_render_pass);
|
&m_depth_resolve_render_pass);
|
||||||
|
|
||||||
|
@ -696,6 +684,9 @@ bool FramebufferManager::PopulateColorReadbackTexture()
|
||||||
|
|
||||||
if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT)
|
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(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
|
||||||
m_copy_color_render_pass, g_object_cache->GetScreenQuadVertexShader(),
|
m_copy_color_render_pass, g_object_cache->GetScreenQuadVertexShader(),
|
||||||
|
@ -720,7 +711,6 @@ bool FramebufferManager::PopulateColorReadbackTexture()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use this as a source texture now.
|
// 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();
|
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)
|
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(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
|
||||||
m_copy_depth_render_pass, g_object_cache->GetScreenQuadVertexShader(),
|
m_copy_depth_render_pass, g_object_cache->GetScreenQuadVertexShader(),
|
||||||
|
@ -801,7 +794,6 @@ bool FramebufferManager::PopulateDepthReadbackTexture()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use this as a source texture now.
|
// 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_texture = m_depth_copy_texture.get();
|
||||||
src_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
src_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
}
|
}
|
||||||
|
@ -847,8 +839,8 @@ bool FramebufferManager::CreateReadbackRenderPasses()
|
||||||
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
|
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
|
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout initialLayout
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
|
||||||
};
|
};
|
||||||
VkAttachmentReference copy_attachment_ref = {
|
VkAttachmentReference copy_attachment_ref = {
|
||||||
0, // uint32_t attachment
|
0, // uint32_t attachment
|
||||||
|
@ -866,14 +858,6 @@ bool FramebufferManager::CreateReadbackRenderPasses()
|
||||||
0, // uint32_t preserveAttachmentCount
|
0, // uint32_t preserveAttachmentCount
|
||||||
nullptr // const uint32_t* pPreserveAttachments
|
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 = {
|
VkRenderPassCreateInfo copy_pass = {
|
||||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
|
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
|
||||||
nullptr, // const void* pNext
|
nullptr, // const void* pNext
|
||||||
|
@ -882,8 +866,8 @@ bool FramebufferManager::CreateReadbackRenderPasses()
|
||||||
©_attachment, // const VkAttachmentDescription* pAttachments
|
©_attachment, // const VkAttachmentDescription* pAttachments
|
||||||
1, // uint32_t subpassCount
|
1, // uint32_t subpassCount
|
||||||
©_subpass, // const VkSubpassDescription* pSubpasses
|
©_subpass, // const VkSubpassDescription* pSubpasses
|
||||||
1, // uint32_t dependencyCount
|
0, // uint32_t dependencyCount
|
||||||
©_dependency // const VkSubpassDependency* pDependencies
|
nullptr // const VkSubpassDependency* pDependencies
|
||||||
};
|
};
|
||||||
|
|
||||||
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), ©_pass, nullptr,
|
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), ©_pass, nullptr,
|
||||||
|
@ -1023,12 +1007,6 @@ bool FramebufferManager::CreateReadbackTextures()
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -613,6 +613,9 @@ void Renderer::DrawVirtualXFB(VkRenderPass render_pass, const TargetRectangle& t
|
||||||
for (u32 i = 0; i < xfb_count; ++i)
|
for (u32 i = 0; i < xfb_count; ++i)
|
||||||
{
|
{
|
||||||
const XFBSource* xfb_source = static_cast<const XFBSource*>(xfb_sources[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 source_rect = xfb_source->sourceRc;
|
||||||
TargetRectangle draw_rect;
|
TargetRectangle draw_rect;
|
||||||
|
|
||||||
|
@ -646,6 +649,9 @@ void Renderer::DrawRealXFB(VkRenderPass render_pass, const TargetRectangle& targ
|
||||||
for (u32 i = 0; i < xfb_count; ++i)
|
for (u32 i = 0; i < xfb_count; ++i)
|
||||||
{
|
{
|
||||||
const XFBSource* xfb_source = static_cast<const XFBSource*>(xfb_sources[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 source_rect = xfb_source->sourceRc;
|
||||||
TargetRectangle draw_rect = target_rect;
|
TargetRectangle draw_rect = target_rect;
|
||||||
source_rect.right -= fb_stride - fb_width;
|
source_rect.right -= fb_stride - fb_width;
|
||||||
|
|
|
@ -36,10 +36,8 @@ TextureCache::TextureCache()
|
||||||
|
|
||||||
TextureCache::~TextureCache()
|
TextureCache::~TextureCache()
|
||||||
{
|
{
|
||||||
if (m_initialize_render_pass != VK_NULL_HANDLE)
|
if (m_render_pass != VK_NULL_HANDLE)
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_initialize_render_pass, nullptr);
|
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_render_pass, nullptr);
|
||||||
if (m_update_render_pass != VK_NULL_HANDLE)
|
|
||||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_update_render_pass, nullptr);
|
|
||||||
TextureCache::DeleteShaders();
|
TextureCache::DeleteShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,11 +85,7 @@ void TextureCache::ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase*
|
||||||
TCacheEntry* entry = static_cast<TCacheEntry*>(base_entry);
|
TCacheEntry* entry = static_cast<TCacheEntry*>(base_entry);
|
||||||
TCacheEntry* unconverted = static_cast<TCacheEntry*>(base_unconverted);
|
TCacheEntry* unconverted = static_cast<TCacheEntry*>(base_unconverted);
|
||||||
|
|
||||||
m_texture_converter->ConvertTexture(
|
m_texture_converter->ConvertTexture(entry, unconverted, m_render_pass, palette, format);
|
||||||
entry, unconverted, GetRenderPassForTextureUpdate(entry->GetTexture()), palette, format);
|
|
||||||
|
|
||||||
// Render pass transitions to SHADER_READ_ONLY.
|
|
||||||
entry->GetTexture()->OverrideImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsDepthCopyFormat(PEControl::PixelFormat 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(),
|
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
dst_texture->GetTexture()->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
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(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), m_render_pass,
|
||||||
GetRenderPassForTextureUpdate(dst_texture->GetTexture()),
|
|
||||||
g_object_cache->GetPassthroughVertexShader(),
|
g_object_cache->GetPassthroughVertexShader(),
|
||||||
g_object_cache->GetPassthroughGeometryShader(), m_copy_shader);
|
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->GetWidth()),
|
||||||
static_cast<int>(src_texture->GetHeight()));
|
static_cast<int>(src_texture->GetHeight()));
|
||||||
draw.EndRenderPass();
|
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)
|
TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config)
|
||||||
|
@ -251,7 +241,7 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry
|
||||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
nullptr,
|
nullptr,
|
||||||
0,
|
0,
|
||||||
m_initialize_render_pass,
|
m_render_pass,
|
||||||
static_cast<u32>(ArraySize(framebuffer_attachments)),
|
static_cast<u32>(ArraySize(framebuffer_attachments)),
|
||||||
framebuffer_attachments,
|
framebuffer_attachments,
|
||||||
texture->GetWidth(),
|
texture->GetWidth(),
|
||||||
|
@ -281,17 +271,6 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry
|
||||||
|
|
||||||
bool TextureCache::CreateRenderPasses()
|
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 = {
|
static constexpr VkAttachmentDescription update_attachment = {
|
||||||
0,
|
0,
|
||||||
TEXTURECACHE_TEXTURE_FORMAT,
|
TEXTURECACHE_TEXTURE_FORMAT,
|
||||||
|
@ -300,8 +279,8 @@ bool TextureCache::CreateRenderPasses()
|
||||||
VK_ATTACHMENT_STORE_OP_STORE,
|
VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
||||||
|
|
||||||
static constexpr VkAttachmentReference color_attachment_reference = {
|
static constexpr VkAttachmentReference color_attachment_reference = {
|
||||||
0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
||||||
|
@ -313,36 +292,6 @@ bool TextureCache::CreateRenderPasses()
|
||||||
nullptr, nullptr,
|
nullptr, nullptr,
|
||||||
0, 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,
|
VkRenderPassCreateInfo update_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||||
nullptr,
|
nullptr,
|
||||||
0,
|
0,
|
||||||
|
@ -350,44 +299,20 @@ bool TextureCache::CreateRenderPasses()
|
||||||
&update_attachment,
|
&update_attachment,
|
||||||
1,
|
1,
|
||||||
&subpass_description,
|
&subpass_description,
|
||||||
static_cast<u32>(ArraySize(update_dependancies)),
|
0,
|
||||||
update_dependancies};
|
nullptr};
|
||||||
|
|
||||||
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &initialize_info, nullptr,
|
VkResult res =
|
||||||
&m_initialize_render_pass);
|
vkCreateRenderPass(g_vulkan_context->GetDevice(), &update_info, nullptr, &m_render_pass);
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateRenderPass (initialize) failed: ");
|
LOG_VULKAN_ERROR(res, "vkCreateRenderPass 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: ");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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_,
|
TextureCache::TCacheEntry::TCacheEntry(const TCacheEntryConfig& config_,
|
||||||
std::unique_ptr<Texture2D> texture,
|
std::unique_ptr<Texture2D> texture,
|
||||||
VkFramebuffer framebuffer)
|
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));
|
width = std::max(1u, std::min(width, m_texture->GetWidth() >> level));
|
||||||
height = std::max(1u, std::min(height, m_texture->GetHeight() >> 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
|
// We don't care about the existing contents of the texture, so we could the image layout to
|
||||||
// VK_IMAGE_LAYOUT_UNDEFINED here. However, if this texture is being re-used from the texture
|
// VK_IMAGE_LAYOUT_UNDEFINED here. However, under section 2.2.1, Queue Operation of the Vulkan
|
||||||
// pool, it may still be in use. We assume that it's not, as non-efb-copy textures are only
|
// specification, it states:
|
||||||
// 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
|
// Command buffer submissions to a single queue must always adhere to command order and
|
||||||
// effects regardless.
|
// API order, but otherwise may overlap or execute out of order.
|
||||||
VkImageMemoryBarrier barrier = {
|
//
|
||||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
// Therefore, if a previous frame's command buffer is still sampling from this texture, and we
|
||||||
nullptr, // const void* pNext
|
// overwrite it without a pipeline barrier, a texture sample could occur in parallel with the
|
||||||
0, // VkAccessFlags srcAccessMask
|
// texture upload/copy. I'm not sure if any drivers currently take advantage of this, but we
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
|
// should insert an explicit pipeline barrier just in case (done by TransitionToLayout).
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
|
//
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
|
// We transition to TRANSFER_DST, ready for the image copy, and leave the texture in this state.
|
||||||
VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
|
// This is so that the remaining mip levels can be uploaded without barriers, and then when the
|
||||||
VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
|
// texture is used, it can be transitioned to SHADER_READ_ONLY (see TCacheEntry::Bind).
|
||||||
m_texture->GetImage(), // VkImage image
|
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
|
||||||
{VK_IMAGE_ASPECT_COLOR_BIT, level, 1, 0, 1}, // VkImageSubresourceRange subresourceRange
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
};
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Does this texture data fit within the streaming buffer?
|
// Does this texture data fit within the streaming buffer?
|
||||||
u32 upload_width = width;
|
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,
|
m_texture->GetImage(), VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, width,
|
||||||
height, level, 0);
|
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,
|
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();
|
scale_by_half ? g_object_cache->GetLinearSampler() : g_object_cache->GetPointSampler();
|
||||||
VkImageLayout original_layout = src_texture->GetLayout();
|
VkImageLayout original_layout = src_texture->GetLayout();
|
||||||
src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
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(
|
UtilityShaderDraw draw(
|
||||||
command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
|
command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
|
||||||
TextureCache::GetInstance()->GetRenderPassForTextureUpdate(m_texture.get()),
|
TextureCache::GetInstance()->m_render_pass, g_object_cache->GetPassthroughVertexShader(),
|
||||||
g_object_cache->GetPassthroughVertexShader(), g_object_cache->GetPassthroughGeometryShader(),
|
g_object_cache->GetPassthroughGeometryShader(),
|
||||||
is_depth_copy ? TextureCache::GetInstance()->m_efb_depth_to_tex_shader :
|
is_depth_copy ? TextureCache::GetInstance()->m_efb_depth_to_tex_shader :
|
||||||
TextureCache::GetInstance()->m_efb_color_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);
|
src_texture->TransitionToLayout(command_buffer, original_layout);
|
||||||
|
|
||||||
// Render pass transitions texture to SHADER_READ_ONLY.
|
// 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,
|
void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase* source,
|
||||||
|
@ -607,6 +519,8 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::Bind(unsigned int stage)
|
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());
|
StateTracker::GetInstance()->SetTexture(stage, m_texture->GetView());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CreateRenderPasses();
|
bool CreateRenderPasses();
|
||||||
VkRenderPass GetRenderPassForTextureUpdate(const Texture2D* texture) const;
|
|
||||||
|
|
||||||
// Copies the contents of a texture using vkCmdCopyImage
|
// Copies the contents of a texture using vkCmdCopyImage
|
||||||
void CopyTextureRectangle(TCacheEntry* dst_texture, const MathUtil::Rectangle<int>& dst_rect,
|
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,
|
void ScaleTextureRectangle(TCacheEntry* dst_texture, const MathUtil::Rectangle<int>& dst_rect,
|
||||||
Texture2D* src_texture, const MathUtil::Rectangle<int>& src_rect);
|
Texture2D* src_texture, const MathUtil::Rectangle<int>& src_rect);
|
||||||
|
|
||||||
VkRenderPass m_initialize_render_pass = VK_NULL_HANDLE;
|
VkRenderPass m_render_pass = VK_NULL_HANDLE;
|
||||||
VkRenderPass m_update_render_pass = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
std::unique_ptr<StreamBuffer> m_texture_upload_buffer;
|
std::unique_ptr<StreamBuffer> m_texture_upload_buffer;
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,10 @@ void TextureConverter::ConvertTexture(TextureCache::TCacheEntry* dst_entry,
|
||||||
m_texel_buffer->CommitMemory(palette_size);
|
m_texel_buffer->CommitMemory(palette_size);
|
||||||
|
|
||||||
VkCommandBuffer command_buffer = GetCommandBufferForTextureConversion(src_entry);
|
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.
|
// Bind and draw to the destination.
|
||||||
UtilityShaderDraw draw(command_buffer,
|
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.
|
// Can't do our own draw within a render pass.
|
||||||
StateTracker::GetInstance()->EndRenderPass();
|
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(),
|
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
|
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
|
||||||
m_encoding_render_pass, g_object_cache->GetScreenQuadVertexShader(),
|
m_encoding_render_pass, g_object_cache->GetScreenQuadVertexShader(),
|
||||||
|
@ -242,7 +249,8 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p
|
||||||
draw.EndRenderPass();
|
draw.EndRenderPass();
|
||||||
|
|
||||||
// Transition the image before copying
|
// 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(
|
m_encoding_download_texture->CopyFromImage(
|
||||||
g_command_buffer_mgr->GetCurrentCommandBuffer(), m_encoding_render_texture->GetImage(),
|
g_command_buffer_mgr->GetCurrentCommandBuffer(), m_encoding_render_texture->GetImage(),
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, render_width, render_height, 0, 0);
|
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();
|
draw.EndRenderPass();
|
||||||
|
|
||||||
// Render pass transitions to TRANSFER_SRC.
|
// 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.
|
// Copy from encoding texture to download buffer.
|
||||||
m_encoding_download_texture->CopyFromImage(command_buffer, m_encoding_render_texture->GetImage(),
|
m_encoding_download_texture->CopyFromImage(command_buffer, m_encoding_render_texture->GetImage(),
|
||||||
|
@ -530,8 +539,8 @@ bool TextureConverter::CreateEncodingRenderPass()
|
||||||
VkAttachmentDescription attachments[] = {
|
VkAttachmentDescription attachments[] = {
|
||||||
{0, ENCODING_TEXTURE_FORMAT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
{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_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL}};
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
||||||
|
|
||||||
VkAttachmentReference color_attachment_references[] = {
|
VkAttachmentReference color_attachment_references[] = {
|
||||||
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
|
||||||
|
@ -540,12 +549,6 @@ bool TextureConverter::CreateEncodingRenderPass()
|
||||||
color_attachment_references, nullptr, nullptr, 0,
|
color_attachment_references, nullptr, nullptr, 0,
|
||||||
nullptr}};
|
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,
|
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||||
nullptr,
|
nullptr,
|
||||||
0,
|
0,
|
||||||
|
@ -553,8 +556,8 @@ bool TextureConverter::CreateEncodingRenderPass()
|
||||||
attachments,
|
attachments,
|
||||||
static_cast<u32>(ArraySize(subpass_descriptions)),
|
static_cast<u32>(ArraySize(subpass_descriptions)),
|
||||||
subpass_descriptions,
|
subpass_descriptions,
|
||||||
static_cast<u32>(ArraySize(dependancies)),
|
0,
|
||||||
dependancies};
|
nullptr};
|
||||||
|
|
||||||
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
|
VkResult res = vkCreateRenderPass(g_vulkan_context->GetDevice(), &pass_info, nullptr,
|
||||||
&m_encoding_render_pass);
|
&m_encoding_render_pass);
|
||||||
|
|
Loading…
Reference in New Issue