mirror of
https://github.com/izzy2lost/WeeU.git
synced 2026-07-06 00:19:59 -07:00
Revert "GX2: Use atomic pointers rather than mutex (#3)"
This reverts commit 1e15f337ec.
This commit is contained in:
@@ -161,8 +161,10 @@ uint32 LatteCP_readU32Deprc()
|
||||
// no display list active
|
||||
while (true)
|
||||
{
|
||||
gxRingBufferWritePtr = gx2WriteGatherPipe.writeGatherPtrGxBuffer[GX2::sGX2MainCoreIndex];
|
||||
readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr);
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
gxRingBufferWritePtr = data.writeGatherPtrGxBuffer[GX2::sGX2MainCoreIndex];
|
||||
readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr);
|
||||
});
|
||||
if (readDistance != 0)
|
||||
break;
|
||||
|
||||
@@ -175,7 +177,9 @@ uint32 LatteCP_readU32Deprc()
|
||||
}
|
||||
LatteThread_HandleOSScreen(); // check if new frame was presented via OSScreen API
|
||||
|
||||
readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr);
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr);
|
||||
});
|
||||
if (readDistance != 0)
|
||||
break;
|
||||
if (Latte_GetStopSignal())
|
||||
@@ -206,8 +210,10 @@ void LatteCP_waitForNWords(uint32 numWords)
|
||||
// no display list active
|
||||
while (true)
|
||||
{
|
||||
gxRingBufferWritePtr = gx2WriteGatherPipe.writeGatherPtrGxBuffer[GX2::sGX2MainCoreIndex];
|
||||
readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr);
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
gxRingBufferWritePtr = data.writeGatherPtrGxBuffer[GX2::sGX2MainCoreIndex];
|
||||
readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr);
|
||||
});
|
||||
if (readDistance < 0)
|
||||
return; // wrap around means there is at least one full command queued after this
|
||||
if (readDistance >= waitDistance)
|
||||
@@ -219,7 +225,9 @@ void LatteCP_waitForNWords(uint32 numWords)
|
||||
{
|
||||
_mm_pause();
|
||||
}
|
||||
readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr);
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr);
|
||||
});
|
||||
if (readDistance < 0)
|
||||
return; // wrap around means there is at least one full command queued after this
|
||||
if (readDistance >= waitDistance)
|
||||
@@ -790,8 +798,11 @@ LatteCMDPtr LatteCP_itHLEFifoWrapAround(LatteCMDPtr cmd, uint32 nWords)
|
||||
{
|
||||
cemu_assert_debug(nWords == 1);
|
||||
uint32 unused = LatteReadCMD();
|
||||
gxRingBufferReadPtr = gx2WriteGatherPipe.gxRingBuffer;
|
||||
cmd = (LatteCMDPtr)gxRingBufferReadPtr;
|
||||
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
gxRingBufferReadPtr = data.gxRingBuffer;
|
||||
cmd = (LatteCMDPtr)gxRingBufferReadPtr;
|
||||
});
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
@@ -206,7 +206,9 @@ int Latte_ThreadEntry()
|
||||
if (Latte_GetStopSignal())
|
||||
LatteThread_Exit();
|
||||
}
|
||||
gxRingBufferReadPtr = gx2WriteGatherPipe.gxRingBuffer;
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
gxRingBufferReadPtr = data.gxRingBuffer;
|
||||
});
|
||||
LatteCP_ProcessRingbuffer();
|
||||
cemu_assert_debug(false); // should never reach
|
||||
return 0;
|
||||
|
||||
@@ -332,39 +332,43 @@ uint64 Latte_GetTime()
|
||||
|
||||
void _GX2SubmitToTCL()
|
||||
{
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
// do nothing if called from non-main GX2 core
|
||||
if (GX2::sGX2MainCoreIndex != coreIndex)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "_GX2SubmitToTCL() called on non-main GX2 core");
|
||||
return;
|
||||
}
|
||||
if( gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL )
|
||||
return; // quit if in display list
|
||||
_GX2LastFlushPtr[coreIndex] = (gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex]);
|
||||
// update last submitted CB timestamp
|
||||
uint64 commandBufferTimestamp = Latte_GetTime();
|
||||
LatteGPUState.lastSubmittedCommandBufferTimestamp.store(commandBufferTimestamp);
|
||||
cemuLog_log(LogType::GX2, "Submitting GX2 command buffer with timestamp {:016x}", commandBufferTimestamp);
|
||||
// submit HLE packet to write retirement timestamp
|
||||
gx2WriteGather_submitU32AsBE(pm4HeaderType3(IT_HLE_SET_CB_RETIREMENT_TIMESTAMP, 2));
|
||||
gx2WriteGather_submitU32AsBE((uint32)(commandBufferTimestamp>>32ULL));
|
||||
gx2WriteGather_submitU32AsBE((uint32)(commandBufferTimestamp&0xFFFFFFFFULL));
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
// do nothing if called from non-main GX2 core
|
||||
if (GX2::sGX2MainCoreIndex != coreIndex)
|
||||
{
|
||||
cemuLog_logDebug(LogType::Force, "_GX2SubmitToTCL() called on non-main GX2 core");
|
||||
return;
|
||||
}
|
||||
if (data.displayListStart[coreIndex] != MPTR_NULL)
|
||||
return; // quit if in display list
|
||||
_GX2LastFlushPtr[coreIndex] = (data.writeGatherPtrGxBuffer[coreIndex]);
|
||||
// update last submitted CB timestamp
|
||||
uint64 commandBufferTimestamp = Latte_GetTime();
|
||||
LatteGPUState.lastSubmittedCommandBufferTimestamp.store(commandBufferTimestamp);
|
||||
cemuLog_log(LogType::GX2, "Submitting GX2 command buffer with timestamp {:016x}", commandBufferTimestamp);
|
||||
// submit HLE packet to write retirement timestamp
|
||||
gx2WriteGather_submitU32AsBE(pm4HeaderType3(IT_HLE_SET_CB_RETIREMENT_TIMESTAMP, 2));
|
||||
gx2WriteGather_submitU32AsBE((uint32)(commandBufferTimestamp >> 32ULL));
|
||||
gx2WriteGather_submitU32AsBE((uint32)(commandBufferTimestamp & 0xFFFFFFFFULL));
|
||||
});
|
||||
}
|
||||
|
||||
uint32 _GX2GetUnflushedBytes(uint32 coreIndex)
|
||||
{
|
||||
uint32 unflushedBytes = 0;
|
||||
if (_GX2LastFlushPtr[coreIndex] != NULL)
|
||||
{
|
||||
if (_GX2LastFlushPtr[coreIndex] > gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex])
|
||||
unflushedBytes = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] - gx2WriteGatherPipe.gxRingBuffer + 4); // this isn't 100% correct since we ignore the bytes between the last flush address and the start of the wrap around
|
||||
return gx2WriteGatherPipe.accessDataRet<uint32>([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 unflushedBytes = 0;
|
||||
if (_GX2LastFlushPtr[coreIndex] != NULL)
|
||||
{
|
||||
if (_GX2LastFlushPtr[coreIndex] > data.writeGatherPtrGxBuffer[coreIndex])
|
||||
unflushedBytes = (uint32)(data.writeGatherPtrGxBuffer[coreIndex] - data.gxRingBuffer + 4); // this isn't 100% correct since we ignore the bytes between the last flush address and the start of the wrap around
|
||||
else
|
||||
unflushedBytes = (uint32)(data.writeGatherPtrGxBuffer[coreIndex] - _GX2LastFlushPtr[coreIndex]);
|
||||
}
|
||||
else
|
||||
unflushedBytes = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] - _GX2LastFlushPtr[coreIndex]);
|
||||
}
|
||||
else
|
||||
unflushedBytes = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] - gx2WriteGatherPipe.gxRingBuffer);
|
||||
return unflushedBytes;
|
||||
unflushedBytes = (uint32)(data.writeGatherPtrGxBuffer[coreIndex] - data.gxRingBuffer);
|
||||
return unflushedBytes;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -373,15 +377,17 @@ uint32 _GX2GetUnflushedBytes(uint32 coreIndex)
|
||||
*/
|
||||
void GX2ReserveCmdSpace(uint32 reservedFreeSpaceInU32)
|
||||
{
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
// if we are in a display list then do nothing
|
||||
if( gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL )
|
||||
return;
|
||||
uint32 unflushedBytes = _GX2GetUnflushedBytes(coreIndex);
|
||||
if( unflushedBytes >= 0x1000 )
|
||||
{
|
||||
_GX2SubmitToTCL();
|
||||
}
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
// if we are in a display list then do nothing
|
||||
if (data.displayListStart[coreIndex] != MPTR_NULL)
|
||||
return;
|
||||
uint32 unflushedBytes = _GX2GetUnflushedBytes(coreIndex);
|
||||
if (unflushedBytes >= 0x1000)
|
||||
{
|
||||
_GX2SubmitToTCL();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void gx2_load()
|
||||
|
||||
@@ -12,33 +12,39 @@
|
||||
|
||||
extern uint8* gxRingBufferReadPtr;
|
||||
|
||||
GX2WriteGatherPipeState gx2WriteGatherPipe = { 0 };
|
||||
GX2WriteGatherPipeState gx2WriteGatherPipe = { };
|
||||
|
||||
void gx2WriteGather_submitU32AsBE(uint32 v)
|
||||
{
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
if (*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] == NULL)
|
||||
return;
|
||||
*(uint32*)(gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]->load()) = _swapEndianU32(v);
|
||||
*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] += 4;
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
if (data.writeGatherPtrWrite[coreIndex] == NULL)
|
||||
return;
|
||||
*(uint32*)(*data.writeGatherPtrWrite[coreIndex]) = _swapEndianU32(v);
|
||||
(*data.writeGatherPtrWrite[coreIndex]) += 4;
|
||||
});
|
||||
}
|
||||
|
||||
void gx2WriteGather_submitU32AsLE(uint32 v)
|
||||
{
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
if (*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] == NULL)
|
||||
return;
|
||||
*(uint32*)(gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]->load()) = v;
|
||||
*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] += 4;
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
if (data.writeGatherPtrWrite[coreIndex] == NULL)
|
||||
return;
|
||||
*(uint32*)(*data.writeGatherPtrWrite[coreIndex]) = v;
|
||||
(*data.writeGatherPtrWrite[coreIndex]) += 4;
|
||||
});
|
||||
}
|
||||
|
||||
void gx2WriteGather_submitU32AsLEArray(uint32* v, uint32 numValues)
|
||||
{
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
if (*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] == NULL)
|
||||
return;
|
||||
memcpy_dwords(gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]->load(), v, numValues);
|
||||
*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] += 4 * numValues;
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
if (data.writeGatherPtrWrite[coreIndex] == NULL)
|
||||
return;
|
||||
memcpy_dwords((*data.writeGatherPtrWrite[coreIndex]), v, numValues);
|
||||
(*data.writeGatherPtrWrite[coreIndex]) += 4 * numValues;
|
||||
});
|
||||
}
|
||||
|
||||
namespace GX2
|
||||
@@ -54,136 +60,156 @@ namespace GX2
|
||||
|
||||
void GX2Init_writeGather() // init write gather, make current core
|
||||
{
|
||||
if (gx2WriteGatherPipe.gxRingBuffer == NULL)
|
||||
gx2WriteGatherPipe.gxRingBuffer = (uint8*)malloc(GX2_COMMAND_RING_BUFFER_SIZE);
|
||||
if (gx2WriteGatherCurrentMainCoreIndex == sGX2MainCoreIndex)
|
||||
return; // write gather already configured for same core
|
||||
for (sint32 i = 0; i < PPC_CORE_COUNT; i++)
|
||||
{
|
||||
if (i == sGX2MainCoreIndex)
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
if (data.gxRingBuffer == NULL)
|
||||
data.gxRingBuffer = (uint8*)malloc(GX2_COMMAND_RING_BUFFER_SIZE);
|
||||
if (gx2WriteGatherCurrentMainCoreIndex == sGX2MainCoreIndex)
|
||||
return; // write gather already configured for same core
|
||||
for (sint32 i = 0; i < PPC_CORE_COUNT; i++)
|
||||
{
|
||||
gx2WriteGatherPipe.writeGatherPtrGxBuffer[i] = gx2WriteGatherPipe.gxRingBuffer;
|
||||
gx2WriteGatherPipe.writeGatherPtrWrite[i] = &gx2WriteGatherPipe.writeGatherPtrGxBuffer[i];
|
||||
if (i == sGX2MainCoreIndex)
|
||||
{
|
||||
data.writeGatherPtrGxBuffer[i] = data.gxRingBuffer;
|
||||
data.writeGatherPtrWrite[i] = &data.writeGatherPtrGxBuffer[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
data.writeGatherPtrGxBuffer[i] = NULL;
|
||||
data.writeGatherPtrWrite[i] = NULL;
|
||||
}
|
||||
data.displayListStart[i] = MPTR_NULL;
|
||||
data.writeGatherPtrDisplayList[i] = NULL;
|
||||
data.displayListMaxSize[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gx2WriteGatherPipe.writeGatherPtrGxBuffer[i] = NULL;
|
||||
gx2WriteGatherPipe.writeGatherPtrWrite[i] = NULL;
|
||||
}
|
||||
gx2WriteGatherPipe.displayListStart[i] = MPTR_NULL;
|
||||
gx2WriteGatherPipe.writeGatherPtrDisplayList[i] = NULL;
|
||||
gx2WriteGatherPipe.displayListMaxSize[i] = 0;
|
||||
}
|
||||
gx2WriteGatherCurrentMainCoreIndex = sGX2MainCoreIndex;
|
||||
gx2WriteGatherInited = true;
|
||||
gx2WriteGatherCurrentMainCoreIndex = sGX2MainCoreIndex;
|
||||
gx2WriteGatherInited = true;
|
||||
});
|
||||
}
|
||||
|
||||
void GX2WriteGather_beginDisplayList(PPCInterpreter_t* hCPU, MPTR buffer, uint32 maxSize)
|
||||
{
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(hCPU);
|
||||
gx2WriteGatherPipe.displayListStart[coreIndex] = buffer;
|
||||
gx2WriteGatherPipe.displayListMaxSize[coreIndex] = maxSize;
|
||||
// set new write gather ptr
|
||||
gx2WriteGatherPipe.writeGatherPtrDisplayList[coreIndex] = memory_getPointerFromVirtualOffset(gx2WriteGatherPipe.displayListStart[coreIndex]);
|
||||
gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] = &gx2WriteGatherPipe.writeGatherPtrDisplayList[coreIndex];
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(hCPU);
|
||||
data.displayListStart[coreIndex] = buffer;
|
||||
data.displayListMaxSize[coreIndex] = maxSize;
|
||||
// set new write gather ptr
|
||||
data.writeGatherPtrDisplayList[coreIndex] = memory_getPointerFromVirtualOffset(data.displayListStart[coreIndex]);
|
||||
data.writeGatherPtrWrite[coreIndex] = &data.writeGatherPtrDisplayList[coreIndex];
|
||||
});
|
||||
}
|
||||
|
||||
uint32 GX2WriteGather_getDisplayListWriteDistance(sint32 coreIndex)
|
||||
{
|
||||
return (uint32)(*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] - memory_getPointerFromVirtualOffset(gx2WriteGatherPipe.displayListStart[coreIndex]));
|
||||
return gx2WriteGatherPipe.accessDataRet<uint32>([&](GX2WriteGatherPipeStateData& data) {
|
||||
return (uint32)(*data.writeGatherPtrWrite[coreIndex] - memory_getPointerFromVirtualOffset(data.displayListStart[coreIndex]));
|
||||
});
|
||||
}
|
||||
|
||||
uint32 GX2WriteGather_getFifoWriteDistance(uint32 coreIndex)
|
||||
{
|
||||
uint32 writeDistance = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] - gx2WriteGatherPipe.gxRingBuffer);
|
||||
return writeDistance;
|
||||
return gx2WriteGatherPipe.accessDataRet<uint32>([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 writeDistance = (uint32)(data.writeGatherPtrGxBuffer[coreIndex] - data.gxRingBuffer);
|
||||
return writeDistance;
|
||||
});
|
||||
}
|
||||
|
||||
uint32 GX2WriteGather_endDisplayList(PPCInterpreter_t* hCPU, MPTR buffer)
|
||||
{
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(hCPU);
|
||||
if (gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL)
|
||||
{
|
||||
uint32 currentWriteSize = GX2WriteGather_getDisplayListWriteDistance(coreIndex);
|
||||
// pad to 32 byte
|
||||
if (gx2WriteGatherPipe.displayListMaxSize[coreIndex] >= ((gx2WriteGatherPipe.displayListMaxSize[coreIndex] + 0x1F) & ~0x1F))
|
||||
return gx2WriteGatherPipe.accessDataRet<uint32>([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(hCPU);
|
||||
if (data.displayListStart[coreIndex] != MPTR_NULL)
|
||||
{
|
||||
while ((currentWriteSize & 0x1F) != 0)
|
||||
uint32 currentWriteSize = GX2WriteGather_getDisplayListWriteDistance(coreIndex);
|
||||
// pad to 32 byte
|
||||
if (data.displayListMaxSize[coreIndex] >= ((data.displayListMaxSize[coreIndex] + 0x1F) & ~0x1F))
|
||||
{
|
||||
gx2WriteGather_submitU32AsBE(pm4HeaderType2Filler());
|
||||
currentWriteSize += 4;
|
||||
while ((currentWriteSize & 0x1F) != 0)
|
||||
{
|
||||
gx2WriteGather_submitU32AsBE(pm4HeaderType2Filler());
|
||||
currentWriteSize += 4;
|
||||
}
|
||||
}
|
||||
// get size of written data
|
||||
currentWriteSize = GX2WriteGather_getDisplayListWriteDistance(coreIndex);
|
||||
// disable current display list and restore write gather ptr
|
||||
data.displayListStart[coreIndex] = MPTR_NULL;
|
||||
if (sGX2MainCoreIndex == coreIndex)
|
||||
data.writeGatherPtrWrite[coreIndex] = &data.writeGatherPtrGxBuffer[coreIndex];
|
||||
else
|
||||
data.writeGatherPtrWrite[coreIndex] = NULL;
|
||||
// return size of (written) display list
|
||||
return currentWriteSize;
|
||||
}
|
||||
// get size of written data
|
||||
currentWriteSize = GX2WriteGather_getDisplayListWriteDistance(coreIndex);
|
||||
// disable current display list and restore write gather ptr
|
||||
gx2WriteGatherPipe.displayListStart[coreIndex] = MPTR_NULL;
|
||||
if (sGX2MainCoreIndex == coreIndex)
|
||||
gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] = &gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex];
|
||||
else
|
||||
*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] = NULL;
|
||||
// return size of (written) display list
|
||||
return currentWriteSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no active display list
|
||||
// return a size of 0
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
// no active display list
|
||||
// return a size of 0
|
||||
return 0u;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool GX2GetCurrentDisplayList(betype<MPTR>* displayListAddr, uint32be* displayListSize)
|
||||
{
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
if (gx2WriteGatherPipe.displayListStart[coreIndex] == MPTR_NULL)
|
||||
return false;
|
||||
return gx2WriteGatherPipe.accessDataRet<bool>([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
if (data.displayListStart[coreIndex] == MPTR_NULL)
|
||||
return false;
|
||||
|
||||
if (displayListAddr)
|
||||
*displayListAddr = gx2WriteGatherPipe.displayListStart[coreIndex];
|
||||
if (displayListSize)
|
||||
*displayListSize = gx2WriteGatherPipe.displayListMaxSize[coreIndex];
|
||||
if (displayListAddr)
|
||||
*displayListAddr = data.displayListStart[coreIndex];
|
||||
if (displayListSize)
|
||||
*displayListSize = data.displayListMaxSize[coreIndex];
|
||||
|
||||
return true;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool GX2GetDisplayListWriteStatus()
|
||||
{
|
||||
// returns true if we are writing to a display list
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
return gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL;
|
||||
return gx2WriteGatherPipe.accessDataRet<bool>([&](GX2WriteGatherPipeStateData& data) {
|
||||
// returns true if we are writing to a display list
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
return data.displayListStart[coreIndex] != MPTR_NULL;
|
||||
});
|
||||
}
|
||||
|
||||
bool GX2WriteGather_isDisplayListActive()
|
||||
{
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
if (gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL)
|
||||
return true;
|
||||
return false;
|
||||
return gx2WriteGatherPipe.accessDataRet<bool>([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
if (data.displayListStart[coreIndex] != MPTR_NULL)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
uint32 GX2WriteGather_getReadWriteDistance()
|
||||
{
|
||||
uint32 coreIndex = sGX2MainCoreIndex;
|
||||
uint32 writeDistance = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] + GX2_COMMAND_RING_BUFFER_SIZE - gxRingBufferReadPtr);
|
||||
writeDistance %= GX2_COMMAND_RING_BUFFER_SIZE;
|
||||
return writeDistance;
|
||||
return gx2WriteGatherPipe.accessDataRet<bool>([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = sGX2MainCoreIndex;
|
||||
uint32 writeDistance = (uint32)(data.writeGatherPtrGxBuffer[coreIndex] + GX2_COMMAND_RING_BUFFER_SIZE - gxRingBufferReadPtr);
|
||||
writeDistance %= GX2_COMMAND_RING_BUFFER_SIZE;
|
||||
return writeDistance;
|
||||
});
|
||||
}
|
||||
|
||||
void GX2WriteGather_checkAndInsertWrapAroundMark()
|
||||
{
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
if (coreIndex != sGX2MainCoreIndex) // only if main gx2 core
|
||||
return;
|
||||
if (gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL)
|
||||
return;
|
||||
uint32 writeDistance = GX2WriteGather_getFifoWriteDistance(coreIndex);
|
||||
if (writeDistance >= (GX2_COMMAND_RING_BUFFER_SIZE * 3 / 5))
|
||||
{
|
||||
gx2WriteGather_submitU32AsBE(pm4HeaderType3(IT_HLE_FIFO_WRAP_AROUND, 1));
|
||||
gx2WriteGather_submitU32AsBE(0); // empty word since we can't send commands with zero data words
|
||||
gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] = gx2WriteGatherPipe.gxRingBuffer;
|
||||
}
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = coreinit::OSGetCoreId();
|
||||
if (coreIndex != sGX2MainCoreIndex) // only if main gx2 core
|
||||
return;
|
||||
if (data.displayListStart[coreIndex] != MPTR_NULL)
|
||||
return;
|
||||
uint32 writeDistance = GX2WriteGather_getFifoWriteDistance(coreIndex);
|
||||
if (writeDistance >= (GX2_COMMAND_RING_BUFFER_SIZE * 3 / 5))
|
||||
{
|
||||
gx2WriteGather_submitU32AsBE(pm4HeaderType3(IT_HLE_FIFO_WRAP_AROUND, 1));
|
||||
gx2WriteGather_submitU32AsBE(0); // empty word since we can't send commands with zero data words
|
||||
data.writeGatherPtrGxBuffer[coreIndex] = data.gxRingBuffer;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void GX2BeginDisplayList(MEMPTR<void> displayListAddr, uint32 size)
|
||||
@@ -217,23 +243,25 @@ namespace GX2
|
||||
|
||||
void GX2DirectCallDisplayList(void* addr, uint32 size)
|
||||
{
|
||||
// this API submits to TCL directly and bypasses write-gatherer
|
||||
// its basically a way to manually submit a command buffer to the GPU
|
||||
// as such it also affects the submission and retire timestamps
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
// this API submits to TCL directly and bypasses write-gatherer
|
||||
// its basically a way to manually submit a command buffer to the GPU
|
||||
// as such it also affects the submission and retire timestamps
|
||||
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
cemu_assert_debug(coreIndex == sGX2MainCoreIndex);
|
||||
coreIndex = sGX2MainCoreIndex; // always submit to main queue which is owned by GX2 main core (TCLSubmitToRing does not need this workaround)
|
||||
uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance());
|
||||
cemu_assert_debug(coreIndex == sGX2MainCoreIndex);
|
||||
coreIndex = sGX2MainCoreIndex; // always submit to main queue which is owned by GX2 main core (TCLSubmitToRing does not need this workaround)
|
||||
|
||||
uint32be* cmdStream = (uint32be*)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex].load());
|
||||
cmdStream[0] = pm4HeaderType3(IT_INDIRECT_BUFFER_PRIV, 3);
|
||||
cmdStream[1] = memory_virtualToPhysical(MEMPTR<void>(addr).GetMPTR());
|
||||
cmdStream[2] = 0;
|
||||
cmdStream[3] = size / 4;
|
||||
gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] += 16;
|
||||
uint32be* cmdStream = (uint32be*)(data.writeGatherPtrGxBuffer[coreIndex]);
|
||||
cmdStream[0] = pm4HeaderType3(IT_INDIRECT_BUFFER_PRIV, 3);
|
||||
cmdStream[1] = memory_virtualToPhysical(MEMPTR<void>(addr).GetMPTR());
|
||||
cmdStream[2] = 0;
|
||||
cmdStream[3] = size / 4;
|
||||
data.writeGatherPtrGxBuffer[coreIndex] += 16;
|
||||
|
||||
// update submission timestamp and retired timestamp
|
||||
_GX2SubmitToTCL();
|
||||
// update submission timestamp and retired timestamp
|
||||
_GX2SubmitToTCL();
|
||||
});
|
||||
}
|
||||
|
||||
void GX2CopyDisplayList(MEMPTR<uint32be*> addr, uint32 size)
|
||||
|
||||
@@ -2,17 +2,37 @@
|
||||
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
||||
#include "Cafe/HW/Espresso/Const.h"
|
||||
|
||||
struct GX2WriteGatherPipeState
|
||||
struct GX2WriteGatherPipeStateData
|
||||
{
|
||||
uint8* gxRingBuffer;
|
||||
// each core has it's own write gatherer and display list state (writing)
|
||||
std::atomic<uint8*> writeGatherPtrGxBuffer[Espresso::CORE_COUNT];
|
||||
std::atomic<uint8*>* writeGatherPtrWrite[Espresso::CORE_COUNT];
|
||||
std::atomic<uint8*> writeGatherPtrDisplayList[Espresso::CORE_COUNT];
|
||||
uint8* writeGatherPtrGxBuffer[Espresso::CORE_COUNT];
|
||||
uint8** writeGatherPtrWrite[Espresso::CORE_COUNT];
|
||||
uint8* writeGatherPtrDisplayList[Espresso::CORE_COUNT];
|
||||
MPTR displayListStart[Espresso::CORE_COUNT];
|
||||
uint32 displayListMaxSize[Espresso::CORE_COUNT];
|
||||
};
|
||||
|
||||
struct GX2WriteGatherPipeState
|
||||
{
|
||||
template<typename Fn>
|
||||
inline void accessData(Fn fn)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
fn(_data);
|
||||
}
|
||||
template<typename T, typename Fn>
|
||||
inline T accessDataRet(Fn fn)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
return fn(_data);
|
||||
}
|
||||
|
||||
private:
|
||||
std::recursive_mutex _mutex;
|
||||
GX2WriteGatherPipeStateData _data = {};
|
||||
};
|
||||
|
||||
extern GX2WriteGatherPipeState gx2WriteGatherPipe;
|
||||
|
||||
void GX2ReserveCmdSpace(uint32 reservedFreeSpaceInU32); // move to GX2 namespace eventually
|
||||
@@ -27,7 +47,9 @@ uint32 PPCInterpreter_getCurrentCoreIndex();
|
||||
template <typename ...Targs>
|
||||
inline void gx2WriteGather_submit_(uint32 coreIndex, uint32be* writePtr)
|
||||
{
|
||||
(*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]) = (uint8*)writePtr;
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
(*data.writeGatherPtrWrite[coreIndex]) = (uint8*)writePtr;
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T, typename ...Targs>
|
||||
@@ -74,12 +96,14 @@ gx2WriteGather_submit_(uint32 coreIndex, uint32be* writePtr, const T& arg, Targs
|
||||
template <typename ...Targs>
|
||||
inline void gx2WriteGather_submit(Targs... args)
|
||||
{
|
||||
uint32 coreIndex = PPCInterpreter_getCurrentCoreIndex();
|
||||
if (*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] == nullptr)
|
||||
return;
|
||||
gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) {
|
||||
uint32 coreIndex = PPCInterpreter_getCurrentCoreIndex();
|
||||
if (data.writeGatherPtrWrite[coreIndex] == nullptr)
|
||||
return;
|
||||
|
||||
uint32be* writePtr = (uint32be*)gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]->load();
|
||||
gx2WriteGather_submit_(coreIndex, writePtr, std::forward<Targs>(args)...);
|
||||
uint32be* writePtr = (uint32be*)(*data.writeGatherPtrWrite[coreIndex]);
|
||||
gx2WriteGather_submit_(coreIndex, writePtr, std::forward<Targs>(args)...);
|
||||
});
|
||||
}
|
||||
|
||||
namespace GX2
|
||||
|
||||
Reference in New Issue
Block a user