fix for recompiler/interperter crash on arm

This commit is contained in:
SSimco
2024-05-25 07:07:33 +03:00
parent 9760bafb8a
commit fb03e66041
5 changed files with 239 additions and 168 deletions
@@ -153,8 +153,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;
@@ -167,7 +169,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())
@@ -198,8 +202,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)
@@ -211,7 +217,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)
@@ -752,8 +760,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;
}
+3 -1
View File
@@ -195,7 +195,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;
+43 -37
View File
@@ -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()
+143 -115
View File
@@ -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]) = _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]) = 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]), 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]);
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)
+31 -7
View File
@@ -2,7 +2,7 @@
#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)
@@ -13,6 +13,26 @@ struct GX2WriteGatherPipeState
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]);
gx2WriteGather_submit_(coreIndex, writePtr, std::forward<Targs>(args)...);
uint32be* writePtr = (uint32be*)(*data.writeGatherPtrWrite[coreIndex]);
gx2WriteGather_submit_(coreIndex, writePtr, std::forward<Targs>(args)...);
});
}
namespace GX2