mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-04-26 13:05:34 -06:00
211 lines
5.7 KiB
C++
211 lines
5.7 KiB
C++
#include "Cafe/HW/Latte/ISA/RegDefines.h"
|
|
#include "Cafe/HW/Latte/Core/Latte.h"
|
|
|
|
#include "Cafe/HW/Latte/Core/LatteQueryObject.h"
|
|
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
|
|
|
#define GPU7_QUERY_TYPE_OCCLUSION (1)
|
|
|
|
uint64 queryEventCounter = 1;
|
|
|
|
struct LatteGX2QueryInformation
|
|
{
|
|
MPTR queryMPTR;
|
|
uint64 queryEventStart;
|
|
uint64 queryEventEnd;
|
|
uint64 sampleSum;
|
|
bool queryEnded;
|
|
};
|
|
|
|
std::vector<LatteGX2QueryInformation*> list_activeGX2Queries2;
|
|
|
|
std::vector<LatteQueryObject*> list_queriesInFlight;
|
|
|
|
uint64 latestQueryFinishedEventId = 0;
|
|
|
|
LatteQueryObject* _currentlyActiveRendererQuery = {0};
|
|
|
|
uint64 LatteQuery_getNextEventId()
|
|
{
|
|
uint64 ev = queryEventCounter;
|
|
queryEventCounter++;
|
|
return ev;
|
|
}
|
|
|
|
void LatteQuery_begin(LatteQueryObject* queryObject, uint64 eventId)
|
|
{
|
|
queryObject->queryEventStart = eventId;
|
|
queryObject->begin();
|
|
}
|
|
|
|
void LatteQuery_end(LatteQueryObject* queryObject, uint64 eventId)
|
|
{
|
|
cemu_assert_debug(!queryObject->queryEnded);
|
|
queryObject->queryEnded = true;
|
|
queryObject->queryEventEnd = eventId;
|
|
queryObject->end();
|
|
}
|
|
|
|
LatteQueryObject* LatteQuery_createSamplePassedQuery()
|
|
{
|
|
return g_renderer->occlusionQuery_create();
|
|
}
|
|
|
|
void LatteQuery_finishGX2Query(LatteGX2QueryInformation* gx2Query)
|
|
{
|
|
uint32* queryObjectData = (uint32*)memory_getPointerFromVirtualOffset(gx2Query->queryMPTR);
|
|
*(uint64*)(queryObjectData + 0) = 0;
|
|
*(uint64*)(queryObjectData + 2) = gx2Query->sampleSum;
|
|
*(uint64*)(queryObjectData + 4) = 0;
|
|
*(uint64*)(queryObjectData + 6) = 0;
|
|
|
|
*(uint64*)(queryObjectData + 8) = 0; // overwrites the 'OCPU' magic constant letting GX2QueryGetOcclusionResult know that the query is finished (for CPU queries)
|
|
}
|
|
|
|
void LatteQuery_UpdateFinishedQueries()
|
|
{
|
|
g_renderer->occlusionQuery_updateState();
|
|
for(uint32 i=0; i<list_queriesInFlight.size(); i++)
|
|
{
|
|
LatteQueryObject* queryObject = list_queriesInFlight[i];
|
|
cemu_assert_debug(queryObject->queryEnded);
|
|
if( queryObject->queryEnded == false )
|
|
continue;
|
|
// check if result is available
|
|
uint64 numSamplesPassed;
|
|
if (!queryObject->getResult(numSamplesPassed))
|
|
break;
|
|
|
|
cemu_assert_debug(latestQueryFinishedEventId < queryObject->queryEventEnd);
|
|
latestQueryFinishedEventId = queryObject->queryEventEnd;
|
|
|
|
// add number of passed samples to all gx2 queries that were active at the time
|
|
for (auto& it : list_activeGX2Queries2)
|
|
{
|
|
if (queryObject->queryEventStart >= it->queryEventStart && queryObject->queryEventEnd <= it->queryEventEnd)
|
|
it->sampleSum += numSamplesPassed;
|
|
}
|
|
|
|
list_queriesInFlight.erase(list_queriesInFlight.begin() + i);
|
|
i--;
|
|
g_renderer->occlusionQuery_destroy(queryObject);
|
|
}
|
|
// check for finished GX2 queries
|
|
for (sint32 i = 0; i < list_activeGX2Queries2.size(); i++)
|
|
{
|
|
auto gx2Query = list_activeGX2Queries2[i];
|
|
if (gx2Query->queryEnded && latestQueryFinishedEventId >= gx2Query->queryEventEnd)
|
|
{
|
|
LatteQuery_finishGX2Query(gx2Query);
|
|
free(gx2Query);
|
|
list_activeGX2Queries2.erase(list_activeGX2Queries2.begin() + i);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LatteQuery_UpdateFinishedQueriesForceFinishAll()
|
|
{
|
|
cemu_assert_debug(_currentlyActiveRendererQuery == nullptr);
|
|
g_renderer->occlusionQuery_flush(); // guarantees that all query commands have been submitted and finished processing
|
|
while (true)
|
|
{
|
|
LatteQuery_UpdateFinishedQueries();
|
|
if (list_queriesInFlight.empty())
|
|
break;
|
|
}
|
|
}
|
|
|
|
sint32 checkQueriesCounter = 0;
|
|
|
|
void LatteQuery_endActiveRendererQuery(uint64 currentEventId)
|
|
{
|
|
if (_currentlyActiveRendererQuery != nullptr)
|
|
{
|
|
LatteQuery_end(_currentlyActiveRendererQuery, currentEventId);
|
|
list_queriesInFlight.emplace_back(_currentlyActiveRendererQuery);
|
|
_currentlyActiveRendererQuery = nullptr;
|
|
}
|
|
}
|
|
|
|
void LatteQuery_BeginOcclusionQuery(MPTR queryMPTR)
|
|
{
|
|
if (checkQueriesCounter < 7)
|
|
{
|
|
checkQueriesCounter++;
|
|
}
|
|
else
|
|
{
|
|
LatteQuery_UpdateFinishedQueries();
|
|
checkQueriesCounter = 0;
|
|
}
|
|
|
|
for(auto& it : list_activeGX2Queries2)
|
|
{
|
|
if (it->queryMPTR == queryMPTR)
|
|
{
|
|
debug_printf("itHLEBeginOcclusionQuery: Query 0x%08x is already active\n", queryMPTR);
|
|
return;
|
|
}
|
|
}
|
|
uint64 currentEventId = LatteQuery_getNextEventId();
|
|
// end any currently active query
|
|
LatteQuery_endActiveRendererQuery(currentEventId);
|
|
// create GX2 query binding
|
|
LatteGX2QueryInformation* queryBinding = (LatteGX2QueryInformation*)malloc(sizeof(LatteGX2QueryInformation));
|
|
memset(queryBinding, 0x00, sizeof(LatteGX2QueryInformation));
|
|
queryBinding->queryEventStart = currentEventId;
|
|
queryBinding->queryMPTR = queryMPTR;
|
|
list_activeGX2Queries2.emplace_back(queryBinding);
|
|
// start renderer query
|
|
LatteQueryObject* queryObject = LatteQuery_createSamplePassedQuery();
|
|
LatteQuery_begin(queryObject, currentEventId);
|
|
_currentlyActiveRendererQuery = queryObject;
|
|
}
|
|
|
|
void LatteQuery_EndOcclusionQuery(MPTR queryMPTR)
|
|
{
|
|
if (queryMPTR == MPTR_NULL)
|
|
return;
|
|
uint64 currentEventId = LatteQuery_getNextEventId();
|
|
// mark query binding as ended
|
|
for(auto& it : list_activeGX2Queries2)
|
|
{
|
|
if (it->queryMPTR == queryMPTR)
|
|
{
|
|
it->queryEventEnd = currentEventId;
|
|
it->queryEnded = true;
|
|
break;
|
|
}
|
|
}
|
|
// end currently active renderer query
|
|
LatteQuery_endActiveRendererQuery(currentEventId);
|
|
// check if there are still active GX2 queries
|
|
bool hasActiveGX2Query = false;
|
|
for (auto& it : list_activeGX2Queries2)
|
|
{
|
|
if (!it->queryEnded)
|
|
{
|
|
hasActiveGX2Query = true;
|
|
break;
|
|
}
|
|
}
|
|
// start a new renderer query if there are still active GX2 queries
|
|
if (hasActiveGX2Query)
|
|
{
|
|
LatteQueryObject* queryObject = LatteQuery_createSamplePassedQuery();
|
|
LatteQuery_begin(queryObject, currentEventId);
|
|
list_queriesInFlight.emplace_back(queryObject);
|
|
_currentlyActiveRendererQuery = queryObject;
|
|
catchOpenGLError();
|
|
}
|
|
}
|
|
|
|
void LatteQuery_CancelActiveGPU7Queries()
|
|
{
|
|
cemu_assert_debug(_currentlyActiveRendererQuery == nullptr);
|
|
}
|
|
|
|
void LatteQuery_Init()
|
|
{
|
|
} |