mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-06 15:01:18 +12:00
Add all the files
This commit is contained in:
parent
e3db07a16a
commit
d60742f52b
1445 changed files with 430238 additions and 0 deletions
212
src/Cafe/HW/Latte/Renderer/Vulkan/VulkanQuery.cpp
Normal file
212
src/Cafe/HW/Latte/Renderer/Vulkan/VulkanQuery.cpp
Normal file
|
@ -0,0 +1,212 @@
|
|||
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
|
||||
|
||||
class LatteQueryObjectVk : public LatteQueryObject
|
||||
{
|
||||
friend class VulkanRenderer;
|
||||
|
||||
LatteQueryObjectVk(VulkanRenderer* rendererVk) : m_rendererVk(rendererVk)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
bool getResult(uint64& numSamplesPassed) override;
|
||||
void begin() override;
|
||||
void end() override;
|
||||
void beginFragment();
|
||||
void endFragment();
|
||||
void handleFinishedFragments();
|
||||
|
||||
uint32 acquireQueryIndex();
|
||||
void releaseQueryIndex(uint32 queryIndex);
|
||||
|
||||
private:
|
||||
struct queryFragment
|
||||
{
|
||||
uint32 queryIndex;
|
||||
uint64 m_finishCommandBuffer;
|
||||
bool isFinished;
|
||||
};
|
||||
|
||||
VulkanRenderer* m_rendererVk;
|
||||
//sint32 m_queryIndex;
|
||||
std::vector<queryFragment> list_queryFragments;
|
||||
bool m_vkQueryEnded{};
|
||||
bool m_hasActiveQuery{};
|
||||
bool m_hasActiveFragment{};
|
||||
uint64 m_finishCommandBuffer;
|
||||
uint64 m_acccumulatedSum;
|
||||
};
|
||||
|
||||
bool LatteQueryObjectVk::getResult(uint64& numSamplesPassed)
|
||||
{
|
||||
if (!m_vkQueryEnded)
|
||||
return false;
|
||||
if (!m_rendererVk->HasCommandBufferFinished(m_finishCommandBuffer))
|
||||
return false;
|
||||
handleFinishedFragments();
|
||||
cemu_assert_debug(list_queryFragments.empty());
|
||||
numSamplesPassed = m_acccumulatedSum;
|
||||
//numSamplesPassed = m_rendererVk->m_occlusionQueries.ptrQueryResults[m_queryIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
void LatteQueryObjectVk::beginFragment()
|
||||
{
|
||||
m_rendererVk->draw_endRenderPass();
|
||||
|
||||
handleFinishedFragments();
|
||||
uint32 newQueryIndex = acquireQueryIndex();
|
||||
|
||||
queryFragment qf{};
|
||||
qf.queryIndex = newQueryIndex;
|
||||
qf.isFinished = false;
|
||||
qf.m_finishCommandBuffer = 0;
|
||||
list_queryFragments.emplace_back(qf);
|
||||
|
||||
|
||||
vkCmdResetQueryPool(m_rendererVk->m_state.currentCommandBuffer, m_rendererVk->m_occlusionQueries.queryPool, newQueryIndex, 1);
|
||||
vkCmdBeginQuery(m_rendererVk->m_state.currentCommandBuffer, m_rendererVk->m_occlusionQueries.queryPool, newQueryIndex, VK_QUERY_CONTROL_PRECISE_BIT);
|
||||
// todo - we already synchronize with command buffers, should we also set wait bits?
|
||||
|
||||
m_hasActiveFragment = true;
|
||||
}
|
||||
|
||||
void LatteQueryObjectVk::begin()
|
||||
{
|
||||
m_vkQueryEnded = false;
|
||||
m_hasActiveQuery = true;
|
||||
beginFragment();
|
||||
}
|
||||
|
||||
void LatteQueryObjectVk::endFragment()
|
||||
{
|
||||
m_rendererVk->draw_endRenderPass();
|
||||
|
||||
cemu_assert_debug(m_hasActiveFragment);
|
||||
uint32 queryIndex = list_queryFragments.back().queryIndex;
|
||||
vkCmdEndQuery(m_rendererVk->m_state.currentCommandBuffer, m_rendererVk->m_occlusionQueries.queryPool, queryIndex);
|
||||
|
||||
vkCmdCopyQueryPoolResults(m_rendererVk->m_state.currentCommandBuffer, m_rendererVk->m_occlusionQueries.queryPool, queryIndex, 1, m_rendererVk->m_occlusionQueries.bufferQueryResults, queryIndex * sizeof(uint64), 8, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
|
||||
list_queryFragments.back().m_finishCommandBuffer = m_rendererVk->GetCurrentCommandBufferId();
|
||||
list_queryFragments.back().isFinished = true;
|
||||
m_hasActiveFragment = false;
|
||||
}
|
||||
|
||||
void LatteQueryObjectVk::handleFinishedFragments()
|
||||
{
|
||||
// remove finished fragments and add to m_acccumulatedSum
|
||||
while (!list_queryFragments.empty())
|
||||
{
|
||||
auto& it = list_queryFragments.front();
|
||||
if (!it.isFinished)
|
||||
break;
|
||||
if (!m_rendererVk->HasCommandBufferFinished(it.m_finishCommandBuffer))
|
||||
break;
|
||||
m_acccumulatedSum += m_rendererVk->m_occlusionQueries.ptrQueryResults[it.queryIndex];
|
||||
releaseQueryIndex(it.queryIndex);
|
||||
list_queryFragments.erase(list_queryFragments.begin());
|
||||
}
|
||||
}
|
||||
|
||||
uint32 LatteQueryObjectVk::acquireQueryIndex()
|
||||
{
|
||||
if (m_rendererVk->m_occlusionQueries.list_availableQueryIndices.empty())
|
||||
{
|
||||
forceLog_printf("Vulkan-Error: Exhausted query pool");
|
||||
assert_dbg();
|
||||
}
|
||||
uint32 queryIndex = m_rendererVk->m_occlusionQueries.list_availableQueryIndices.back();
|
||||
m_rendererVk->m_occlusionQueries.list_availableQueryIndices.pop_back();
|
||||
return queryIndex;
|
||||
}
|
||||
|
||||
void LatteQueryObjectVk::releaseQueryIndex(uint32 queryIndex)
|
||||
{
|
||||
m_rendererVk->m_occlusionQueries.list_availableQueryIndices.emplace_back(queryIndex);
|
||||
}
|
||||
|
||||
void LatteQueryObjectVk::end()
|
||||
{
|
||||
cemu_assert_debug(!list_queryFragments.empty());
|
||||
if(m_hasActiveFragment)
|
||||
endFragment();
|
||||
m_vkQueryEnded = true;
|
||||
m_hasActiveQuery = false;
|
||||
m_finishCommandBuffer = m_rendererVk->GetCurrentCommandBufferId();
|
||||
m_rendererVk->m_occlusionQueries.m_lastCommandBuffer = m_finishCommandBuffer;
|
||||
m_rendererVk->RequestSubmitSoon(); // make sure the current command buffer gets submitted soon
|
||||
m_rendererVk->RequestSubmitOnIdle();
|
||||
}
|
||||
|
||||
LatteQueryObject* VulkanRenderer::occlusionQuery_create()
|
||||
{
|
||||
// create query pool if it doesn't already exist
|
||||
if(m_occlusionQueries.queryPool == VK_NULL_HANDLE)
|
||||
{
|
||||
VkQueryPoolCreateInfo queryPoolCreateInfo{};
|
||||
queryPoolCreateInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
|
||||
queryPoolCreateInfo.flags = 0;
|
||||
queryPoolCreateInfo.queryType = VK_QUERY_TYPE_OCCLUSION;
|
||||
queryPoolCreateInfo.queryCount = OCCLUSION_QUERY_POOL_SIZE;
|
||||
queryPoolCreateInfo.pipelineStatistics = 0;
|
||||
auto r = vkCreateQueryPool(m_logicalDevice, &queryPoolCreateInfo, nullptr, &m_occlusionQueries.queryPool);
|
||||
if (r != VK_SUCCESS)
|
||||
{
|
||||
forceLog_printf("Vulkan-Error: Failed to create query pool with error %d", (sint32)r);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
LatteQueryObjectVk* queryObjVk = nullptr;
|
||||
if (m_occlusionQueries.list_cachedQueries.empty())
|
||||
{
|
||||
queryObjVk = new LatteQueryObjectVk(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
queryObjVk = m_occlusionQueries.list_cachedQueries.front();
|
||||
m_occlusionQueries.list_cachedQueries.erase(m_occlusionQueries.list_cachedQueries.begin()+0);
|
||||
}
|
||||
queryObjVk->queryEnded = false;
|
||||
queryObjVk->queryEventStart = 0;
|
||||
queryObjVk->queryEventEnd = 0;
|
||||
queryObjVk->m_vkQueryEnded = false;
|
||||
queryObjVk->m_acccumulatedSum = 0;
|
||||
cemu_assert_debug(queryObjVk->list_queryFragments.empty()); // query fragment list should always be cleared in _destroy()
|
||||
m_occlusionQueries.list_currentlyActiveQueries.emplace_back(queryObjVk);
|
||||
return queryObjVk;
|
||||
}
|
||||
|
||||
void VulkanRenderer::occlusionQuery_destroy(LatteQueryObject* queryObj)
|
||||
{
|
||||
LatteQueryObjectVk* queryObjVk = static_cast<LatteQueryObjectVk*>(queryObj);
|
||||
m_occlusionQueries.list_currentlyActiveQueries.erase(std::remove(m_occlusionQueries.list_currentlyActiveQueries.begin(), m_occlusionQueries.list_currentlyActiveQueries.end(), queryObj), m_occlusionQueries.list_currentlyActiveQueries.end());
|
||||
m_occlusionQueries.list_cachedQueries.emplace_back(queryObjVk);
|
||||
for (auto& it : queryObjVk->list_queryFragments)
|
||||
queryObjVk->releaseQueryIndex(it.queryIndex);
|
||||
queryObjVk->list_queryFragments.clear();
|
||||
}
|
||||
|
||||
void VulkanRenderer::occlusionQuery_flush()
|
||||
{
|
||||
WaitCommandBufferFinished(m_occlusionQueries.m_lastCommandBuffer);
|
||||
}
|
||||
|
||||
void VulkanRenderer::occlusionQuery_updateState()
|
||||
{
|
||||
// check for finished command buffers here since query states are tied to buffers
|
||||
ProcessFinishedCommandBuffers();
|
||||
}
|
||||
|
||||
void VulkanRenderer::occlusionQuery_notifyEndCommandBuffer()
|
||||
{
|
||||
for (auto& it : m_occlusionQueries.list_currentlyActiveQueries)
|
||||
if(it->m_hasActiveQuery)
|
||||
it->endFragment();
|
||||
}
|
||||
|
||||
void VulkanRenderer::occlusionQuery_notifyBeginCommandBuffer()
|
||||
{
|
||||
for (auto& it : m_occlusionQueries.list_currentlyActiveQueries)
|
||||
if (it->m_hasActiveQuery)
|
||||
it->beginFragment();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue