diff --git a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp index ab03ab25..167911b6 100644 --- a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp +++ b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp @@ -153,10 +153,8 @@ uint32 LatteCP_readU32Deprc() // no display list active while (true) { - gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) { - gxRingBufferWritePtr = data.writeGatherPtrGxBuffer[GX2::sGX2MainCoreIndex]; - readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr); - }); + gxRingBufferWritePtr = gx2WriteGatherPipe.writeGatherPtrGxBuffer[GX2::sGX2MainCoreIndex]; + readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr); if (readDistance != 0) break; @@ -169,9 +167,7 @@ uint32 LatteCP_readU32Deprc() } LatteThread_HandleOSScreen(); // check if new frame was presented via OSScreen API - gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) { - readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr); - }); + readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr); if (readDistance != 0) break; if (Latte_GetStopSignal()) @@ -202,10 +198,8 @@ void LatteCP_waitForNWords(uint32 numWords) // no display list active while (true) { - gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) { - gxRingBufferWritePtr = data.writeGatherPtrGxBuffer[GX2::sGX2MainCoreIndex]; - readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr); - }); + gxRingBufferWritePtr = gx2WriteGatherPipe.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) @@ -217,9 +211,7 @@ void LatteCP_waitForNWords(uint32 numWords) { _mm_pause(); } - gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) { - readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr); - }); + readDistance = (sint32)(gxRingBufferWritePtr - gxRingBufferReadPtr); if (readDistance < 0) return; // wrap around means there is at least one full command queued after this if (readDistance >= waitDistance) @@ -787,11 +779,8 @@ LatteCMDPtr LatteCP_itHLEFifoWrapAround(LatteCMDPtr cmd, uint32 nWords) { cemu_assert_debug(nWords == 1); uint32 unused = LatteReadCMD(); - - gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) { - gxRingBufferReadPtr = data.gxRingBuffer; - cmd = (LatteCMDPtr)gxRingBufferReadPtr; - }); + gxRingBufferReadPtr = gx2WriteGatherPipe.gxRingBuffer; + cmd = (LatteCMDPtr)gxRingBufferReadPtr; return cmd; } diff --git a/src/Cafe/HW/Latte/Core/LatteThread.cpp b/src/Cafe/HW/Latte/Core/LatteThread.cpp index 36751ba7..d2ca5e47 100644 --- a/src/Cafe/HW/Latte/Core/LatteThread.cpp +++ b/src/Cafe/HW/Latte/Core/LatteThread.cpp @@ -206,9 +206,7 @@ int Latte_ThreadEntry() if (Latte_GetStopSignal()) LatteThread_Exit(); } - gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) { - gxRingBufferReadPtr = data.gxRingBuffer; - }); + gxRingBufferReadPtr = gx2WriteGatherPipe.gxRingBuffer; LatteCP_ProcessRingbuffer(); cemu_assert_debug(false); // should never reach return 0; diff --git a/src/Cafe/OS/libs/gx2/GX2.cpp b/src/Cafe/OS/libs/gx2/GX2.cpp index 184ec1da..c2ea34a4 100644 --- a/src/Cafe/OS/libs/gx2/GX2.cpp +++ b/src/Cafe/OS/libs/gx2/GX2.cpp @@ -332,43 +332,39 @@ uint64 Latte_GetTime() void _GX2SubmitToTCL() { - 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 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)); } uint32 _GX2GetUnflushedBytes(uint32 coreIndex) { - return gx2WriteGatherPipe.accessDataRet([&](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]); - } + 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 else - unflushedBytes = (uint32)(data.writeGatherPtrGxBuffer[coreIndex] - data.gxRingBuffer); - return unflushedBytes; - }); + unflushedBytes = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] - _GX2LastFlushPtr[coreIndex]); + } + else + unflushedBytes = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] - gx2WriteGatherPipe.gxRingBuffer); + return unflushedBytes; } /* @@ -377,17 +373,15 @@ uint32 _GX2GetUnflushedBytes(uint32 coreIndex) */ void GX2ReserveCmdSpace(uint32 reservedFreeSpaceInU32) { - 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(); - } - }); + 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(); + } } void gx2_load() diff --git a/src/Cafe/OS/libs/gx2/GX2_Command.cpp b/src/Cafe/OS/libs/gx2/GX2_Command.cpp index 9ec5baea..c5afef61 100644 --- a/src/Cafe/OS/libs/gx2/GX2_Command.cpp +++ b/src/Cafe/OS/libs/gx2/GX2_Command.cpp @@ -12,39 +12,33 @@ extern uint8* gxRingBufferReadPtr; -GX2WriteGatherPipeState gx2WriteGatherPipe = { }; +GX2WriteGatherPipeState gx2WriteGatherPipe = { 0 }; void gx2WriteGather_submitU32AsBE(uint32 v) { - 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; - }); + uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance()); + if (*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] == NULL) + return; + *(uint32*)(gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]->load()) = _swapEndianU32(v); + *gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] += 4; } void gx2WriteGather_submitU32AsLE(uint32 v) { - 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; - }); + uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance()); + if (*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] == NULL) + return; + *(uint32*)(gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]->load()) = v; + *gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] += 4; } void gx2WriteGather_submitU32AsLEArray(uint32* v, uint32 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; - }); + 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; } namespace GX2 @@ -60,156 +54,136 @@ namespace GX2 void GX2Init_writeGather() // init write gather, make current core { - 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++) + 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) { - 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; + gx2WriteGatherPipe.writeGatherPtrGxBuffer[i] = gx2WriteGatherPipe.gxRingBuffer; + gx2WriteGatherPipe.writeGatherPtrWrite[i] = &gx2WriteGatherPipe.writeGatherPtrGxBuffer[i]; } - gx2WriteGatherCurrentMainCoreIndex = sGX2MainCoreIndex; - gx2WriteGatherInited = true; - }); + 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; } void GX2WriteGather_beginDisplayList(PPCInterpreter_t* hCPU, MPTR buffer, uint32 maxSize) { - 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 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]; } uint32 GX2WriteGather_getDisplayListWriteDistance(sint32 coreIndex) { - return gx2WriteGatherPipe.accessDataRet([&](GX2WriteGatherPipeStateData& data) { - return (uint32)(*data.writeGatherPtrWrite[coreIndex] - memory_getPointerFromVirtualOffset(data.displayListStart[coreIndex])); - }); + return (uint32)(*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] - memory_getPointerFromVirtualOffset(gx2WriteGatherPipe.displayListStart[coreIndex])); } uint32 GX2WriteGather_getFifoWriteDistance(uint32 coreIndex) { - return gx2WriteGatherPipe.accessDataRet([&](GX2WriteGatherPipeStateData& data) { - uint32 writeDistance = (uint32)(data.writeGatherPtrGxBuffer[coreIndex] - data.gxRingBuffer); - return writeDistance; - }); + uint32 writeDistance = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] - gx2WriteGatherPipe.gxRingBuffer); + return writeDistance; } uint32 GX2WriteGather_endDisplayList(PPCInterpreter_t* hCPU, MPTR buffer) { - return gx2WriteGatherPipe.accessDataRet([&](GX2WriteGatherPipeStateData& data) { - uint32 coreIndex = PPCInterpreter_getCoreIndex(hCPU); - if (data.displayListStart[coreIndex] != MPTR_NULL) + 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)) { - uint32 currentWriteSize = GX2WriteGather_getDisplayListWriteDistance(coreIndex); - // pad to 32 byte - if (data.displayListMaxSize[coreIndex] >= ((data.displayListMaxSize[coreIndex] + 0x1F) & ~0x1F)) + while ((currentWriteSize & 0x1F) != 0) { - while ((currentWriteSize & 0x1F) != 0) - { - gx2WriteGather_submitU32AsBE(pm4HeaderType2Filler()); - currentWriteSize += 4; - } + 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 - { - // no active display list - // return a size of 0 - return 0u; - } - }); + *gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] = NULL; + // return size of (written) display list + return currentWriteSize; + } + else + { + // no active display list + // return a size of 0 + return 0; + } } bool GX2GetCurrentDisplayList(betype* displayListAddr, uint32be* displayListSize) { - return gx2WriteGatherPipe.accessDataRet([&](GX2WriteGatherPipeStateData& data) { - uint32 coreIndex = coreinit::OSGetCoreId(); - if (data.displayListStart[coreIndex] == MPTR_NULL) - return false; + uint32 coreIndex = coreinit::OSGetCoreId(); + if (gx2WriteGatherPipe.displayListStart[coreIndex] == MPTR_NULL) + return false; - if (displayListAddr) - *displayListAddr = data.displayListStart[coreIndex]; - if (displayListSize) - *displayListSize = data.displayListMaxSize[coreIndex]; + if (displayListAddr) + *displayListAddr = gx2WriteGatherPipe.displayListStart[coreIndex]; + if (displayListSize) + *displayListSize = gx2WriteGatherPipe.displayListMaxSize[coreIndex]; - return true; - }); + return true; } bool GX2GetDisplayListWriteStatus() { - return gx2WriteGatherPipe.accessDataRet([&](GX2WriteGatherPipeStateData& data) { - // returns true if we are writing to a display list - uint32 coreIndex = coreinit::OSGetCoreId(); - return data.displayListStart[coreIndex] != MPTR_NULL; - }); + // returns true if we are writing to a display list + uint32 coreIndex = coreinit::OSGetCoreId(); + return gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL; } bool GX2WriteGather_isDisplayListActive() { - return gx2WriteGatherPipe.accessDataRet([&](GX2WriteGatherPipeStateData& data) { - uint32 coreIndex = coreinit::OSGetCoreId(); - if (data.displayListStart[coreIndex] != MPTR_NULL) - return true; - return false; - }); + uint32 coreIndex = coreinit::OSGetCoreId(); + if (gx2WriteGatherPipe.displayListStart[coreIndex] != MPTR_NULL) + return true; + return false; } uint32 GX2WriteGather_getReadWriteDistance() { - return gx2WriteGatherPipe.accessDataRet([&](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; - }); + uint32 coreIndex = sGX2MainCoreIndex; + uint32 writeDistance = (uint32)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] + GX2_COMMAND_RING_BUFFER_SIZE - gxRingBufferReadPtr); + writeDistance %= GX2_COMMAND_RING_BUFFER_SIZE; + return writeDistance; } void GX2WriteGather_checkAndInsertWrapAroundMark() { - 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; - } - }); + 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; + } } void GX2BeginDisplayList(MEMPTR displayListAddr, uint32 size) @@ -243,25 +217,23 @@ namespace GX2 void GX2DirectCallDisplayList(void* addr, uint32 size) { - 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 + // 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*)(data.writeGatherPtrGxBuffer[coreIndex]); - cmdStream[0] = pm4HeaderType3(IT_INDIRECT_BUFFER_PRIV, 3); - cmdStream[1] = memory_virtualToPhysical(MEMPTR(addr).GetMPTR()); - cmdStream[2] = 0; - cmdStream[3] = size / 4; - data.writeGatherPtrGxBuffer[coreIndex] += 16; + uint32be* cmdStream = (uint32be*)(gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex].load()); + cmdStream[0] = pm4HeaderType3(IT_INDIRECT_BUFFER_PRIV, 3); + cmdStream[1] = memory_virtualToPhysical(MEMPTR(addr).GetMPTR()); + cmdStream[2] = 0; + cmdStream[3] = size / 4; + gx2WriteGatherPipe.writeGatherPtrGxBuffer[coreIndex] += 16; - // update submission timestamp and retired timestamp - _GX2SubmitToTCL(); - }); + // update submission timestamp and retired timestamp + _GX2SubmitToTCL(); } void GX2CopyDisplayList(MEMPTR addr, uint32 size) diff --git a/src/Cafe/OS/libs/gx2/GX2_Command.h b/src/Cafe/OS/libs/gx2/GX2_Command.h index 9ddb53d2..fb9bb65e 100644 --- a/src/Cafe/OS/libs/gx2/GX2_Command.h +++ b/src/Cafe/OS/libs/gx2/GX2_Command.h @@ -2,37 +2,17 @@ #include "Cafe/HW/Latte/ISA/LatteReg.h" #include "Cafe/HW/Espresso/Const.h" -struct GX2WriteGatherPipeStateData +struct GX2WriteGatherPipeState { uint8* gxRingBuffer; // each core has it's own write gatherer and display list state (writing) - uint8* writeGatherPtrGxBuffer[Espresso::CORE_COUNT]; - uint8** writeGatherPtrWrite[Espresso::CORE_COUNT]; - uint8* writeGatherPtrDisplayList[Espresso::CORE_COUNT]; + std::atomic writeGatherPtrGxBuffer[Espresso::CORE_COUNT]; + std::atomic* writeGatherPtrWrite[Espresso::CORE_COUNT]; + std::atomic writeGatherPtrDisplayList[Espresso::CORE_COUNT]; MPTR displayListStart[Espresso::CORE_COUNT]; uint32 displayListMaxSize[Espresso::CORE_COUNT]; }; -struct GX2WriteGatherPipeState -{ - template - inline void accessData(Fn fn) - { - std::lock_guard lock(_mutex); - fn(_data); - } - template - 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 @@ -47,9 +27,7 @@ uint32 PPCInterpreter_getCurrentCoreIndex(); template inline void gx2WriteGather_submit_(uint32 coreIndex, uint32be* writePtr) { - gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) { - (*data.writeGatherPtrWrite[coreIndex]) = (uint8*)writePtr; - }); + (*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]) = (uint8*)writePtr; } template @@ -96,14 +74,12 @@ gx2WriteGather_submit_(uint32 coreIndex, uint32be* writePtr, const T& arg, Targs template inline void gx2WriteGather_submit(Targs... args) { - gx2WriteGatherPipe.accessData([&](GX2WriteGatherPipeStateData& data) { - uint32 coreIndex = PPCInterpreter_getCurrentCoreIndex(); - if (data.writeGatherPtrWrite[coreIndex] == nullptr) - return; + uint32 coreIndex = PPCInterpreter_getCurrentCoreIndex(); + if (*gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex] == nullptr) + return; - uint32be* writePtr = (uint32be*)(*data.writeGatherPtrWrite[coreIndex]); - gx2WriteGather_submit_(coreIndex, writePtr, std::forward(args)...); - }); + uint32be* writePtr = (uint32be*)gx2WriteGatherPipe.writeGatherPtrWrite[coreIndex]->load(); + gx2WriteGather_submit_(coreIndex, writePtr, std::forward(args)...); } namespace GX2