mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-06-02 02:42:28 -05:00
fix render pass barrier logic
This commit is contained in:
parent
b3e310220e
commit
f3dbc86f9b
|
|
@ -8,6 +8,7 @@
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h"
|
||||||
|
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
|
||||||
#include "util/math/vector2.h"
|
#include "util/math/vector2.h"
|
||||||
#include "util/helpers/Semaphore.h"
|
#include "util/helpers/Semaphore.h"
|
||||||
#include "util/containers/flat_hash_map.hpp"
|
#include "util/containers/flat_hash_map.hpp"
|
||||||
|
|
@ -546,7 +547,7 @@ private:
|
||||||
void draw_handleSpecialState5();
|
void draw_handleSpecialState5();
|
||||||
|
|
||||||
// draw synchronization helper
|
// draw synchronization helper
|
||||||
void sync_inputTexturesChanged();
|
bool sync_isInputTexturesSyncRequired();
|
||||||
void sync_RenderPassLoadTextures(CachedFBOVk* fboVk);
|
void sync_RenderPassLoadTextures(CachedFBOVk* fboVk);
|
||||||
void sync_RenderPassStoreTextures(CachedFBOVk* fboVk);
|
void sync_RenderPassStoreTextures(CachedFBOVk* fboVk);
|
||||||
|
|
||||||
|
|
@ -825,6 +826,7 @@ private:
|
||||||
bufMemBarrier.offset = offset;
|
bufMemBarrier.offset = offset;
|
||||||
bufMemBarrier.size = size;
|
bufMemBarrier.size = size;
|
||||||
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
|
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
|
||||||
|
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<uint32 TSrcSyncOpA, uint32 TDstSyncOpA, uint32 TSrcSyncOpB, uint32 TDstSyncOpB>
|
template<uint32 TSrcSyncOpA, uint32 TDstSyncOpA, uint32 TSrcSyncOpB, uint32 TDstSyncOpB>
|
||||||
|
|
@ -863,6 +865,7 @@ private:
|
||||||
bufMemBarrier[1].size = sizeB;
|
bufMemBarrier[1].size = sizeB;
|
||||||
|
|
||||||
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStagesA|srcStagesB, dstStagesA|dstStagesB, 0, 0, nullptr, 2, bufMemBarrier, 0, nullptr);
|
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStagesA|srcStagesB, dstStagesA|dstStagesB, 0, 0, nullptr, 2, bufMemBarrier, 0, nullptr);
|
||||||
|
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
void barrier_sequentializeTransfer()
|
void barrier_sequentializeTransfer()
|
||||||
|
|
@ -881,6 +884,7 @@ private:
|
||||||
memBarrier.dstAccessMask |= (VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
|
memBarrier.dstAccessMask |= (VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
|
||||||
|
|
||||||
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 1, &memBarrier, 0, nullptr, 0, nullptr);
|
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 1, &memBarrier, 0, nullptr, 0, nullptr);
|
||||||
|
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
void barrier_sequentializeCommand()
|
void barrier_sequentializeCommand()
|
||||||
|
|
@ -889,6 +893,7 @@ private:
|
||||||
VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
|
|
||||||
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 0, nullptr, 0, nullptr, 0, nullptr);
|
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 0, nullptr, 0, nullptr, 0, nullptr);
|
||||||
|
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<uint32 TSrcSyncOp, uint32 TDstSyncOp>
|
template<uint32 TSrcSyncOp, uint32 TDstSyncOp>
|
||||||
|
|
@ -916,6 +921,7 @@ private:
|
||||||
0, NULL,
|
0, NULL,
|
||||||
0, NULL,
|
0, NULL,
|
||||||
1, &imageMemBarrier);
|
1, &imageMemBarrier);
|
||||||
|
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<uint32 TSrcSyncOp, uint32 TDstSyncOp>
|
template<uint32 TSrcSyncOp, uint32 TDstSyncOp>
|
||||||
|
|
|
||||||
|
|
@ -975,68 +975,21 @@ VkDescriptorSetInfo* VulkanRenderer::draw_getOrCreateDescriptorSet(PipelineInfo*
|
||||||
return dsInfo;
|
return dsInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::sync_inputTexturesChanged()
|
bool VulkanRenderer::sync_isInputTexturesSyncRequired()
|
||||||
{
|
{
|
||||||
bool writeFlushRequired = false;
|
auto checkSync = [&](const VkDescriptorSetInfo* info) {
|
||||||
|
if (info)
|
||||||
if (m_state.activeVertexDS)
|
|
||||||
{
|
|
||||||
for (auto& tex : m_state.activeVertexDS->list_fboCandidates)
|
|
||||||
{
|
{
|
||||||
tex->m_vkFlushIndex_read = m_state.currentFlushIndex;
|
for (auto& tex : m_state.activeVertexDS->list_fboCandidates)
|
||||||
if (tex->m_vkFlushIndex_write == m_state.currentFlushIndex)
|
{
|
||||||
writeFlushRequired = true;
|
tex->m_vkFlushIndex_read = m_state.currentFlushIndex;
|
||||||
|
if (tex->m_vkFlushIndex_write == m_state.currentFlushIndex)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
if (m_state.activeGeometryDS)
|
};
|
||||||
{
|
return checkSync(m_state.activeVertexDS) || checkSync(m_state.activeGeometryDS) || checkSync(m_state.activePixelDS);
|
||||||
for (auto& tex : m_state.activeGeometryDS->list_fboCandidates)
|
|
||||||
{
|
|
||||||
tex->m_vkFlushIndex_read = m_state.currentFlushIndex;
|
|
||||||
if (tex->m_vkFlushIndex_write == m_state.currentFlushIndex)
|
|
||||||
writeFlushRequired = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_state.activePixelDS)
|
|
||||||
{
|
|
||||||
for (auto& tex : m_state.activePixelDS->list_fboCandidates)
|
|
||||||
{
|
|
||||||
tex->m_vkFlushIndex_read = m_state.currentFlushIndex;
|
|
||||||
if (tex->m_vkFlushIndex_write == m_state.currentFlushIndex)
|
|
||||||
writeFlushRequired = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// barrier here
|
|
||||||
if (writeFlushRequired)
|
|
||||||
{
|
|
||||||
VkMemoryBarrier memoryBarrier{};
|
|
||||||
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
|
||||||
memoryBarrier.srcAccessMask = 0;
|
|
||||||
memoryBarrier.dstAccessMask = 0;
|
|
||||||
|
|
||||||
VkPipelineStageFlags srcStage = 0;
|
|
||||||
VkPipelineStageFlags dstStage = 0;
|
|
||||||
|
|
||||||
// src
|
|
||||||
srcStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
memoryBarrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
|
|
||||||
srcStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
|
||||||
memoryBarrier.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
||||||
|
|
||||||
// dst
|
|
||||||
dstStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
||||||
memoryBarrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
|
|
||||||
dstStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
||||||
memoryBarrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStage, dstStage, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
|
|
||||||
|
|
||||||
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
|
|
||||||
|
|
||||||
m_state.currentFlushIndex++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::sync_RenderPassLoadTextures(CachedFBOVk* fboVk)
|
void VulkanRenderer::sync_RenderPassLoadTextures(CachedFBOVk* fboVk)
|
||||||
|
|
@ -1051,7 +1004,7 @@ void VulkanRenderer::sync_RenderPassLoadTextures(CachedFBOVk* fboVk)
|
||||||
readFlushRequired = true;
|
readFlushRequired = true;
|
||||||
|
|
||||||
|
|
||||||
texVk->m_vkFlushIndex_write = m_state.currentFlushIndex;
|
texVk->m_vkFlushIndex_read = m_state.currentFlushIndex;
|
||||||
// todo - also check for write-before-write ?
|
// todo - also check for write-before-write ?
|
||||||
if (texVk->m_vkFlushIndex_read == m_state.currentFlushIndex)
|
if (texVk->m_vkFlushIndex_read == m_state.currentFlushIndex)
|
||||||
readFlushRequired = true;
|
readFlushRequired = true;
|
||||||
|
|
@ -1091,11 +1044,10 @@ void VulkanRenderer::sync_RenderPassLoadTextures(CachedFBOVk* fboVk)
|
||||||
|
|
||||||
void VulkanRenderer::sync_RenderPassStoreTextures(CachedFBOVk* fboVk)
|
void VulkanRenderer::sync_RenderPassStoreTextures(CachedFBOVk* fboVk)
|
||||||
{
|
{
|
||||||
uint32 flushIndex = m_state.currentFlushIndex;
|
|
||||||
for (auto& tex : fboVk->GetTextures())
|
for (auto& tex : fboVk->GetTextures())
|
||||||
{
|
{
|
||||||
LatteTextureVk* texVk = (LatteTextureVk*)tex;
|
LatteTextureVk* texVk = (LatteTextureVk*)tex;
|
||||||
texVk->m_vkFlushIndex_write = flushIndex;
|
texVk->m_vkFlushIndex_write = m_state.currentFlushIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1164,20 +1116,22 @@ void VulkanRenderer::draw_setRenderPass()
|
||||||
auto vkObjRenderPass = fboVk->GetRenderPassObj();
|
auto vkObjRenderPass = fboVk->GetRenderPassObj();
|
||||||
auto vkObjFramebuffer = fboVk->GetFramebufferObj();
|
auto vkObjFramebuffer = fboVk->GetFramebufferObj();
|
||||||
|
|
||||||
bool overridePassReuse = m_state.hasRenderSelfDependency && (GetConfig().vk_accurate_barriers || m_state.activePipelineInfo->neverSkipAccurateBarrier);
|
const bool syncSkipAllowed = !(GetConfig().vk_accurate_barriers || m_state.activePipelineInfo->neverSkipAccurateBarrier);
|
||||||
|
|
||||||
if (!overridePassReuse && m_state.activeRenderpassFBO == fboVk)
|
const bool FBOChanged = m_state.activeRenderpassFBO != fboVk;
|
||||||
|
|
||||||
|
bool inputSyncNecessary = false;
|
||||||
|
if (m_state.descriptorSetsChanged)
|
||||||
|
inputSyncNecessary = sync_isInputTexturesSyncRequired();
|
||||||
|
|
||||||
|
const bool passReusable = !FBOChanged && !inputSyncNecessary;
|
||||||
|
|
||||||
|
if (passReusable)
|
||||||
{
|
{
|
||||||
if (m_state.descriptorSetsChanged)
|
// reuse previous render pass
|
||||||
sync_inputTexturesChanged();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
draw_endRenderPass();
|
draw_endRenderPass();
|
||||||
if (m_state.descriptorSetsChanged)
|
|
||||||
sync_inputTexturesChanged();
|
|
||||||
|
|
||||||
// assume that FBO changed, update self-dependency state
|
|
||||||
m_state.hasRenderSelfDependency = fboVk->CheckForCollision(m_state.activeVertexDS, m_state.activeGeometryDS, m_state.activePixelDS);
|
|
||||||
|
|
||||||
sync_RenderPassLoadTextures(fboVk);
|
sync_RenderPassLoadTextures(fboVk);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user