Compare commits
38 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f60d5aac3e | ||
|
|
b8885aa03b | ||
|
|
c024e5c69a | ||
|
|
4efaecf125 | ||
|
|
902bf6d37d | ||
|
|
2cd788b6ad | ||
|
|
dd828607e0 | ||
|
|
b798813eee | ||
|
|
bb752df736 | ||
|
|
6fd3a1bf85 | ||
|
|
b72d2069ba | ||
|
|
5bce81c3d6 | ||
|
|
bae4e6c2f5 | ||
|
|
fff2de8224 | ||
|
|
3121acdf4e | ||
|
|
f3bb52c0a9 | ||
|
|
ec8d72a567 | ||
|
|
ab350b8975 | ||
|
|
42a00877a2 | ||
|
|
9619964e8c | ||
|
|
67a8e73101 | ||
|
|
f83c6e1e0c | ||
|
|
cfb7fd395c | ||
|
|
b62a8ca43e | ||
|
|
544fbd5c84 | ||
|
|
79504f1a39 | ||
|
|
25cd5d9dda | ||
|
|
2624b1eae6 | ||
|
|
da53bcee60 | ||
|
|
baff9ffcac | ||
|
|
66ac7cf730 | ||
|
|
53fbf8e206 | ||
|
|
551882e512 | ||
|
|
ed9ae5a977 | ||
|
|
e864aa25d5 | ||
|
|
836ec9176a | ||
|
|
34ec64233a | ||
|
|
c8135b3c18 |
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 82417da780...0e1112b7df
57
externals/microprofile/microprofile.h
vendored
57
externals/microprofile/microprofile.h
vendored
@@ -152,9 +152,11 @@ typedef uint16_t MicroProfileGroupId;
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#ifndef MICROPROFILE_API
|
||||
#define MICROPROFILE_API
|
||||
@@ -605,28 +607,45 @@ struct MicroProfileFrameState
|
||||
|
||||
struct MicroProfileThreadLog
|
||||
{
|
||||
MicroProfileLogEntry Log[MICROPROFILE_BUFFER_SIZE];
|
||||
std::array<MicroProfileLogEntry, MICROPROFILE_BUFFER_SIZE> Log{};
|
||||
|
||||
std::atomic<uint32_t> nPut;
|
||||
std::atomic<uint32_t> nGet;
|
||||
uint32_t nActive;
|
||||
uint32_t nGpu;
|
||||
ThreadIdType nThreadId;
|
||||
std::atomic<uint32_t> nPut{0};
|
||||
std::atomic<uint32_t> nGet{0};
|
||||
uint32_t nActive = 0;
|
||||
uint32_t nGpu = 0;
|
||||
ThreadIdType nThreadId{};
|
||||
|
||||
uint32_t nStack[MICROPROFILE_STACK_MAX];
|
||||
int64_t nChildTickStack[MICROPROFILE_STACK_MAX];
|
||||
uint32_t nStackPos;
|
||||
std::array<uint32_t, MICROPROFILE_STACK_MAX> nStack{};
|
||||
std::array<int64_t, MICROPROFILE_STACK_MAX> nChildTickStack{};
|
||||
uint32_t nStackPos = 0;
|
||||
|
||||
|
||||
uint8_t nGroupStackPos[MICROPROFILE_MAX_GROUPS];
|
||||
int64_t nGroupTicks[MICROPROFILE_MAX_GROUPS];
|
||||
int64_t nAggregateGroupTicks[MICROPROFILE_MAX_GROUPS];
|
||||
std::array<uint8_t, MICROPROFILE_MAX_GROUPS> nGroupStackPos{};
|
||||
std::array<int64_t, MICROPROFILE_MAX_GROUPS> nGroupTicks{};
|
||||
std::array<int64_t, MICROPROFILE_MAX_GROUPS> nAggregateGroupTicks{};
|
||||
enum
|
||||
{
|
||||
THREAD_MAX_LEN = 64,
|
||||
};
|
||||
char ThreadName[64];
|
||||
int nFreeListNext;
|
||||
char ThreadName[64]{};
|
||||
int nFreeListNext = 0;
|
||||
|
||||
void Reset() {
|
||||
Log.fill({});
|
||||
nPut = 0;
|
||||
nGet = 0;
|
||||
nActive = 0;
|
||||
nGpu = 0;
|
||||
nThreadId = {};
|
||||
nStack.fill(0);
|
||||
nChildTickStack.fill(0);
|
||||
nStackPos = 0;
|
||||
nGroupStackPos.fill(0);
|
||||
nGroupTicks.fill(0);
|
||||
nAggregateGroupTicks.fill(0);
|
||||
std::fill(std::begin(ThreadName), std::end(ThreadName), '\0');
|
||||
nFreeListNext = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#if MICROPROFILE_GPU_TIMERS_D3D11
|
||||
@@ -1151,6 +1170,7 @@ MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName)
|
||||
MP_ASSERT(pLog->nPut.load() == 0);
|
||||
MP_ASSERT(pLog->nGet.load() == 0);
|
||||
S.nFreeListHead = S.Pool[S.nFreeListHead]->nFreeListNext;
|
||||
pLog->Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1158,7 +1178,6 @@ MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName)
|
||||
S.nMemUsage += sizeof(MicroProfileThreadLog);
|
||||
S.Pool[S.nNumLogs++] = pLog;
|
||||
}
|
||||
memset(pLog, 0, sizeof(*pLog));
|
||||
int len = (int)strlen(pName);
|
||||
int maxlen = sizeof(pLog->ThreadName)-1;
|
||||
len = len < maxlen ? len : maxlen;
|
||||
@@ -1206,8 +1225,8 @@ void MicroProfileOnThreadExit()
|
||||
{
|
||||
S.Frames[i].nLogStart[nLogIndex] = 0;
|
||||
}
|
||||
memset(pLog->nGroupStackPos, 0, sizeof(pLog->nGroupStackPos));
|
||||
memset(pLog->nGroupTicks, 0, sizeof(pLog->nGroupTicks));
|
||||
pLog->nGroupStackPos.fill(0);
|
||||
pLog->nGroupTicks.fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
212
externals/microprofile/microprofileui.h
vendored
212
externals/microprofile/microprofileui.h
vendored
@@ -169,14 +169,13 @@ MICROPROFILEUI_API void MicroProfileCustomGroup(const char* pCustomName, uint32_
|
||||
MICROPROFILEUI_API void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer);
|
||||
|
||||
#ifdef MICROPROFILEUI_IMPL
|
||||
#ifdef _WIN32
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
MICROPROFILE_DEFINE(g_MicroProfileDetailed, "MicroProfile", "Detailed View", 0x8888000);
|
||||
MICROPROFILE_DEFINE(g_MicroProfileDrawGraph, "MicroProfile", "Draw Graph", 0xff44ee00);
|
||||
@@ -227,10 +226,10 @@ struct SOptionDesc
|
||||
uint8_t nIndex;
|
||||
bool bSelected;
|
||||
};
|
||||
static uint32_t g_MicroProfileAggregatePresets[] = {0, 10, 20, 30, 60, 120};
|
||||
static float g_MicroProfileReferenceTimePresets[] = {5.f, 10.f, 15.f,20.f, 33.33f, 66.66f, 100.f, 250.f, 500.f, 1000.f};
|
||||
static uint32_t g_MicroProfileOpacityPresets[] = {0x40, 0x80, 0xc0, 0xff};
|
||||
static const char* g_MicroProfilePresetNames[] =
|
||||
static const std::array<uint32_t, 6> g_MicroProfileAggregatePresets{0, 10, 20, 30, 60, 120};
|
||||
static const std::array<float, 10> g_MicroProfileReferenceTimePresets{5.f, 10.f, 15.f,20.f, 33.33f, 66.66f, 100.f, 250.f, 500.f, 1000.f};
|
||||
static const std::array<uint32_t, 4> g_MicroProfileOpacityPresets{0x40, 0x80, 0xc0, 0xff};
|
||||
static const std::array<const char*, 7> g_MicroProfilePresetNames
|
||||
{
|
||||
MICROPROFILE_DEFAULT_PRESET,
|
||||
"Render",
|
||||
@@ -243,8 +242,8 @@ static const char* g_MicroProfilePresetNames[] =
|
||||
|
||||
enum
|
||||
{
|
||||
MICROPROFILE_NUM_REFERENCE_PRESETS = sizeof(g_MicroProfileReferenceTimePresets)/sizeof(g_MicroProfileReferenceTimePresets[0]),
|
||||
MICROPROFILE_NUM_OPACITY_PRESETS = sizeof(g_MicroProfileOpacityPresets)/sizeof(g_MicroProfileOpacityPresets[0]),
|
||||
MICROPROFILE_NUM_REFERENCE_PRESETS = g_MicroProfileReferenceTimePresets.size(),
|
||||
MICROPROFILE_NUM_OPACITY_PRESETS = g_MicroProfileOpacityPresets.size(),
|
||||
#if MICROPROFILE_CONTEXT_SWITCH_TRACE
|
||||
MICROPROFILE_OPTION_SIZE = MICROPROFILE_NUM_REFERENCE_PRESETS + MICROPROFILE_NUM_OPACITY_PRESETS * 2 + 2 + 7,
|
||||
#else
|
||||
@@ -326,9 +325,9 @@ struct MicroProfileUI
|
||||
|
||||
MicroProfileUI g_MicroProfileUI;
|
||||
#define UI g_MicroProfileUI
|
||||
static uint32_t g_nMicroProfileBackColors[2] = { 0x474747, 0x313131 };
|
||||
static const std::array<uint32_t, 2> g_nMicroProfileBackColors{ 0x474747, 0x313131 };
|
||||
#define MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS 16
|
||||
static uint32_t g_nMicroProfileContextSwitchThreadColors[MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS] = //palette generated by http://tools.medialab.sciences-po.fr/iwanthue/index.php
|
||||
static const std::array<uint32_t, MICROPROFILE_NUM_CONTEXT_SWITCH_COLORS> g_nMicroProfileContextSwitchThreadColors //palette generated by http://tools.medialab.sciences-po.fr/iwanthue/index.php
|
||||
{
|
||||
0x63607B,
|
||||
0x755E2B,
|
||||
@@ -356,7 +355,7 @@ void MicroProfileInitUI()
|
||||
{
|
||||
bInitialized = true;
|
||||
memset(&g_MicroProfileUI, 0, sizeof(g_MicroProfileUI));
|
||||
UI.nActiveMenu = (uint32_t)-1;
|
||||
UI.nActiveMenu = UINT32_MAX;
|
||||
UI.fDetailedOffsetTarget = UI.fDetailedOffset = 0.f;
|
||||
UI.fDetailedRangeTarget = UI.fDetailedRange = 50.f;
|
||||
|
||||
@@ -368,7 +367,7 @@ void MicroProfileInitUI()
|
||||
UI.nWidth = 100;
|
||||
UI.nHeight = 100;
|
||||
|
||||
UI.nCustomActive = (uint32_t)-1;
|
||||
UI.nCustomActive = UINT32_MAX;
|
||||
UI.nCustomTimerCount = 0;
|
||||
UI.nCustomCount = 0;
|
||||
|
||||
@@ -498,8 +497,8 @@ inline void MicroProfileDrawFloatWindow(uint32_t nX, uint32_t nY, const char** p
|
||||
{
|
||||
MicroProfileDrawBox(nX-MICROPROFILE_TEXT_WIDTH, nY, nX, nY + MICROPROFILE_TEXT_WIDTH, pColors[i]|0xff000000);
|
||||
}
|
||||
MicroProfileDrawText(nX + 1, nY + 1, (uint32_t)-1, ppStrings[i0], (uint32_t)strlen(ppStrings[i0]));
|
||||
MicroProfileDrawText(nX + nWidth - nStringLengths[i0+1] * (MICROPROFILE_TEXT_WIDTH+1), nY + 1, (uint32_t)-1, ppStrings[i0+1], (uint32_t)strlen(ppStrings[i0+1]));
|
||||
MicroProfileDrawText(nX + 1, nY + 1, UINT32_MAX, ppStrings[i0], (uint32_t)strlen(ppStrings[i0]));
|
||||
MicroProfileDrawText(nX + nWidth - nStringLengths[i0+1] * (MICROPROFILE_TEXT_WIDTH+1), nY + 1, UINT32_MAX, ppStrings[i0+1], (uint32_t)strlen(ppStrings[i0+1]));
|
||||
nY += (MICROPROFILE_TEXT_HEIGHT+1);
|
||||
}
|
||||
}
|
||||
@@ -522,7 +521,7 @@ inline void MicroProfileDrawTextBox(uint32_t nX, uint32_t nY, const char** ppStr
|
||||
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000);
|
||||
for(uint32_t i = 0; i < nNumStrings; ++i)
|
||||
{
|
||||
MicroProfileDrawText(nX + 1, nY + 1, (uint32_t)-1, ppStrings[i], (uint32_t)strlen(ppStrings[i]));
|
||||
MicroProfileDrawText(nX + 1, nY + 1, UINT32_MAX, ppStrings[i], (uint32_t)strlen(ppStrings[i]));
|
||||
nY += (MICROPROFILE_TEXT_HEIGHT+1);
|
||||
}
|
||||
}
|
||||
@@ -781,7 +780,7 @@ inline void MicroProfileDrawDetailedContextSwitchBars(uint32_t nY, uint32_t nThr
|
||||
{
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
int64_t nTickIn = -1;
|
||||
uint32_t nThreadBefore = -1;
|
||||
uint32_t nThreadBefore = UINT32_MAX;
|
||||
float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
|
||||
float fMsToScreen = UI.nWidth / UI.fDetailedRange;
|
||||
float fMouseX = (float)UI.nMouseX;
|
||||
@@ -949,10 +948,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
|
||||
uint32_t nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadAfter;
|
||||
uint32_t nContextSwitchHoverThreadBefore = S.nContextSwitchHoverThreadBefore;
|
||||
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = -1;
|
||||
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = UINT32_MAX;
|
||||
|
||||
uint32_t nContextSwitchStart = -1;
|
||||
uint32_t nContextSwitchEnd = -1;
|
||||
uint32_t nContextSwitchStart = UINT32_MAX;
|
||||
uint32_t nContextSwitchEnd = UINT32_MAX;
|
||||
S.nContextSwitchHoverCpuNext = 0xff;
|
||||
S.nContextSwitchHoverTickIn = -1;
|
||||
S.nContextSwitchHoverTickOut = -1;
|
||||
@@ -1005,9 +1004,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
}while(pFrameLogFirst != pFrameFirst);
|
||||
|
||||
|
||||
if(nGet == (uint32_t)-1)
|
||||
if (nGet == UINT32_MAX) {
|
||||
continue;
|
||||
MP_ASSERT(nGet != (uint32_t)-1);
|
||||
}
|
||||
MP_ASSERT(nGet != UINT32_MAX);
|
||||
|
||||
nPut = pFrameLogLast->nLogStart[i];
|
||||
|
||||
@@ -1023,9 +1023,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
int64_t nBaseTicks = bGpu ? nBaseTicksGpu : nBaseTicksCpu;
|
||||
char ThreadName[MicroProfileThreadLog::THREAD_MAX_LEN + 16];
|
||||
uint64_t nThreadId = pLog->nThreadId;
|
||||
snprintf(ThreadName, sizeof(ThreadName)-1, "%04llx: %s", nThreadId, &pLog->ThreadName[0] );
|
||||
snprintf(ThreadName, sizeof(ThreadName)-1, "%04" PRIx64 ": %s", nThreadId, &pLog->ThreadName[0] );
|
||||
nY += 3;
|
||||
uint32_t nThreadColor = -1;
|
||||
uint32_t nThreadColor = UINT32_MAX;
|
||||
if(pLog->nThreadId == nContextSwitchHoverThreadAfter || pLog->nThreadId == nContextSwitchHoverThreadBefore)
|
||||
nThreadColor = UI.nHoverColorShared|0x906060;
|
||||
MicroProfileDrawText(0, nY, nThreadColor, &ThreadName[0], (uint32_t)strlen(&ThreadName[0]));
|
||||
@@ -1048,7 +1048,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
uint32_t nEnd = nRange[j][1];
|
||||
for(uint32_t k = nStart; k < nEnd; ++k)
|
||||
{
|
||||
MicroProfileLogEntry* pEntry = pLog->Log + k;
|
||||
MicroProfileLogEntry* pEntry = &pLog->Log[k];
|
||||
int nType = MicroProfileLogType(*pEntry);
|
||||
if(MP_LOG_ENTER == nType)
|
||||
{
|
||||
@@ -1066,7 +1066,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
continue;
|
||||
}
|
||||
|
||||
MicroProfileLogEntry* pEntryEnter = pLog->Log + nStack[nStackPos-1];
|
||||
MicroProfileLogEntry* pEntryEnter = &pLog->Log[nStack[nStackPos-1]];
|
||||
if(MicroProfileLogTimerIndex(*pEntryEnter) != MicroProfileLogTimerIndex(*pEntry))
|
||||
{
|
||||
//uprintf("mismatch %llx %llx\n", pEntryEnter->nToken, pEntry->nToken);
|
||||
@@ -1126,7 +1126,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
uint32_t nIntegerWidth = (uint32_t)(fXEnd - fXStart);
|
||||
if(nIntegerWidth)
|
||||
{
|
||||
if(bHover && UI.nActiveMenu == -1)
|
||||
if(bHover && UI.nActiveMenu == UINT32_MAX)
|
||||
{
|
||||
nHoverToken = MicroProfileLogTimerIndex(*pEntry);
|
||||
#if MICROPROFILE_DEBUG
|
||||
@@ -1146,7 +1146,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
int nCharacters = (nTextWidth - 2*MICROPROFILE_TEXT_WIDTH) / MICROPROFILE_TEXT_WIDTH;
|
||||
if(nCharacters>0)
|
||||
{
|
||||
MicroProfileDrawText(fXStartText+1, fYStart+1, -1, S.TimerInfo[nTimerIndex].pName, MicroProfileMin<uint32_t>(S.TimerInfo[nTimerIndex].nNameLen, nCharacters));
|
||||
MicroProfileDrawText(fXStartText + 1, fYStart + 1, UINT32_MAX, S.TimerInfo[nTimerIndex].pName, MicroProfileMin<uint32_t>(S.TimerInfo[nTimerIndex].nNameLen, nCharacters));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1158,7 +1158,7 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
int nLineX = (int)floor(fXAvg+0.5f);
|
||||
if(nLineX != (int)nLinesDrawn[nStackPos])
|
||||
{
|
||||
if(bHover && UI.nActiveMenu == -1)
|
||||
if(bHover && UI.nActiveMenu == UINT32_MAX)
|
||||
{
|
||||
nHoverToken = (uint32_t)MicroProfileLogTimerIndex(*pEntry);
|
||||
nHoverTime = MicroProfileLogTickDifference(nTickStart, nTickEnd);
|
||||
@@ -1235,9 +1235,9 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
// nThreadId is 32-bit on Windows
|
||||
int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04x: %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) );
|
||||
#else
|
||||
int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04llx: %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) );
|
||||
int nStrLen = snprintf(ThreadName, sizeof(ThreadName)-1, "%04" PRIx64 ": %s%s", nThreadId, cLocal, i < nNumThreadsBase ? &S.Pool[i]->ThreadName[0] : MICROPROFILE_THREAD_NAME_FROM_ID(nThreadId) );
|
||||
#endif
|
||||
uint32_t nThreadColor = -1;
|
||||
uint32_t nThreadColor = UINT32_MAX;
|
||||
if(nThreadId == nContextSwitchHoverThreadAfter || nThreadId == nContextSwitchHoverThreadBefore)
|
||||
nThreadColor = UI.nHoverColorShared|0x906060;
|
||||
MicroProfileDrawDetailedContextSwitchBars(nY+2, nThreadId, nContextSwitchStart, nContextSwitchEnd, nBaseTicksCpu, nBaseY);
|
||||
@@ -1249,9 +1249,6 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
|
||||
S.nContextSwitchHoverCpu = S.nContextSwitchHoverCpuNext;
|
||||
|
||||
|
||||
|
||||
|
||||
UI.pDisplayMouseOver = pMouseOverNext;
|
||||
|
||||
if(!S.nRunning)
|
||||
@@ -1286,10 +1283,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart);
|
||||
float fStartTextX = fXStart - fStartTextWidth - 2;
|
||||
MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
|
||||
MicroProfileDrawText(fStartTextX+1, nBaseY, (uint32_t)-1, sBuffer, nLenStart);
|
||||
MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart);
|
||||
uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd);
|
||||
MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
|
||||
MicroProfileDrawText(fXEnd+2, nBaseY+1, (uint32_t)-1, sBuffer, nLenEnd);
|
||||
MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd);
|
||||
|
||||
if(UI.nMouseRight)
|
||||
{
|
||||
@@ -1316,10 +1313,10 @@ inline void MicroProfileDrawDetailedBars(uint32_t nWidth, uint32_t nHeight, int
|
||||
float fStartTextWidth = (float)((1+MICROPROFILE_TEXT_WIDTH) * nLenStart);
|
||||
float fStartTextX = fXStart - fStartTextWidth - 2;
|
||||
MicroProfileDrawBox(fStartTextX, nBaseY, fStartTextX + fStartTextWidth + 2, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
|
||||
MicroProfileDrawText(fStartTextX+1, nBaseY, (uint32_t)-1, sBuffer, nLenStart);
|
||||
MicroProfileDrawText(fStartTextX+1, nBaseY, UINT32_MAX, sBuffer, nLenStart);
|
||||
uint32_t nLenEnd = snprintf(sBuffer, sizeof(sBuffer)-1, "%.2fms", fMsEnd);
|
||||
MicroProfileDrawBox(fXEnd+1, nBaseY, fXEnd+1+(1+MICROPROFILE_TEXT_WIDTH) * nLenEnd + 3, MICROPROFILE_TEXT_HEIGHT + 2 + nBaseY, 0x33000000, MicroProfileBoxTypeFlat);
|
||||
MicroProfileDrawText(fXEnd+2, nBaseY+1, (uint32_t)-1, sBuffer, nLenEnd);
|
||||
MicroProfileDrawText(fXEnd+2, nBaseY+1, UINT32_MAX, sBuffer, nLenEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1365,7 +1362,7 @@ inline void MicroProfileDrawDetailedFrameHistory(uint32_t nWidth, uint32_t nHeig
|
||||
fBaseX = fXStart;
|
||||
uint32_t nColor = MICROPROFILE_FRAME_HISTORY_COLOR_CPU;
|
||||
if(nIndex == nSelectedFrame)
|
||||
nColor = (uint32_t)-1;
|
||||
nColor = UINT32_MAX;
|
||||
MicroProfileDrawBox(fXStart, nBaseY + fScale * nBarHeight, fXEnd, nBaseY+MICROPROFILE_FRAME_HISTORY_HEIGHT, nColor, MicroProfileBoxTypeBar);
|
||||
if(pNext->nFrameStartCpu > nCpuStart)
|
||||
{
|
||||
@@ -1387,7 +1384,7 @@ inline void MicroProfileDrawDetailedView(uint32_t nWidth, uint32_t nHeight)
|
||||
uint32_t nBaseY = MICROPROFILE_TEXT_HEIGHT + 1;
|
||||
|
||||
int nSelectedFrame = -1;
|
||||
if(UI.nMouseY > nBaseY && UI.nMouseY <= nBaseY + MICROPROFILE_FRAME_HISTORY_HEIGHT && UI.nActiveMenu == -1)
|
||||
if(UI.nMouseY > nBaseY && UI.nMouseY <= nBaseY + MICROPROFILE_FRAME_HISTORY_HEIGHT && UI.nActiveMenu == UINT32_MAX)
|
||||
{
|
||||
|
||||
nSelectedFrame = ((MICROPROFILE_NUM_FRAMES) * (UI.nWidth-UI.nMouseX) / UI.nWidth);
|
||||
@@ -1425,7 +1422,7 @@ inline void MicroProfileDrawHeader(int32_t nX, uint32_t nWidth, const char* pNam
|
||||
if(pName)
|
||||
{
|
||||
MicroProfileDrawBox(nX-8, MICROPROFILE_TEXT_HEIGHT + 2, nX + nWidth+5, MICROPROFILE_TEXT_HEIGHT + 2 + (MICROPROFILE_TEXT_HEIGHT+1), 0xff000000|g_nMicroProfileBackColors[1]);
|
||||
MicroProfileDrawText(nX, MICROPROFILE_TEXT_HEIGHT + 2, (uint32_t)-1, pName, (uint32_t)strlen(pName));
|
||||
MicroProfileDrawText(nX, MICROPROFILE_TEXT_HEIGHT + 2, UINT32_MAX, pName, (uint32_t)strlen(pName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1440,7 +1437,7 @@ inline void MicroProfileLoopActiveGroupsDraw(int32_t nX, int32_t nY, const char*
|
||||
uint32_t nCount = 0;
|
||||
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
|
||||
{
|
||||
uint64_t nMask = 1ll << j;
|
||||
uint64_t nMask = 1ULL << j;
|
||||
if(nMask & nGroup)
|
||||
{
|
||||
nY += MICROPROFILE_TEXT_HEIGHT + 1;
|
||||
@@ -1521,7 +1518,7 @@ inline void MicroProfileCalcTimers(float* pTimers, float* pAverage, float* pMax,
|
||||
}
|
||||
}
|
||||
}
|
||||
nMask <<= 1ll;
|
||||
nMask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1543,7 +1540,7 @@ inline void MicroProfileDrawBarArrayCallback(uint32_t nTimer, uint32_t nIdx, uin
|
||||
snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pTimers[nIdx]);
|
||||
if (!pTimers2)
|
||||
MicroProfileDrawBox(nX + nTextWidth, nY, nX + nTextWidth + fWidth * pTimers[nIdx+1], nY + nHeight, UI.nOpacityForeground|S.TimerInfo[nTimer].nColor, MicroProfileBoxTypeBar);
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, sBuffer, (uint32_t)strlen(sBuffer));
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, sBuffer, (uint32_t)strlen(sBuffer));
|
||||
}
|
||||
|
||||
|
||||
@@ -1564,7 +1561,7 @@ inline void MicroProfileDrawBarCallCountCallback(uint32_t nTimer, uint32_t nIdx,
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
char sBuffer[SBUF_MAX];
|
||||
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5d", S.Frame[nTimer].nCount);//fix
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, sBuffer, nLen);
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, sBuffer, nLen);
|
||||
}
|
||||
|
||||
inline uint32_t MicroProfileDrawBarCallCount(int32_t nX, int32_t nY, const char* pName)
|
||||
@@ -1588,7 +1585,7 @@ inline void MicroProfileDrawBarMetaAverageCallback(uint32_t nTimer, uint32_t nId
|
||||
float fRcpFrames = pArgs->fRcpFrames;
|
||||
char sBuffer[SBUF_MAX];
|
||||
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5.2f", pCounters[nTimer] * fRcpFrames);
|
||||
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, (uint32_t)-1, sBuffer, nLen);
|
||||
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, UINT32_MAX, sBuffer, nLen);
|
||||
}
|
||||
|
||||
inline uint32_t MicroProfileDrawBarMetaAverage(int32_t nX, int32_t nY, uint64_t* pCounters, const char* pName, uint32_t nTotalHeight)
|
||||
@@ -1609,8 +1606,8 @@ inline void MicroProfileDrawBarMetaCountCallback(uint32_t nTimer, uint32_t nIdx,
|
||||
{
|
||||
uint64_t* pCounters = (uint64_t*)pExtra;
|
||||
char sBuffer[SBUF_MAX];
|
||||
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5llu", pCounters[nTimer]);
|
||||
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, (uint32_t)-1, sBuffer, nLen);
|
||||
int nLen = snprintf(sBuffer, SBUF_MAX-1, "%5" PRIu64, pCounters[nTimer]);
|
||||
MicroProfileDrawText(nX - nLen * (MICROPROFILE_TEXT_WIDTH+1), nY, UINT32_MAX, sBuffer, nLen);
|
||||
}
|
||||
|
||||
inline uint32_t MicroProfileDrawBarMetaCount(int32_t nX, int32_t nY, uint64_t* pCounters, const char* pName, uint32_t nTotalHeight)
|
||||
@@ -1667,7 +1664,7 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight)
|
||||
if(bMouseOver)
|
||||
{
|
||||
float fXAvg = fMouseXPrc * MICROPROFILE_GRAPH_WIDTH + nX;
|
||||
MicroProfileDrawLineVertical(fXAvg, nY, nY + MICROPROFILE_GRAPH_HEIGHT, (uint32_t)-1);
|
||||
MicroProfileDrawLineVertical(fXAvg, nY, nY + MICROPROFILE_GRAPH_HEIGHT, UINT32_MAX);
|
||||
}
|
||||
|
||||
|
||||
@@ -1706,7 +1703,7 @@ bool MicroProfileDrawGraph(uint32_t nScreenWidth, uint32_t nScreenHeight)
|
||||
|
||||
char buf[32];
|
||||
int nLen = snprintf(buf, sizeof(buf)-1, "%5.2fms", S.fReferenceTime);
|
||||
MicroProfileDrawText(nX+1, fY1 - (2+MICROPROFILE_TEXT_HEIGHT), (uint32_t)-1, buf, nLen);
|
||||
MicroProfileDrawText(nX+1, fY1 - (2+MICROPROFILE_TEXT_HEIGHT), UINT32_MAX, buf, nLen);
|
||||
}
|
||||
|
||||
|
||||
@@ -1782,7 +1779,7 @@ void MicroProfileDumpTimers()
|
||||
|
||||
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
|
||||
{
|
||||
uint64_t nMask = 1ll << j;
|
||||
uint64_t nMask = 1ULL << j;
|
||||
if(nMask & nActiveGroup)
|
||||
{
|
||||
MICROPROFILE_PRINTF("%s\n", S.GroupInfo[j].pName);
|
||||
@@ -1823,7 +1820,7 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
|
||||
uint32_t nNumGroups = 0;
|
||||
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
|
||||
{
|
||||
if(nActiveGroup & (1ll << j))
|
||||
if(nActiveGroup & (1ULL << j))
|
||||
{
|
||||
nNumTimers += S.GroupInfo[j].nNumTimers;
|
||||
nNumGroups += 1;
|
||||
@@ -1878,7 +1875,7 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
|
||||
for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i)
|
||||
{
|
||||
uint32_t nY0 = nY + i * (nHeight + 1);
|
||||
bool bInside = (UI.nActiveMenu == -1) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
|
||||
bool bInside = (UI.nActiveMenu == UINT32_MAX) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
|
||||
MicroProfileDrawBox(nX, nY0, nWidth+nX, nY0 + (nHeight+1)+1, UI.nOpacityBackground | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0)));
|
||||
}
|
||||
nX += 10;
|
||||
@@ -1927,22 +1924,22 @@ inline void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeigh
|
||||
nY = nHeight + 3 - UI.nOffsetY;
|
||||
for(uint32_t i = 0; i < nNumTimers+nNumGroups+1; ++i)
|
||||
{
|
||||
uint32_t nY0 = nY + i * (nHeight + 1);
|
||||
bool bInside = (UI.nActiveMenu == -1) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
|
||||
const uint32_t nY0 = nY + i * (nHeight + 1);
|
||||
const bool bInside = (UI.nActiveMenu == UINT32_MAX) && ((UI.nMouseY >= nY0) && (UI.nMouseY < (nY0 + nHeight + 1)));
|
||||
MicroProfileDrawBox(nX, nY0, nTimerWidth, nY0 + (nHeight+1)+1, 0xff0000000 | (g_nMicroProfileBackColors[nColorIndex++ & 1] + ((bInside) ? 0x002c2c2c : 0)));
|
||||
}
|
||||
nX += MicroProfileDrawBarLegend(nX, nY, nTotalHeight, nTimerWidth-5) + 1;
|
||||
|
||||
for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
|
||||
{
|
||||
if(nActiveGroup & (1ll << j))
|
||||
if(nActiveGroup & (1ULL << j))
|
||||
{
|
||||
MicroProfileDrawText(nX, nY + (1+nHeight) * nLegendOffset, (uint32_t)-1, S.GroupInfo[j].pName, S.GroupInfo[j].nNameLen);
|
||||
MicroProfileDrawText(nX, nY + (1+nHeight) * nLegendOffset, UINT32_MAX, S.GroupInfo[j].pName, S.GroupInfo[j].nNameLen);
|
||||
nLegendOffset += S.GroupInfo[j].nNumTimers+1;
|
||||
}
|
||||
}
|
||||
MicroProfileDrawHeader(nX, nTimerWidth-5, "Group");
|
||||
MicroProfileDrawTextRight(nTimerWidth-3, MICROPROFILE_TEXT_HEIGHT + 2, (uint32_t)-1, "Timer", 5);
|
||||
MicroProfileDrawTextRight(nTimerWidth-3, MICROPROFILE_TEXT_HEIGHT + 2, UINT32_MAX, "Timer", 5);
|
||||
MicroProfileDrawLineVertical(nTimerWidth, 0, nTotalHeight+nY, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]);
|
||||
MicroProfileDrawLineHorizontal(0, nWidth, 2*MICROPROFILE_TEXT_HEIGHT + 3, UI.nOpacityBackground|g_nMicroProfileBackColors[0]|g_nMicroProfileBackColors[1]);
|
||||
}
|
||||
@@ -2003,7 +2000,7 @@ inline const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected)
|
||||
}
|
||||
else
|
||||
{
|
||||
*bSelected = 0 != (S.nActiveGroupWanted & (1ll << Item.nIndex));
|
||||
*bSelected = 0 != (S.nActiveGroupWanted & (1ULL << Item.nIndex));
|
||||
snprintf(buffer, sizeof(buffer)-1, " %s", Item.pName);
|
||||
}
|
||||
return buffer;
|
||||
@@ -2015,16 +2012,18 @@ inline const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected)
|
||||
inline const char* MicroProfileUIMenuAggregate(int nIndex, bool* bSelected)
|
||||
{
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
if(nIndex < sizeof(g_MicroProfileAggregatePresets)/sizeof(g_MicroProfileAggregatePresets[0]))
|
||||
if(static_cast<uint32_t>(nIndex) < g_MicroProfileAggregatePresets.size())
|
||||
{
|
||||
int val = g_MicroProfileAggregatePresets[nIndex];
|
||||
*bSelected = (int)S.nAggregateFlip == val;
|
||||
if(0 == val)
|
||||
uint32_t val = g_MicroProfileAggregatePresets[nIndex];
|
||||
*bSelected = S.nAggregateFlip == val;
|
||||
if (0 == val)
|
||||
{
|
||||
return "Infinite";
|
||||
}
|
||||
else
|
||||
{
|
||||
static char buf[128];
|
||||
snprintf(buf, sizeof(buf)-1, "%7d", val);
|
||||
snprintf(buf, sizeof(buf)-1, "%7u", val);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
@@ -2098,11 +2097,13 @@ inline const char* MicroProfileUIMenuPreset(int nIndex, bool* bSelected)
|
||||
{
|
||||
static char buf[128];
|
||||
*bSelected = false;
|
||||
int nNumPresets = sizeof(g_MicroProfilePresetNames) / sizeof(g_MicroProfilePresetNames[0]);
|
||||
int nNumPresets = static_cast<int>(g_MicroProfilePresetNames.size());
|
||||
int nIndexSave = nIndex - nNumPresets - 1;
|
||||
if(nIndex == nNumPresets)
|
||||
if (nIndex == nNumPresets)
|
||||
{
|
||||
return "--";
|
||||
else if(nIndexSave >=0 && nIndexSave <nNumPresets)
|
||||
}
|
||||
else if(nIndexSave >=0 && nIndexSave < nNumPresets)
|
||||
{
|
||||
snprintf(buf, sizeof(buf)-1, "Save '%s'", g_MicroProfilePresetNames[nIndexSave]);
|
||||
return buf;
|
||||
@@ -2120,13 +2121,13 @@ inline const char* MicroProfileUIMenuPreset(int nIndex, bool* bSelected)
|
||||
|
||||
inline const char* MicroProfileUIMenuCustom(int nIndex, bool* bSelected)
|
||||
{
|
||||
if((uint32_t)-1 == UI.nCustomActive)
|
||||
if(UINT32_MAX == UI.nCustomActive)
|
||||
{
|
||||
*bSelected = nIndex == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bSelected = nIndex-2 == UI.nCustomActive;
|
||||
*bSelected = nIndex-2 == static_cast<int>(UI.nCustomActive);
|
||||
}
|
||||
switch(nIndex)
|
||||
{
|
||||
@@ -2202,7 +2203,7 @@ inline void MicroProfileUIClickGroups(int nIndex)
|
||||
else
|
||||
{
|
||||
MP_ASSERT(Item.nIndex < S.nGroupCount);
|
||||
S.nActiveGroupWanted ^= (1ll << Item.nIndex);
|
||||
S.nActiveGroupWanted ^= (1ULL << Item.nIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2273,7 +2274,7 @@ inline void MicroProfileUIClickOptions(int nIndex)
|
||||
|
||||
inline void MicroProfileUIClickPreset(int nIndex)
|
||||
{
|
||||
int nNumPresets = sizeof(g_MicroProfilePresetNames) / sizeof(g_MicroProfilePresetNames[0]);
|
||||
int nNumPresets = static_cast<int>(g_MicroProfilePresetNames.size());
|
||||
int nIndexSave = nIndex - nNumPresets - 1;
|
||||
if(nIndexSave >= 0 && nIndexSave < nNumPresets)
|
||||
{
|
||||
@@ -2310,7 +2311,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
|
||||
uint32_t nX = 0;
|
||||
uint32_t nY = 0;
|
||||
bool bMouseOver = UI.nMouseY < MICROPROFILE_TEXT_HEIGHT + 1;
|
||||
|
||||
#define SBUF_SIZE 256
|
||||
char buffer[256];
|
||||
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + (MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff000000|g_nMicroProfileBackColors[1]);
|
||||
@@ -2321,7 +2322,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
uint32_t nNumMenuItems = 0;
|
||||
|
||||
int nLen = snprintf(buffer, 127, "MicroProfile");
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, buffer, nLen);
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen);
|
||||
nX += (sizeof("MicroProfile")+2) * (MICROPROFILE_TEXT_WIDTH+1);
|
||||
pMenuText[nNumMenuItems++] = "Mode";
|
||||
pMenuText[nNumMenuItems++] = "Groups";
|
||||
@@ -2409,7 +2410,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
};
|
||||
|
||||
|
||||
uint32_t nSelectMenu = (uint32_t)-1;
|
||||
uint32_t nSelectMenu = UINT32_MAX;
|
||||
for(uint32_t i = 0; i < nNumMenuItems; ++i)
|
||||
{
|
||||
nMenuX[i] = nX;
|
||||
@@ -2419,17 +2420,17 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
{
|
||||
MicroProfileDrawBox(nX-1, nY, nX + nLen * (MICROPROFILE_TEXT_WIDTH+1), nY +(MICROPROFILE_TEXT_HEIGHT+1)+1, 0xff888888);
|
||||
nSelectMenu = i;
|
||||
if((UI.nMouseLeft || UI.nMouseRight) && i == (int)nPauseIndex)
|
||||
if((UI.nMouseLeft || UI.nMouseRight) && i == (uint32_t)nPauseIndex)
|
||||
{
|
||||
S.nToggleRunning = 1;
|
||||
}
|
||||
}
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, pMenuText[i], (uint32_t)strlen(pMenuText[i]));
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, pMenuText[i], (uint32_t)strlen(pMenuText[i]));
|
||||
nX += (nLen+1) * (MICROPROFILE_TEXT_WIDTH+1);
|
||||
}
|
||||
uint32_t nMenu = nSelectMenu != (uint32_t)-1 ? nSelectMenu : UI.nActiveMenu;
|
||||
uint32_t nMenu = nSelectMenu != UINT32_MAX ? nSelectMenu : UI.nActiveMenu;
|
||||
UI.nActiveMenu = nMenu;
|
||||
if((uint32_t)-1 != nMenu)
|
||||
if(UINT32_MAX != nMenu)
|
||||
{
|
||||
nX = nMenuX[nMenu];
|
||||
nY += MICROPROFILE_TEXT_HEIGHT+1;
|
||||
@@ -2450,9 +2451,9 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
{
|
||||
UI.nActiveMenu = nMenu;
|
||||
}
|
||||
else if(nSelectMenu == (uint32_t)-1)
|
||||
else if(nSelectMenu == UINT32_MAX)
|
||||
{
|
||||
UI.nActiveMenu = (uint32_t)-1;
|
||||
UI.nActiveMenu = UINT32_MAX;
|
||||
}
|
||||
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + nHeight, 0xff000000|g_nMicroProfileBackColors[1]);
|
||||
for(int i = 0; i < nNumLines; ++i)
|
||||
@@ -2461,7 +2462,6 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
const char* pString = CB(i, &bSelected);
|
||||
if(UI.nMouseY >= nY && UI.nMouseY < nY + MICROPROFILE_TEXT_HEIGHT + 1)
|
||||
{
|
||||
bMouseOver = true;
|
||||
if(UI.nMouseLeft || UI.nMouseRight)
|
||||
{
|
||||
CBClick[nMenu](i);
|
||||
@@ -2469,7 +2469,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
MicroProfileDrawBox(nX, nY, nX + nWidth, nY + MICROPROFILE_TEXT_HEIGHT + 1, 0xff888888);
|
||||
}
|
||||
int nLen = snprintf(buffer, SBUF_SIZE-1, "%c %s", bSelected ? '*' : ' ' ,pString);
|
||||
MicroProfileDrawText(nX, nY, (uint32_t)-1, buffer, nLen);
|
||||
MicroProfileDrawText(nX, nY, UINT32_MAX, buffer, nLen);
|
||||
nY += MICROPROFILE_TEXT_HEIGHT+1;
|
||||
}
|
||||
}
|
||||
@@ -2484,7 +2484,7 @@ inline void MicroProfileDrawMenu(uint32_t nWidth, uint32_t nHeight)
|
||||
float fMaxMs = fToMs * S.nFlipMaxDisplay;
|
||||
int nLen = snprintf(FrameTimeMessage, sizeof(FrameTimeMessage)-1, "Time[%6.2f] Avg[%6.2f] Max[%6.2f]", fMs, fAverageMs, fMaxMs);
|
||||
pMenuText[nNumMenuItems++] = &FrameTimeMessage[0];
|
||||
MicroProfileDrawText(nWidth - nLen * (MICROPROFILE_TEXT_WIDTH+1), 0, -1, FrameTimeMessage, nLen);
|
||||
MicroProfileDrawText(nWidth - nLen * (MICROPROFILE_TEXT_WIDTH+1), 0, UINT32_MAX, FrameTimeMessage, nLen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2538,7 +2538,7 @@ inline void MicroProfileMoveGraph()
|
||||
|
||||
inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
{
|
||||
if((uint32_t)-1 != UI.nCustomActive)
|
||||
if(UINT32_MAX != UI.nCustomActive)
|
||||
{
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
MP_ASSERT(UI.nCustomActive < MICROPROFILE_CUSTOM_MAX);
|
||||
@@ -2571,8 +2571,8 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
pColors[i] = S.TimerInfo[nTimerIndex].nColor;
|
||||
}
|
||||
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 3*MICROPROFILE_TEXT_WIDTH, nOffsetY, (uint32_t)-1, "Avg", sizeof("Avg")-1);
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 13*MICROPROFILE_TEXT_WIDTH, nOffsetY, (uint32_t)-1, "Max", sizeof("Max")-1);
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 3*MICROPROFILE_TEXT_WIDTH, nOffsetY, UINT32_MAX, "Avg", sizeof("Avg")-1);
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING + 13*MICROPROFILE_TEXT_WIDTH, nOffsetY, UINT32_MAX, "Max", sizeof("Max")-1);
|
||||
for(uint32_t i = 0; i < nCount; ++i)
|
||||
{
|
||||
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
|
||||
@@ -2582,10 +2582,10 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
int nSize;
|
||||
uint32_t nOffsetX = MICROPROFILE_CUSTOM_PADDING;
|
||||
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeAvg[i]);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, (uint32_t)-1, Buffer, nSize);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, UINT32_MAX, Buffer, nSize);
|
||||
nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1);
|
||||
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2f", pTimeMax[i]);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, (uint32_t)-1, Buffer, nSize);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, UINT32_MAX, Buffer, nSize);
|
||||
nOffsetX += (nSize+2) * (MICROPROFILE_TEXT_WIDTH+1);
|
||||
nSize = snprintf(Buffer, sizeof(Buffer)-1, "%s:%s", S.GroupInfo[nGroupIndex].pName, pTimerInfo->pName);
|
||||
MicroProfileDrawText(nOffsetX, nOffsetY, pTimerInfo->nColor, Buffer, nSize);
|
||||
@@ -2599,9 +2599,9 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
nOffsetY = nOffsetYBase;
|
||||
float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? pTimeMax : pTimeAvg;
|
||||
const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? "Max" : "Avg";
|
||||
MicroProfileDrawText(nMaxOffsetX, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString)));
|
||||
MicroProfileDrawText(nMaxOffsetX, nOffsetY, UINT32_MAX, pString, static_cast<uint32_t>(strlen(pString)));
|
||||
int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference);
|
||||
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize);
|
||||
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, UINT32_MAX, Buffer, nSize);
|
||||
for(uint32_t i = 0; i < nCount; ++i)
|
||||
{
|
||||
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
|
||||
@@ -2613,9 +2613,9 @@ inline void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)
|
||||
{
|
||||
nOffsetY += 2*(1+MICROPROFILE_TEXT_HEIGHT);
|
||||
const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? "Max" : "Avg";
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString)));
|
||||
MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, UINT32_MAX, pString, static_cast<uint32_t>(strlen(pString)));
|
||||
int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference);
|
||||
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize);
|
||||
MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, UINT32_MAX, Buffer, nSize);
|
||||
nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT);
|
||||
float fPosX = MICROPROFILE_CUSTOM_PADDING;
|
||||
float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? pTimeMax : pTimeAvg;
|
||||
@@ -2668,7 +2668,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
UI.nHoverTime = 0;
|
||||
UI.nHoverFrame = -1;
|
||||
if(S.nDisplay != MP_DRAW_DETAILED)
|
||||
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = -1;
|
||||
S.nContextSwitchHoverThread = S.nContextSwitchHoverThreadAfter = S.nContextSwitchHoverThreadBefore = UINT32_MAX;
|
||||
MicroProfileMoveGraph();
|
||||
|
||||
|
||||
@@ -2798,13 +2798,13 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
|
||||
|
||||
|
||||
if(UI.nActiveMenu == -1 && !bMouseOverGraph)
|
||||
if(UI.nActiveMenu == UINT32_MAX && !bMouseOverGraph)
|
||||
{
|
||||
if(UI.nHoverToken != MICROPROFILE_INVALID_TOKEN)
|
||||
{
|
||||
MicroProfileDrawFloatTooltip(UI.nMouseX, UI.nMouseY, UI.nHoverToken, UI.nHoverTime);
|
||||
}
|
||||
else if(S.nContextSwitchHoverThreadAfter != -1 && S.nContextSwitchHoverThreadBefore != -1)
|
||||
else if(S.nContextSwitchHoverThreadAfter != UINT32_MAX && S.nContextSwitchHoverThreadBefore != UINT32_MAX)
|
||||
{
|
||||
float fToMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
|
||||
MicroProfileStringArray ToolTip;
|
||||
@@ -2820,7 +2820,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
MicroProfileStringArrayFormat(&ToolTip, "%6.2fms", fToMs * nDifference );
|
||||
MicroProfileStringArrayAddLiteral(&ToolTip, "CPU");
|
||||
MicroProfileStringArrayFormat(&ToolTip, "%d", S.nContextSwitchHoverCpu);
|
||||
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, -1);
|
||||
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, UINT32_MAX);
|
||||
|
||||
|
||||
}
|
||||
@@ -2858,7 +2858,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, -1);
|
||||
MicroProfileDrawFloatWindow(UI.nMouseX, UI.nMouseY+20, &ToolTip.ppStrings[0], ToolTip.nNumStrings, UINT32_MAX);
|
||||
}
|
||||
if(UI.nMouseLeft)
|
||||
{
|
||||
@@ -2883,7 +2883,7 @@ inline void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
|
||||
#endif
|
||||
m.unlock();
|
||||
}
|
||||
else if(UI.nCustomActive != (uint32_t)-1)
|
||||
else if(UI.nCustomActive != UINT32_MAX)
|
||||
{
|
||||
std::recursive_mutex& m = MicroProfileGetMutex();
|
||||
m.lock();
|
||||
@@ -3179,7 +3179,7 @@ void MicroProfileLoadPreset(const char* pSuffix)
|
||||
{
|
||||
if(0 == MP_STRCASECMP(pGroupName, S.GroupInfo[j].pName))
|
||||
{
|
||||
S.nActiveGroupWanted |= (1ll << j);
|
||||
S.nActiveGroupWanted |= (1ULL << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3212,7 +3212,7 @@ void MicroProfileLoadPreset(const char* pSuffix)
|
||||
uint64_t nGroupIndex = S.TimerInfo[j].nGroupIndex;
|
||||
if(0 == MP_STRCASECMP(pGraphName, S.TimerInfo[j].pName) && 0 == MP_STRCASECMP(pGraphGroupName, S.GroupInfo[nGroupIndex].pName))
|
||||
{
|
||||
MicroProfileToken nToken = MicroProfileMakeToken(1ll << nGroupIndex, (uint16_t)j);
|
||||
MicroProfileToken nToken = MicroProfileMakeToken(1ULL << nGroupIndex, (uint16_t)j);
|
||||
S.Graph[i].nToken = nToken; // note: group index is stored here but is checked without in MicroProfileToggleGraph()!
|
||||
S.TimerInfo[j].bGraph = true;
|
||||
if(nToken != nPrevToken)
|
||||
@@ -3235,7 +3235,7 @@ inline uint32_t MicroProfileCustomGroupFind(const char* pCustomName)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return (uint32_t)-1;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
inline uint32_t MicroProfileCustomGroup(const char* pCustomName)
|
||||
@@ -3251,7 +3251,7 @@ inline uint32_t MicroProfileCustomGroup(const char* pCustomName)
|
||||
uint32_t nIndex = UI.nCustomCount;
|
||||
UI.nCustomCount++;
|
||||
memset(&UI.Custom[nIndex], 0, sizeof(UI.Custom[nIndex]));
|
||||
uint32_t nLen = (uint32_t)strlen(pCustomName);
|
||||
size_t nLen = strlen(pCustomName);
|
||||
if(nLen > MICROPROFILE_NAME_MAX_LEN-1)
|
||||
nLen = MICROPROFILE_NAME_MAX_LEN-1;
|
||||
memcpy(&UI.Custom[nIndex].pName[0], pCustomName, nLen);
|
||||
@@ -3309,7 +3309,7 @@ inline void MicroProfileCustomGroupEnable(uint32_t nIndex)
|
||||
void MicroProfileCustomGroupToggle(const char* pCustomName)
|
||||
{
|
||||
uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName);
|
||||
if(nIndex == (uint32_t)-1 || nIndex == UI.nCustomActive)
|
||||
if(nIndex == UINT32_MAX || nIndex == UI.nCustomActive)
|
||||
{
|
||||
MicroProfileCustomGroupDisable();
|
||||
}
|
||||
@@ -3328,13 +3328,13 @@ void MicroProfileCustomGroupDisable()
|
||||
{
|
||||
MicroProfile& S = *MicroProfileGet();
|
||||
S.nForceGroupUI = 0;
|
||||
UI.nCustomActive = (uint32_t)-1;
|
||||
UI.nCustomActive = UINT32_MAX;
|
||||
}
|
||||
|
||||
void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup, const char* pTimer)
|
||||
{
|
||||
uint32_t nIndex = MicroProfileCustomGroupFind(pCustomName);
|
||||
if((uint32_t)-1 == nIndex)
|
||||
if(UINT32_MAX == nIndex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -3344,7 +3344,7 @@ void MicroProfileCustomGroupAddTimer(const char* pCustomName, const char* pGroup
|
||||
MP_ASSERT(nToken != MICROPROFILE_INVALID_TOKEN); //Timer must be registered first.
|
||||
UI.Custom[nIndex].pTimers[nTimerIndex] = nToken;
|
||||
uint16_t nGroup = MicroProfileGetGroupIndex(nToken);
|
||||
UI.Custom[nIndex].nGroupMask |= (1ll << nGroup);
|
||||
UI.Custom[nIndex].nGroupMask |= (1ULL << nGroup);
|
||||
UI.Custom[nIndex].nNumTimers++;
|
||||
}
|
||||
|
||||
|
||||
2
externals/xbyak
vendored
2
externals/xbyak
vendored
Submodule externals/xbyak updated: 82b70e6659...18c9caaa0a
@@ -10,7 +10,7 @@
|
||||
#include "common/swap.h"
|
||||
#include "common/vector_math.h"
|
||||
|
||||
namespace Color {
|
||||
namespace Common::Color {
|
||||
|
||||
/// Convert a 1-bit color component to 8 bit
|
||||
[[nodiscard]] constexpr u8 Convert1To8(u8 value) {
|
||||
@@ -268,4 +268,4 @@ inline void EncodeX24S8(u8 stencil, u8* bytes) {
|
||||
bytes[3] = stencil;
|
||||
}
|
||||
|
||||
} // namespace Color
|
||||
} // namespace Common::Color
|
||||
|
||||
@@ -143,7 +143,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable&
|
||||
config.wall_clock_cntpct = uses_wall_clock;
|
||||
|
||||
// Safe optimizations
|
||||
if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) {
|
||||
if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) {
|
||||
if (!Settings::values.cpuopt_page_tables) {
|
||||
config.page_table = nullptr;
|
||||
}
|
||||
@@ -170,6 +170,17 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable&
|
||||
}
|
||||
}
|
||||
|
||||
// Unsafe optimizations
|
||||
if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) {
|
||||
config.unsafe_optimizations = true;
|
||||
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||
}
|
||||
if (Settings::values.cpuopt_unsafe_reduce_fp_error) {
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<Dynarmic::A32::Jit>(config);
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
|
||||
config.wall_clock_cntpct = uses_wall_clock;
|
||||
|
||||
// Safe optimizations
|
||||
if (Settings::values.cpu_accuracy != Settings::CPUAccuracy::Accurate) {
|
||||
if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) {
|
||||
if (!Settings::values.cpuopt_page_tables) {
|
||||
config.page_table = nullptr;
|
||||
}
|
||||
@@ -222,6 +222,17 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
|
||||
}
|
||||
}
|
||||
|
||||
// Unsafe optimizations
|
||||
if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) {
|
||||
config.unsafe_optimizations = true;
|
||||
if (Settings::values.cpuopt_unsafe_unfuse_fma) {
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
|
||||
}
|
||||
if (Settings::values.cpuopt_unsafe_reduce_fp_error) {
|
||||
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<Dynarmic::A64::Jit>(config);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hardware_properties.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
|
||||
constexpr u64 MAX_SLICE_LENGTH = 4000;
|
||||
constexpr s64 MAX_SLICE_LENGTH = 4000;
|
||||
|
||||
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
|
||||
return std::make_shared<EventType>(std::move(callback), std::move(name));
|
||||
@@ -37,10 +37,8 @@ struct CoreTiming::Event {
|
||||
}
|
||||
};
|
||||
|
||||
CoreTiming::CoreTiming() {
|
||||
clock =
|
||||
Common::CreateBestMatchingClock(Core::Hardware::BASE_CLOCK_RATE, Core::Hardware::CNTFREQ);
|
||||
}
|
||||
CoreTiming::CoreTiming()
|
||||
: clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
|
||||
|
||||
CoreTiming::~CoreTiming() = default;
|
||||
|
||||
@@ -136,7 +134,7 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
|
||||
|
||||
void CoreTiming::AddTicks(u64 ticks) {
|
||||
this->ticks += ticks;
|
||||
downcount -= ticks;
|
||||
downcount -= static_cast<s64>(ticks);
|
||||
}
|
||||
|
||||
void CoreTiming::Idle() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <limits>
|
||||
#include "common/logging/log.h"
|
||||
#include "common/uint128.h"
|
||||
#include "core/hardware_properties.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <chrono>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hardware_properties.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@ void CpuManager::Shutdown() {
|
||||
running_mode = false;
|
||||
Pause(false);
|
||||
if (is_multicore) {
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
core_data[core].host_thread->join();
|
||||
core_data[core].host_thread.reset();
|
||||
for (auto& data : core_data) {
|
||||
data.host_thread->join();
|
||||
data.host_thread.reset();
|
||||
}
|
||||
} else {
|
||||
core_data[0].host_thread->join();
|
||||
@@ -166,25 +166,23 @@ void CpuManager::MultiCorePause(bool paused) {
|
||||
bool all_not_barrier = false;
|
||||
while (!all_not_barrier) {
|
||||
all_not_barrier = true;
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
all_not_barrier &=
|
||||
!core_data[core].is_running.load() && core_data[core].initialized.load();
|
||||
for (const auto& data : core_data) {
|
||||
all_not_barrier &= !data.is_running.load() && data.initialized.load();
|
||||
}
|
||||
}
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
core_data[core].enter_barrier->Set();
|
||||
for (auto& data : core_data) {
|
||||
data.enter_barrier->Set();
|
||||
}
|
||||
if (paused_state.load()) {
|
||||
bool all_barrier = false;
|
||||
while (!all_barrier) {
|
||||
all_barrier = true;
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
all_barrier &=
|
||||
core_data[core].is_paused.load() && core_data[core].initialized.load();
|
||||
for (const auto& data : core_data) {
|
||||
all_barrier &= data.is_paused.load() && data.initialized.load();
|
||||
}
|
||||
}
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
core_data[core].exit_barrier->Set();
|
||||
for (auto& data : core_data) {
|
||||
data.exit_barrier->Set();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -192,9 +190,8 @@ void CpuManager::MultiCorePause(bool paused) {
|
||||
bool all_barrier = false;
|
||||
while (!all_barrier) {
|
||||
all_barrier = true;
|
||||
for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
all_barrier &=
|
||||
core_data[core].is_paused.load() && core_data[core].initialized.load();
|
||||
for (const auto& data : core_data) {
|
||||
all_barrier &= data.is_paused.load() && data.initialized.load();
|
||||
}
|
||||
}
|
||||
/// Don't release the barrier
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core::Crypto {
|
||||
namespace {
|
||||
|
||||
constexpr u64 CURRENT_CRYPTO_REVISION = 0x5;
|
||||
constexpr u64 FULL_TICKET_SIZE = 0x400;
|
||||
@@ -49,7 +50,72 @@ constexpr std::array eticket_source_hashes{
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{
|
||||
constexpr std::array<std::pair<std::string_view, KeyIndex<S128KeyType>>, 30> s128_file_id{{
|
||||
{"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}},
|
||||
{"eticket_rsa_kek_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKek), 0}},
|
||||
{"eticket_rsa_kekek_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKekek), 0}},
|
||||
{"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Mask0), 0}},
|
||||
{"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Seed3), 0}},
|
||||
{"rsa_oaep_kek_generation_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::RSAOaepKekGeneration), 0}},
|
||||
{"sd_card_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek), 0}},
|
||||
{"aes_kek_generation_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration), 0}},
|
||||
{"aes_key_generation_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration), 0}},
|
||||
{"package2_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Package2), 0}},
|
||||
{"master_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Master), 0}},
|
||||
{"header_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::HeaderKek), 0}},
|
||||
{"key_area_key_application_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
|
||||
static_cast<u64>(KeyAreaKeyType::Application)}},
|
||||
{"key_area_key_ocean_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
|
||||
static_cast<u64>(KeyAreaKeyType::Ocean)}},
|
||||
{"key_area_key_system_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
|
||||
static_cast<u64>(KeyAreaKeyType::System)}},
|
||||
{"titlekek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Titlekek), 0}},
|
||||
{"keyblob_mac_key_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC), 0}},
|
||||
{"tsec_key", {S128KeyType::TSEC, 0, 0}},
|
||||
{"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}},
|
||||
{"sd_seed", {S128KeyType::SDSeed, 0, 0}},
|
||||
{"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Crypto)}},
|
||||
{"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Tweak)}},
|
||||
{"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Crypto)}},
|
||||
{"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Tweak)}},
|
||||
{"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Crypto)}},
|
||||
{"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Tweak)}},
|
||||
{"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Crypto)}},
|
||||
{"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Tweak)}},
|
||||
{"header_kek", {S128KeyType::HeaderKek, 0, 0}},
|
||||
{"sd_card_kek", {S128KeyType::SDKek, 0, 0}},
|
||||
}};
|
||||
|
||||
auto Find128ByName(std::string_view name) {
|
||||
return std::find_if(s128_file_id.begin(), s128_file_id.end(),
|
||||
[&name](const auto& pair) { return pair.first == name; });
|
||||
}
|
||||
|
||||
constexpr std::array<std::pair<std::string_view, KeyIndex<S256KeyType>>, 6> s256_file_id{{
|
||||
{"header_key", {S256KeyType::Header, 0, 0}},
|
||||
{"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save), 0}},
|
||||
{"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA), 0}},
|
||||
{"header_key_source", {S256KeyType::HeaderSource, 0, 0}},
|
||||
{"sd_card_save_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::Save), 0}},
|
||||
{"sd_card_nca_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::NCA), 0}},
|
||||
}};
|
||||
|
||||
auto Find256ByName(std::string_view name) {
|
||||
return std::find_if(s256_file_id.begin(), s256_file_id.end(),
|
||||
[&name](const auto& pair) { return pair.first == name; });
|
||||
}
|
||||
|
||||
using KeyArray = std::array<std::pair<std::pair<S128KeyType, u64>, std::string_view>, 7>;
|
||||
constexpr KeyArray KEYS_VARIABLE_LENGTH{{
|
||||
{{S128KeyType::Master, 0}, "master_key_"},
|
||||
{{S128KeyType::Package1, 0}, "package1_key_"},
|
||||
{{S128KeyType::Package2, 0}, "package2_key_"},
|
||||
@@ -57,14 +123,13 @@ const std::map<std::pair<S128KeyType, u64>, std::string> KEYS_VARIABLE_LENGTH{
|
||||
{{S128KeyType::Source, static_cast<u64>(SourceKeyType::Keyblob)}, "keyblob_key_source_"},
|
||||
{{S128KeyType::Keyblob, 0}, "keyblob_key_"},
|
||||
{{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"},
|
||||
};
|
||||
}};
|
||||
|
||||
namespace {
|
||||
template <std::size_t Size>
|
||||
bool IsAllZeroArray(const std::array<u8, Size>& array) {
|
||||
return std::all_of(array.begin(), array.end(), [](const auto& elem) { return elem == 0; });
|
||||
}
|
||||
} // namespace
|
||||
} // Anonymous namespace
|
||||
|
||||
u64 GetSignatureTypeDataSize(SignatureType type) {
|
||||
switch (type) {
|
||||
@@ -564,13 +629,13 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
|
||||
s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key;
|
||||
} else {
|
||||
out[0] = Common::ToLower(out[0]);
|
||||
if (s128_file_id.find(out[0]) != s128_file_id.end()) {
|
||||
const auto index = s128_file_id.at(out[0]);
|
||||
Key128 key = Common::HexStringToArray<16>(out[1]);
|
||||
if (const auto iter128 = Find128ByName(out[0]); iter128 != s128_file_id.end()) {
|
||||
const auto& index = iter128->second;
|
||||
const Key128 key = Common::HexStringToArray<16>(out[1]);
|
||||
s128_keys[{index.type, index.field1, index.field2}] = key;
|
||||
} else if (s256_file_id.find(out[0]) != s256_file_id.end()) {
|
||||
const auto index = s256_file_id.at(out[0]);
|
||||
Key256 key = Common::HexStringToArray<32>(out[1]);
|
||||
} else if (const auto iter256 = Find256ByName(out[0]); iter256 != s256_file_id.end()) {
|
||||
const auto& index = iter256->second;
|
||||
const Key256 key = Common::HexStringToArray<32>(out[1]);
|
||||
s256_keys[{index.type, index.field1, index.field2}] = key;
|
||||
} else if (out[0].compare(0, 8, "keyblob_") == 0 &&
|
||||
out[0].compare(0, 9, "keyblob_k") != 0) {
|
||||
@@ -742,8 +807,7 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
|
||||
}
|
||||
|
||||
const auto iter2 = std::find_if(
|
||||
s128_file_id.begin(), s128_file_id.end(),
|
||||
[&id, &field1, &field2](const std::pair<std::string, KeyIndex<S128KeyType>> elem) {
|
||||
s128_file_id.begin(), s128_file_id.end(), [&id, &field1, &field2](const auto& elem) {
|
||||
return std::tie(elem.second.type, elem.second.field1, elem.second.field2) ==
|
||||
std::tie(id, field1, field2);
|
||||
});
|
||||
@@ -753,9 +817,11 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
|
||||
|
||||
// Variable cases
|
||||
if (id == S128KeyType::KeyArea) {
|
||||
static constexpr std::array<const char*, 3> kak_names = {"key_area_key_application_{:02X}",
|
||||
"key_area_key_ocean_{:02X}",
|
||||
"key_area_key_system_{:02X}"};
|
||||
static constexpr std::array<const char*, 3> kak_names = {
|
||||
"key_area_key_application_{:02X}",
|
||||
"key_area_key_ocean_{:02X}",
|
||||
"key_area_key_system_{:02X}",
|
||||
};
|
||||
WriteKeyToFile(category, fmt::format(kak_names.at(field2), field1), key);
|
||||
} else if (id == S128KeyType::Master) {
|
||||
WriteKeyToFile(category, fmt::format("master_key_{:02X}", field1), key);
|
||||
@@ -781,8 +847,7 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) {
|
||||
return;
|
||||
}
|
||||
const auto iter = std::find_if(
|
||||
s256_file_id.begin(), s256_file_id.end(),
|
||||
[&id, &field1, &field2](const std::pair<std::string, KeyIndex<S256KeyType>> elem) {
|
||||
s256_file_id.begin(), s256_file_id.end(), [&id, &field1, &field2](const auto& elem) {
|
||||
return std::tie(elem.second.type, elem.second.field1, elem.second.field2) ==
|
||||
std::tie(id, field1, field2);
|
||||
});
|
||||
@@ -1245,58 +1310,4 @@ bool KeyManager::AddTicketPersonalized(Ticket raw) {
|
||||
SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> KeyManager::s128_file_id = {
|
||||
{"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}},
|
||||
{"eticket_rsa_kek_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKek), 0}},
|
||||
{"eticket_rsa_kekek_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::ETicketKekek), 0}},
|
||||
{"rsa_kek_mask_0", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Mask0), 0}},
|
||||
{"rsa_kek_seed_3", {S128KeyType::RSAKek, static_cast<u64>(RSAKekType::Seed3), 0}},
|
||||
{"rsa_oaep_kek_generation_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::RSAOaepKekGeneration), 0}},
|
||||
{"sd_card_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::SDKek), 0}},
|
||||
{"aes_kek_generation_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration), 0}},
|
||||
{"aes_key_generation_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKeyGeneration), 0}},
|
||||
{"package2_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Package2), 0}},
|
||||
{"master_key_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Master), 0}},
|
||||
{"header_kek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::HeaderKek), 0}},
|
||||
{"key_area_key_application_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
|
||||
static_cast<u64>(KeyAreaKeyType::Application)}},
|
||||
{"key_area_key_ocean_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
|
||||
static_cast<u64>(KeyAreaKeyType::Ocean)}},
|
||||
{"key_area_key_system_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyAreaKey),
|
||||
static_cast<u64>(KeyAreaKeyType::System)}},
|
||||
{"titlekek_source", {S128KeyType::Source, static_cast<u64>(SourceKeyType::Titlekek), 0}},
|
||||
{"keyblob_mac_key_source",
|
||||
{S128KeyType::Source, static_cast<u64>(SourceKeyType::KeyblobMAC), 0}},
|
||||
{"tsec_key", {S128KeyType::TSEC, 0, 0}},
|
||||
{"secure_boot_key", {S128KeyType::SecureBoot, 0, 0}},
|
||||
{"sd_seed", {S128KeyType::SDSeed, 0, 0}},
|
||||
{"bis_key_0_crypt", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Crypto)}},
|
||||
{"bis_key_0_tweak", {S128KeyType::BIS, 0, static_cast<u64>(BISKeyType::Tweak)}},
|
||||
{"bis_key_1_crypt", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Crypto)}},
|
||||
{"bis_key_1_tweak", {S128KeyType::BIS, 1, static_cast<u64>(BISKeyType::Tweak)}},
|
||||
{"bis_key_2_crypt", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Crypto)}},
|
||||
{"bis_key_2_tweak", {S128KeyType::BIS, 2, static_cast<u64>(BISKeyType::Tweak)}},
|
||||
{"bis_key_3_crypt", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Crypto)}},
|
||||
{"bis_key_3_tweak", {S128KeyType::BIS, 3, static_cast<u64>(BISKeyType::Tweak)}},
|
||||
{"header_kek", {S128KeyType::HeaderKek, 0, 0}},
|
||||
{"sd_card_kek", {S128KeyType::SDKek, 0, 0}},
|
||||
};
|
||||
|
||||
const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> KeyManager::s256_file_id = {
|
||||
{"header_key", {S256KeyType::Header, 0, 0}},
|
||||
{"sd_card_save_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::Save), 0}},
|
||||
{"sd_card_nca_key_source", {S256KeyType::SDKeySource, static_cast<u64>(SDKeyType::NCA), 0}},
|
||||
{"header_key_source", {S256KeyType::HeaderSource, 0, 0}},
|
||||
{"sd_card_save_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::Save), 0}},
|
||||
{"sd_card_nca_key", {S256KeyType::SDKey, static_cast<u64>(SDKeyType::NCA), 0}},
|
||||
};
|
||||
} // namespace Core::Crypto
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <string>
|
||||
|
||||
#include <variant>
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
@@ -293,9 +292,6 @@ private:
|
||||
|
||||
void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
|
||||
void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
|
||||
|
||||
static const boost::container::flat_map<std::string, KeyIndex<S128KeyType>> s128_file_id;
|
||||
static const boost::container::flat_map<std::string, KeyIndex<S256KeyType>> s256_file_id;
|
||||
};
|
||||
|
||||
Key128 GenerateKeyEncryptionKey(Key128 source, Key128 master, Key128 kek_seed, Key128 key_seed);
|
||||
|
||||
@@ -257,8 +257,7 @@ std::vector<NcaID> PlaceholderCache::List() const {
|
||||
for (const auto& sdir : dir->GetSubdirectories()) {
|
||||
for (const auto& file : sdir->GetFiles()) {
|
||||
const auto name = file->GetName();
|
||||
if (name.length() == 36 && name[32] == '.' && name[33] == 'n' && name[34] == 'c' &&
|
||||
name[35] == 'a') {
|
||||
if (name.length() == 36 && name.ends_with(".nca")) {
|
||||
out.push_back(Common::HexStringToArray<0x10>(name.substr(0, 32)));
|
||||
}
|
||||
}
|
||||
@@ -621,25 +620,25 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
|
||||
|
||||
InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
|
||||
bool overwrite_if_exists, const VfsCopyFunction& copy) {
|
||||
CNMTHeader header{
|
||||
nca.GetTitleId(), // Title ID
|
||||
0, // Ignore/Default title version
|
||||
type, // Type
|
||||
{}, // Padding
|
||||
0x10, // Default table offset
|
||||
1, // 1 Content Entry
|
||||
0, // No Meta Entries
|
||||
{}, // Padding
|
||||
{}, // Reserved 1
|
||||
0, // Is committed
|
||||
0, // Required download system version
|
||||
{}, // Reserved 2
|
||||
const CNMTHeader header{
|
||||
.title_id = nca.GetTitleId(),
|
||||
.title_version = 0,
|
||||
.type = type,
|
||||
.reserved = {},
|
||||
.table_offset = 0x10,
|
||||
.number_content_entries = 1,
|
||||
.number_meta_entries = 0,
|
||||
.attributes = 0,
|
||||
.reserved2 = {},
|
||||
.is_committed = 0,
|
||||
.required_download_system_version = 0,
|
||||
.reserved3 = {},
|
||||
};
|
||||
OptionalHeader opt_header{0, 0};
|
||||
const OptionalHeader opt_header{0, 0};
|
||||
ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
|
||||
const auto& data = nca.GetBaseFile()->ReadBytes(0x100000);
|
||||
mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0);
|
||||
memcpy(&c_rec.nca_id, &c_rec.hash, 16);
|
||||
std::memcpy(&c_rec.nca_id, &c_rec.hash, 16);
|
||||
const CNMT new_cnmt(header, opt_header, {c_rec}, {});
|
||||
if (!RawInstallYuzuMeta(new_cnmt)) {
|
||||
return InstallResult::ErrorMetaFailed;
|
||||
|
||||
@@ -72,8 +72,10 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
|
||||
|
||||
VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
|
||||
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
||||
if (cache.find(path) != cache.end()) {
|
||||
auto weak = cache[path];
|
||||
|
||||
if (const auto weak_iter = cache.find(path); weak_iter != cache.cend()) {
|
||||
const auto& weak = weak_iter->second;
|
||||
|
||||
if (!weak.expired()) {
|
||||
return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms));
|
||||
}
|
||||
@@ -84,7 +86,7 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
|
||||
}
|
||||
|
||||
auto backing = std::make_shared<FS::IOFile>(path, ModeFlagsToString(perms).c_str());
|
||||
cache[path] = backing;
|
||||
cache.insert_or_assign(path, backing);
|
||||
|
||||
// Cannot use make_shared as RealVfsFile constructor is private
|
||||
return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms));
|
||||
@@ -116,11 +118,12 @@ VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_
|
||||
VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) {
|
||||
const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault);
|
||||
const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault);
|
||||
const auto cached_file_iter = cache.find(old_path);
|
||||
|
||||
if (cache.find(old_path) != cache.end()) {
|
||||
auto file = cache[old_path].lock();
|
||||
if (cached_file_iter != cache.cend()) {
|
||||
auto file = cached_file_iter->second.lock();
|
||||
|
||||
if (!cache[old_path].expired()) {
|
||||
if (!cached_file_iter->second.expired()) {
|
||||
file->Close();
|
||||
}
|
||||
|
||||
@@ -131,7 +134,7 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_
|
||||
|
||||
cache.erase(old_path);
|
||||
file->Open(new_path, "r+b");
|
||||
cache[new_path] = file;
|
||||
cache.insert_or_assign(new_path, std::move(file));
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
@@ -142,12 +145,15 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_
|
||||
|
||||
bool RealVfsFilesystem::DeleteFile(std::string_view path_) {
|
||||
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
||||
if (cache.find(path) != cache.end()) {
|
||||
if (!cache[path].expired()) {
|
||||
cache[path].lock()->Close();
|
||||
const auto cached_iter = cache.find(path);
|
||||
|
||||
if (cached_iter != cache.cend()) {
|
||||
if (!cached_iter->second.expired()) {
|
||||
cached_iter->second.lock()->Close();
|
||||
}
|
||||
cache.erase(path);
|
||||
}
|
||||
|
||||
return FS::Delete(path);
|
||||
}
|
||||
|
||||
@@ -192,21 +198,25 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
|
||||
}
|
||||
|
||||
for (auto& kv : cache) {
|
||||
// Path in cache starts with old_path
|
||||
if (kv.first.rfind(old_path, 0) == 0) {
|
||||
const auto file_old_path =
|
||||
FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault);
|
||||
const auto file_new_path =
|
||||
FS::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()),
|
||||
FS::DirectorySeparator::PlatformDefault);
|
||||
auto cached = cache[file_old_path];
|
||||
if (!cached.expired()) {
|
||||
auto file = cached.lock();
|
||||
file->Open(file_new_path, "r+b");
|
||||
cache.erase(file_old_path);
|
||||
cache[file_new_path] = file;
|
||||
}
|
||||
// If the path in the cache doesn't start with old_path, then bail on this file.
|
||||
if (kv.first.rfind(old_path, 0) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto file_old_path =
|
||||
FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault);
|
||||
auto file_new_path = FS::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()),
|
||||
FS::DirectorySeparator::PlatformDefault);
|
||||
const auto& cached = cache[file_old_path];
|
||||
|
||||
if (cached.expired()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto file = cached.lock();
|
||||
file->Open(file_new_path, "r+b");
|
||||
cache.erase(file_old_path);
|
||||
cache.insert_or_assign(std::move(file_new_path), std::move(file));
|
||||
}
|
||||
|
||||
return OpenDirectory(new_path, Mode::ReadWrite);
|
||||
@@ -214,15 +224,21 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
|
||||
|
||||
bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) {
|
||||
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
||||
|
||||
for (auto& kv : cache) {
|
||||
// Path in cache starts with old_path
|
||||
if (kv.first.rfind(path, 0) == 0) {
|
||||
if (!cache[kv.first].expired()) {
|
||||
cache[kv.first].lock()->Close();
|
||||
}
|
||||
cache.erase(kv.first);
|
||||
// If the path in the cache doesn't start with path, then bail on this file.
|
||||
if (kv.first.rfind(path, 0) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& entry = cache[kv.first];
|
||||
if (!entry.expired()) {
|
||||
entry.lock()->Close();
|
||||
}
|
||||
|
||||
cache.erase(kv.first);
|
||||
}
|
||||
|
||||
return FS::DeleteDirRecursively(path);
|
||||
}
|
||||
|
||||
@@ -260,14 +276,14 @@ bool RealVfsFile::IsReadable() const {
|
||||
}
|
||||
|
||||
std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const {
|
||||
if (!backing->Seek(offset, SEEK_SET)) {
|
||||
if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) {
|
||||
return 0;
|
||||
}
|
||||
return backing->ReadBytes(data, length);
|
||||
}
|
||||
|
||||
std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) {
|
||||
if (!backing->Seek(offset, SEEK_SET)) {
|
||||
if (!backing->Seek(static_cast<s64>(offset), SEEK_SET)) {
|
||||
return 0;
|
||||
}
|
||||
return backing->WriteBytes(data, length);
|
||||
|
||||
@@ -359,7 +359,8 @@ enum class GPUAccuracy : u32 {
|
||||
|
||||
enum class CPUAccuracy {
|
||||
Accurate = 0,
|
||||
DebugMode = 1,
|
||||
Unsafe = 1,
|
||||
DebugMode = 2,
|
||||
};
|
||||
|
||||
extern bool configuring_global;
|
||||
@@ -419,6 +420,9 @@ struct Values {
|
||||
bool cpuopt_misc_ir;
|
||||
bool cpuopt_reduce_misalign_checks;
|
||||
|
||||
bool cpuopt_unsafe_unfuse_fma;
|
||||
bool cpuopt_unsafe_reduce_fp_error;
|
||||
|
||||
// Renderer
|
||||
Setting<RendererBackend> renderer_backend;
|
||||
bool renderer_debug;
|
||||
|
||||
@@ -38,7 +38,8 @@ public:
|
||||
explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_,
|
||||
GCAdapter::Adapter* adapter)
|
||||
: port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
|
||||
gcadapter(adapter), origin_value(adapter->GetOriginValue(port_, axis_)) {}
|
||||
gcadapter(adapter),
|
||||
origin_value(static_cast<float>(adapter->GetOriginValue(port_, axis_))) {}
|
||||
|
||||
bool GetStatus() const override {
|
||||
if (gcadapter->DeviceConnected(port)) {
|
||||
@@ -151,8 +152,9 @@ public:
|
||||
GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, GCAdapter::Adapter* adapter,
|
||||
float range_)
|
||||
: port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter),
|
||||
origin_value_x(adapter->GetOriginValue(port_, axis_x_)),
|
||||
origin_value_y(adapter->GetOriginValue(port_, axis_y_)), range(range_) {}
|
||||
origin_value_x(static_cast<float>(adapter->GetOriginValue(port_, axis_x_))),
|
||||
origin_value_y(static_cast<float>(adapter->GetOriginValue(port_, axis_y_))),
|
||||
range(range_) {}
|
||||
|
||||
float GetAxis(int axis) const {
|
||||
if (gcadapter->DeviceConnected(port)) {
|
||||
|
||||
@@ -10,7 +10,13 @@
|
||||
|
||||
namespace Tegra::Engines {
|
||||
|
||||
Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer) : rasterizer{rasterizer} {}
|
||||
Fermi2D::Fermi2D() = default;
|
||||
|
||||
Fermi2D::~Fermi2D() = default;
|
||||
|
||||
void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
||||
ASSERT_MSG(method < Regs::NUM_REGS,
|
||||
@@ -87,7 +93,7 @@ void Fermi2D::HandleSurfaceCopy() {
|
||||
copy_config.src_rect = src_rect;
|
||||
copy_config.dst_rect = dst_rect;
|
||||
|
||||
if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
|
||||
if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,11 @@ namespace Tegra::Engines {
|
||||
|
||||
class Fermi2D final : public EngineInterface {
|
||||
public:
|
||||
explicit Fermi2D(VideoCore::RasterizerInterface& rasterizer);
|
||||
~Fermi2D() = default;
|
||||
explicit Fermi2D();
|
||||
~Fermi2D();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
/// Write the value to the register identified by method.
|
||||
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
|
||||
@@ -149,7 +152,7 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
VideoCore::RasterizerInterface* rasterizer;
|
||||
|
||||
/// Performs the copy from the source surface to the destination surface as configured in the
|
||||
/// registers.
|
||||
|
||||
@@ -16,14 +16,15 @@
|
||||
|
||||
namespace Tegra::Engines {
|
||||
|
||||
KeplerCompute::KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager)
|
||||
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{
|
||||
memory_manager,
|
||||
regs.upload} {}
|
||||
KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_)
|
||||
: system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {}
|
||||
|
||||
KeplerCompute::~KeplerCompute() = default;
|
||||
|
||||
void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
||||
ASSERT_MSG(method < Regs::NUM_REGS,
|
||||
"Invalid KeplerCompute register, increase the size of the Regs structure");
|
||||
@@ -104,11 +105,11 @@ SamplerDescriptor KeplerCompute::AccessSampler(u32 handle) const {
|
||||
}
|
||||
|
||||
VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
void KeplerCompute::ProcessLaunch() {
|
||||
@@ -119,7 +120,7 @@ void KeplerCompute::ProcessLaunch() {
|
||||
const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start;
|
||||
LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr);
|
||||
|
||||
rasterizer.DispatchCompute(code_addr);
|
||||
rasterizer->DispatchCompute(code_addr);
|
||||
}
|
||||
|
||||
Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
|
||||
|
||||
@@ -42,10 +42,12 @@ namespace Tegra::Engines {
|
||||
|
||||
class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface {
|
||||
public:
|
||||
explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager);
|
||||
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
|
||||
~KeplerCompute();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
static constexpr std::size_t NumConstBuffers = 8;
|
||||
|
||||
struct Regs {
|
||||
@@ -230,11 +232,6 @@ public:
|
||||
const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override;
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
MemoryManager& memory_manager;
|
||||
Upload::State upload_state;
|
||||
|
||||
void ProcessLaunch();
|
||||
|
||||
/// Retrieves information about a specific TIC entry from the TIC buffer.
|
||||
@@ -242,6 +239,11 @@ private:
|
||||
|
||||
/// Retrieves information about a specific TSC entry from the TSC buffer.
|
||||
Texture::TSCEntry GetTSCEntry(u32 tsc_index) const;
|
||||
|
||||
Core::System& system;
|
||||
MemoryManager& memory_manager;
|
||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||
Upload::State upload_state;
|
||||
};
|
||||
|
||||
#define ASSERT_REG_POSITION(field_name, position) \
|
||||
|
||||
@@ -22,14 +22,19 @@ using VideoCore::QueryType;
|
||||
/// First register id that is actually a Macro call.
|
||||
constexpr u32 MacroRegistersStart = 0xE00;
|
||||
|
||||
Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager)
|
||||
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager},
|
||||
macro_engine{GetMacroEngine(*this)}, upload_state{memory_manager, regs.upload} {
|
||||
Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
|
||||
: system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)},
|
||||
upload_state{memory_manager, regs.upload} {
|
||||
dirty.flags.flip();
|
||||
InitializeRegisterDefaults();
|
||||
}
|
||||
|
||||
Maxwell3D::~Maxwell3D() = default;
|
||||
|
||||
void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
void Maxwell3D::InitializeRegisterDefaults() {
|
||||
// Initializes registers to their default values - what games expect them to be at boot. This is
|
||||
// for certain registers that may not be explicitly set by games.
|
||||
@@ -192,7 +197,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
||||
|
||||
switch (method) {
|
||||
case MAXWELL3D_REG_INDEX(wait_for_idle): {
|
||||
rasterizer.WaitForIdle();
|
||||
rasterizer->WaitForIdle();
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(shadow_ram_control): {
|
||||
@@ -402,7 +407,7 @@ void Maxwell3D::FlushMMEInlineDraw() {
|
||||
|
||||
const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed;
|
||||
if (ShouldExecute()) {
|
||||
rasterizer.Draw(is_indexed, true);
|
||||
rasterizer->Draw(is_indexed, true);
|
||||
}
|
||||
|
||||
// TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
|
||||
@@ -465,7 +470,7 @@ void Maxwell3D::ProcessQueryGet() {
|
||||
switch (regs.query.query_get.operation) {
|
||||
case Regs::QueryOperation::Release:
|
||||
if (regs.query.query_get.fence == 1) {
|
||||
rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
|
||||
rasterizer->SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
|
||||
} else {
|
||||
StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0);
|
||||
}
|
||||
@@ -533,7 +538,7 @@ void Maxwell3D::ProcessQueryCondition() {
|
||||
void Maxwell3D::ProcessCounterReset() {
|
||||
switch (regs.counter_reset) {
|
||||
case Regs::CounterReset::SampleCnt:
|
||||
rasterizer.ResetCounter(QueryType::SamplesPassed);
|
||||
rasterizer->ResetCounter(QueryType::SamplesPassed);
|
||||
break;
|
||||
default:
|
||||
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}",
|
||||
@@ -547,7 +552,7 @@ void Maxwell3D::ProcessSyncPoint() {
|
||||
const u32 increment = regs.sync_info.increment.Value();
|
||||
[[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
|
||||
if (increment) {
|
||||
rasterizer.SignalSyncPoint(sync_point);
|
||||
rasterizer->SignalSyncPoint(sync_point);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,7 +575,7 @@ void Maxwell3D::DrawArrays() {
|
||||
|
||||
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
|
||||
if (ShouldExecute()) {
|
||||
rasterizer.Draw(is_indexed, false);
|
||||
rasterizer->Draw(is_indexed, false);
|
||||
}
|
||||
|
||||
// TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
|
||||
@@ -590,8 +595,8 @@ std::optional<u64> Maxwell3D::GetQueryResult() {
|
||||
return 0;
|
||||
case Regs::QuerySelect::SamplesPassed:
|
||||
// Deferred.
|
||||
rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
|
||||
system.GPU().GetTicks());
|
||||
rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
|
||||
system.GPU().GetTicks());
|
||||
return {};
|
||||
default:
|
||||
LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
|
||||
@@ -718,7 +723,7 @@ void Maxwell3D::ProcessClearBuffers() {
|
||||
regs.clear_buffers.R == regs.clear_buffers.B &&
|
||||
regs.clear_buffers.R == regs.clear_buffers.A);
|
||||
|
||||
rasterizer.Clear();
|
||||
rasterizer->Clear();
|
||||
}
|
||||
|
||||
u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const {
|
||||
@@ -752,11 +757,11 @@ SamplerDescriptor Maxwell3D::AccessSampler(u32 handle) const {
|
||||
}
|
||||
|
||||
VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
} // namespace Tegra::Engines
|
||||
|
||||
@@ -51,9 +51,11 @@ namespace Tegra::Engines {
|
||||
|
||||
class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface {
|
||||
public:
|
||||
explicit Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager);
|
||||
~Maxwell3D() = default;
|
||||
explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager);
|
||||
~Maxwell3D();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
/// Register structure of the Maxwell3D engine.
|
||||
/// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
|
||||
@@ -1418,12 +1420,12 @@ public:
|
||||
return execute_on;
|
||||
}
|
||||
|
||||
VideoCore::RasterizerInterface& GetRasterizer() {
|
||||
return rasterizer;
|
||||
VideoCore::RasterizerInterface& Rasterizer() {
|
||||
return *rasterizer;
|
||||
}
|
||||
|
||||
const VideoCore::RasterizerInterface& GetRasterizer() const {
|
||||
return rasterizer;
|
||||
const VideoCore::RasterizerInterface& Rasterizer() const {
|
||||
return *rasterizer;
|
||||
}
|
||||
|
||||
/// Notify a memory write has happened.
|
||||
@@ -1460,11 +1462,10 @@ private:
|
||||
void InitializeRegisterDefaults();
|
||||
|
||||
Core::System& system;
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
|
||||
MemoryManager& memory_manager;
|
||||
|
||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||
|
||||
/// Start offsets of each macro in macro_memory
|
||||
std::array<u32, 0x80> macro_positions = {};
|
||||
|
||||
|
||||
@@ -5,15 +5,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/core.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/settings.h"
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/memory_manager.h"
|
||||
#include "video_core/rasterizer_interface.h"
|
||||
|
||||
@@ -27,21 +27,28 @@ namespace Tegra {
|
||||
|
||||
MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
|
||||
|
||||
GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async)
|
||||
: system{system}, renderer{std::move(renderer_)}, is_async{is_async} {
|
||||
auto& rasterizer{renderer->Rasterizer()};
|
||||
memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer);
|
||||
dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this);
|
||||
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager);
|
||||
fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer);
|
||||
kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager);
|
||||
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager);
|
||||
kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
|
||||
shader_notify = std::make_unique<VideoCore::ShaderNotify>();
|
||||
}
|
||||
GPU::GPU(Core::System& system_, bool is_async_)
|
||||
: system{system_}, dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)},
|
||||
memory_manager{std::make_unique<Tegra::MemoryManager>(system)},
|
||||
maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)},
|
||||
fermi_2d{std::make_unique<Engines::Fermi2D>()},
|
||||
kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)},
|
||||
maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)},
|
||||
kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)},
|
||||
shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {}
|
||||
|
||||
GPU::~GPU() = default;
|
||||
|
||||
void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
|
||||
renderer = std::move(renderer_);
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer();
|
||||
memory_manager->BindRasterizer(rasterizer);
|
||||
maxwell_3d->BindRasterizer(rasterizer);
|
||||
fermi_2d->BindRasterizer(rasterizer);
|
||||
kepler_compute->BindRasterizer(rasterizer);
|
||||
}
|
||||
|
||||
Engines::Maxwell3D& GPU::Maxwell3D() {
|
||||
return *maxwell_3d;
|
||||
}
|
||||
|
||||
@@ -142,11 +142,6 @@ class MemoryManager;
|
||||
|
||||
class GPU {
|
||||
public:
|
||||
explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
bool is_async);
|
||||
|
||||
virtual ~GPU();
|
||||
|
||||
struct MethodCall {
|
||||
u32 method{};
|
||||
u32 argument{};
|
||||
@@ -162,6 +157,12 @@ public:
|
||||
method_count(method_count) {}
|
||||
};
|
||||
|
||||
explicit GPU(Core::System& system, bool is_async);
|
||||
virtual ~GPU();
|
||||
|
||||
/// Binds a renderer to the GPU.
|
||||
void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer);
|
||||
|
||||
/// Calls a GPU method.
|
||||
void CallMethod(const MethodCall& method_call);
|
||||
|
||||
@@ -345,8 +346,8 @@ private:
|
||||
bool ExecuteMethodOnEngine(u32 method);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||
Core::System& system;
|
||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||
|
||||
private:
|
||||
|
||||
@@ -10,16 +10,14 @@
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer_), true), gpu_thread{system},
|
||||
cpu_context(renderer->GetRenderWindow().CreateSharedContext()),
|
||||
gpu_context(std::move(context)) {}
|
||||
GPUAsynch::GPUAsynch(Core::System& system) : GPU{system, true}, gpu_thread{system} {}
|
||||
|
||||
GPUAsynch::~GPUAsynch() = default;
|
||||
|
||||
void GPUAsynch::Start() {
|
||||
gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher);
|
||||
gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher);
|
||||
cpu_context = renderer->GetRenderWindow().CreateSharedContext();
|
||||
cpu_context->MakeCurrent();
|
||||
}
|
||||
|
||||
void GPUAsynch::ObtainContext() {
|
||||
|
||||
@@ -20,8 +20,7 @@ namespace VideoCommon {
|
||||
/// Implementation of GPU interface that runs the GPU asynchronously
|
||||
class GPUAsynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
explicit GPUAsynch(Core::System& system);
|
||||
~GPUAsynch() override;
|
||||
|
||||
void Start() override;
|
||||
@@ -42,7 +41,6 @@ protected:
|
||||
private:
|
||||
GPUThread::ThreadManager gpu_thread;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -7,20 +7,18 @@
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer), false), context{std::move(context)} {}
|
||||
GPUSynch::GPUSynch(Core::System& system) : GPU{system, false} {}
|
||||
|
||||
GPUSynch::~GPUSynch() = default;
|
||||
|
||||
void GPUSynch::Start() {}
|
||||
|
||||
void GPUSynch::ObtainContext() {
|
||||
context->MakeCurrent();
|
||||
renderer->Context().MakeCurrent();
|
||||
}
|
||||
|
||||
void GPUSynch::ReleaseContext() {
|
||||
context->DoneCurrent();
|
||||
renderer->Context().DoneCurrent();
|
||||
}
|
||||
|
||||
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
|
||||
@@ -19,8 +19,7 @@ namespace VideoCommon {
|
||||
/// Implementation of GPU interface that runs the GPU synchronously
|
||||
class GPUSynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
explicit GPUSynch(Core::System& system);
|
||||
~GPUSynch() override;
|
||||
|
||||
void Start() override;
|
||||
@@ -36,9 +35,6 @@ public:
|
||||
protected:
|
||||
void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id,
|
||||
[[maybe_unused]] u32 value) const override {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -24,7 +24,7 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||
maxwell3d.regs.index_array.first = parameters[4];
|
||||
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(true, true);
|
||||
maxwell3d.Rasterizer().Draw(true, true);
|
||||
}
|
||||
maxwell3d.regs.index_array.count = 0;
|
||||
maxwell3d.mme_draw.instance_count = 0;
|
||||
@@ -42,7 +42,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||
maxwell3d.mme_draw.instance_count = count;
|
||||
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(false, true);
|
||||
maxwell3d.Rasterizer().Draw(false, true);
|
||||
}
|
||||
maxwell3d.regs.vertex_buffer.count = 0;
|
||||
maxwell3d.mme_draw.instance_count = 0;
|
||||
@@ -65,7 +65,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
||||
maxwell3d.regs.draw.topology.Assign(
|
||||
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(true, true);
|
||||
maxwell3d.Rasterizer().Draw(true, true);
|
||||
}
|
||||
maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
|
||||
maxwell3d.regs.index_array.count = 0;
|
||||
|
||||
@@ -34,7 +34,6 @@ void MacroInterpreterImpl::Execute(const std::vector<u32>& parameters, u32 metho
|
||||
this->parameters = std::make_unique<u32[]>(num_parameters);
|
||||
}
|
||||
std::memcpy(this->parameters.get(), parameters.data(), num_parameters * sizeof(u32));
|
||||
this->num_parameters = num_parameters;
|
||||
|
||||
// Execute the code until we hit an exit condition.
|
||||
bool keep_executing = true;
|
||||
|
||||
@@ -14,11 +14,15 @@
|
||||
|
||||
namespace Tegra {
|
||||
|
||||
MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
|
||||
: system{system}, rasterizer{rasterizer}, page_table(page_table_size) {}
|
||||
MemoryManager::MemoryManager(Core::System& system_)
|
||||
: system{system_}, page_table(page_table_size) {}
|
||||
|
||||
MemoryManager::~MemoryManager() = default;
|
||||
|
||||
void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) {
|
||||
u64 remaining_size{size};
|
||||
for (u64 offset{}; offset < size; offset += page_size) {
|
||||
@@ -217,7 +221,7 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz
|
||||
|
||||
// Flush must happen on the rasterizer interface, such that memory is always synchronous
|
||||
// when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu.
|
||||
rasterizer.FlushRegion(src_addr, copy_amount);
|
||||
rasterizer->FlushRegion(src_addr, copy_amount);
|
||||
system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
|
||||
}
|
||||
|
||||
@@ -266,7 +270,7 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s
|
||||
|
||||
// Invalidate must happen on the rasterizer interface, such that memory is always
|
||||
// synchronous when it is written (even when in asynchronous GPU mode).
|
||||
rasterizer.InvalidateRegion(dest_addr, copy_amount);
|
||||
rasterizer->InvalidateRegion(dest_addr, copy_amount);
|
||||
system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
|
||||
}
|
||||
|
||||
@@ -312,10 +316,10 @@ void MemoryManager::CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_add
|
||||
WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size);
|
||||
}
|
||||
|
||||
bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) {
|
||||
bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const {
|
||||
const auto cpu_addr{GpuToCpuAddress(gpu_addr)};
|
||||
if (!cpu_addr) {
|
||||
return {};
|
||||
return false;
|
||||
}
|
||||
const std::size_t page{(*cpu_addr & Core::Memory::PAGE_MASK) + size};
|
||||
return page <= Core::Memory::PAGE_SIZE;
|
||||
|
||||
@@ -68,9 +68,12 @@ static_assert(sizeof(PageEntry) == 4, "PageEntry is too large");
|
||||
|
||||
class MemoryManager final {
|
||||
public:
|
||||
explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer);
|
||||
explicit MemoryManager(Core::System& system);
|
||||
~MemoryManager();
|
||||
|
||||
/// Binds a renderer to the memory manager.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
|
||||
|
||||
template <typename T>
|
||||
@@ -109,7 +112,7 @@ public:
|
||||
/**
|
||||
* IsGranularRange checks if a gpu region can be simply read with a pointer.
|
||||
*/
|
||||
bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size);
|
||||
bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const;
|
||||
|
||||
GPUVAddr Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size);
|
||||
GPUVAddr MapAllocate(VAddr cpu_addr, std::size_t size, std::size_t align);
|
||||
@@ -141,7 +144,7 @@ private:
|
||||
|
||||
Core::System& system;
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||
|
||||
std::vector<PageEntry> page_table;
|
||||
};
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
RendererBase::RendererBase(Core::Frontend::EmuWindow& window) : render_window{window} {
|
||||
RendererBase::RendererBase(Core::Frontend::EmuWindow& window_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
||||
: render_window{window_}, context{std::move(context_)} {
|
||||
RefreshBaseSettings();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
namespace Core::Frontend {
|
||||
class EmuWindow;
|
||||
}
|
||||
class GraphicsContext;
|
||||
} // namespace Core::Frontend
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
@@ -25,14 +26,15 @@ struct RendererSettings {
|
||||
|
||||
// Screenshot
|
||||
std::atomic<bool> screenshot_requested{false};
|
||||
void* screenshot_bits;
|
||||
void* screenshot_bits{};
|
||||
std::function<void()> screenshot_complete_callback;
|
||||
Layout::FramebufferLayout screenshot_framebuffer_layout;
|
||||
};
|
||||
|
||||
class RendererBase : NonCopyable {
|
||||
public:
|
||||
explicit RendererBase(Core::Frontend::EmuWindow& window);
|
||||
explicit RendererBase(Core::Frontend::EmuWindow& window,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||
virtual ~RendererBase();
|
||||
|
||||
/// Initialize the renderer
|
||||
@@ -68,6 +70,14 @@ public:
|
||||
return *rasterizer;
|
||||
}
|
||||
|
||||
Core::Frontend::GraphicsContext& Context() {
|
||||
return *context;
|
||||
}
|
||||
|
||||
const Core::Frontend::GraphicsContext& Context() const {
|
||||
return *context;
|
||||
}
|
||||
|
||||
Core::Frontend::EmuWindow& GetRenderWindow() {
|
||||
return render_window;
|
||||
}
|
||||
@@ -94,6 +104,7 @@ public:
|
||||
protected:
|
||||
Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
|
||||
std::unique_ptr<RasterizerInterface> rasterizer;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context;
|
||||
f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
|
||||
int m_current_frame = 0; ///< Current frame, should be set by the renderer
|
||||
|
||||
|
||||
@@ -4,16 +4,17 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include "video_core/renderer_opengl/gl_buffer_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_fence_manager.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed)
|
||||
: VideoCommon::FenceBase(payload, is_stubbed), sync_object{} {}
|
||||
GLInnerFence::GLInnerFence(u32 payload, bool is_stubbed) : FenceBase(payload, is_stubbed) {}
|
||||
|
||||
GLInnerFence::GLInnerFence(GPUVAddr address, u32 payload, bool is_stubbed)
|
||||
: VideoCommon::FenceBase(address, payload, is_stubbed), sync_object{} {}
|
||||
: FenceBase(address, payload, is_stubbed) {}
|
||||
|
||||
GLInnerFence::~GLInnerFence() = default;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/fence_manager.h"
|
||||
|
||||
@@ -214,20 +214,20 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran
|
||||
// Skip games without title id
|
||||
const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0;
|
||||
if (!Settings::values.use_disk_shader_cache.GetValue() || !has_title_id) {
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Common::FS::IOFile file(GetTransferablePath(), "rb");
|
||||
if (!file.IsOpen()) {
|
||||
LOG_INFO(Render_OpenGL, "No transferable shader cache found");
|
||||
is_usable = true;
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
u32 version{};
|
||||
if (file.ReadBytes(&version, sizeof(version)) != sizeof(version)) {
|
||||
LOG_ERROR(Render_OpenGL, "Failed to get transferable cache version, skipping it");
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (version < NativeVersion) {
|
||||
@@ -235,12 +235,12 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran
|
||||
file.Close();
|
||||
InvalidateTransferable();
|
||||
is_usable = true;
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
if (version > NativeVersion) {
|
||||
LOG_WARNING(Render_OpenGL, "Transferable shader cache was generated with a newer version "
|
||||
"of the emulator, skipping");
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Version is valid, load the shaders
|
||||
@@ -249,7 +249,7 @@ std::optional<std::vector<ShaderDiskCacheEntry>> ShaderDiskCacheOpenGL::LoadTran
|
||||
ShaderDiskCacheEntry& entry = entries.emplace_back();
|
||||
if (!entry.Load(file)) {
|
||||
LOG_ERROR(Render_OpenGL, "Failed to load transferable raw entry, skipping");
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,12 +290,12 @@ std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::Lo
|
||||
ShaderCacheVersionHash file_hash{};
|
||||
if (!LoadArrayFromPrecompiled(file_hash.data(), file_hash.size())) {
|
||||
precompiled_cache_virtual_file_offset = 0;
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
if (GetShaderCacheVersionHash() != file_hash) {
|
||||
LOG_INFO(Render_OpenGL, "Precompiled cache is from another version of the emulator");
|
||||
precompiled_cache_virtual_file_offset = 0;
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<ShaderDiskCachePrecompiled> entries;
|
||||
@@ -305,15 +305,16 @@ std::optional<std::vector<ShaderDiskCachePrecompiled>> ShaderDiskCacheOpenGL::Lo
|
||||
if (!LoadObjectFromPrecompiled(entry.unique_identifier) ||
|
||||
!LoadObjectFromPrecompiled(entry.binary_format) ||
|
||||
!LoadObjectFromPrecompiled(binary_size)) {
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
entry.binary.resize(binary_size);
|
||||
if (!LoadArrayFromPrecompiled(entry.binary.data(), entry.binary.size())) {
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
|
||||
return std::move(entries);
|
||||
}
|
||||
|
||||
void ShaderDiskCacheOpenGL::InvalidateTransferable() {
|
||||
|
||||
@@ -403,7 +403,7 @@ void CachedSurface::DecorateSurfaceName() {
|
||||
LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr(), params.TargetName());
|
||||
}
|
||||
|
||||
void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) {
|
||||
void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, const std::string& prefix) {
|
||||
LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
Tegra::Texture::SwizzleSource z_source,
|
||||
Tegra::Texture::SwizzleSource w_source);
|
||||
|
||||
void DecorateViewName(GPUVAddr gpu_addr, std::string prefix);
|
||||
void DecorateViewName(GPUVAddr gpu_addr, const std::string& prefix);
|
||||
|
||||
void MarkAsModified(u64 tick) {
|
||||
surface.MarkAsModified(true, tick);
|
||||
|
||||
@@ -313,10 +313,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context)
|
||||
: RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context},
|
||||
program_manager{device}, has_debug_tool{HasDebugTool()} {}
|
||||
RendererOpenGL::RendererOpenGL(Core::System& system_, Core::Frontend::EmuWindow& emu_window_,
|
||||
Tegra::GPU& gpu_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
||||
: RendererBase{emu_window_, std::move(context_)}, system{system_},
|
||||
emu_window{emu_window_}, gpu{gpu_}, program_manager{device}, has_debug_tool{HasDebugTool()} {}
|
||||
|
||||
RendererOpenGL::~RendererOpenGL() = default;
|
||||
|
||||
@@ -384,7 +385,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||
if (has_debug_tool) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
Present(0);
|
||||
context.SwapBuffers();
|
||||
context->SwapBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,8 +56,9 @@ class FrameMailbox;
|
||||
|
||||
class RendererOpenGL final : public VideoCore::RendererBase {
|
||||
public:
|
||||
explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context);
|
||||
explicit RendererOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
|
||||
Tegra::GPU& gpu,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||
~RendererOpenGL() override;
|
||||
|
||||
bool Init() override;
|
||||
@@ -93,9 +94,9 @@ private:
|
||||
|
||||
bool Present(int timeout_ms);
|
||||
|
||||
Core::Frontend::EmuWindow& emu_window;
|
||||
Core::System& system;
|
||||
Core::Frontend::GraphicsContext& context;
|
||||
Core::Frontend::EmuWindow& emu_window;
|
||||
Tegra::GPU& gpu;
|
||||
const Device device;
|
||||
|
||||
StateTracker state_tracker{system};
|
||||
@@ -120,7 +121,7 @@ private:
|
||||
std::vector<u8> gl_framebuffer_data;
|
||||
|
||||
/// Used for transforming the framebuffer orientation
|
||||
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags;
|
||||
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{};
|
||||
Common::Rectangle<int> framebuffer_crop_rect;
|
||||
|
||||
/// Frame presentation mailbox
|
||||
|
||||
@@ -237,8 +237,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system)
|
||||
: RendererBase(window), system{system} {}
|
||||
RendererVulkan::RendererVulkan(Core::System& system_, Core::Frontend::EmuWindow& emu_window,
|
||||
Tegra::GPU& gpu_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context)
|
||||
: RendererBase{emu_window, std::move(context)}, system{system_}, gpu{gpu_} {}
|
||||
|
||||
RendererVulkan::~RendererVulkan() {
|
||||
ShutDown();
|
||||
|
||||
@@ -38,7 +38,9 @@ struct VKScreenInfo {
|
||||
|
||||
class RendererVulkan final : public VideoCore::RendererBase {
|
||||
public:
|
||||
explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system);
|
||||
explicit RendererVulkan(Core::System& system, Core::Frontend::EmuWindow& emu_window,
|
||||
Tegra::GPU& gpu,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||
~RendererVulkan() override;
|
||||
|
||||
bool Init() override;
|
||||
@@ -58,6 +60,7 @@ private:
|
||||
void Report() const;
|
||||
|
||||
Core::System& system;
|
||||
Tegra::GPU& gpu;
|
||||
|
||||
Common::DynamicLibrary library;
|
||||
vk::InstanceDispatch dld;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/settings.h"
|
||||
@@ -16,37 +17,46 @@
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
namespace {
|
||||
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window,
|
||||
Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context) {
|
||||
|
||||
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(
|
||||
Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context) {
|
||||
switch (Settings::values.renderer_backend.GetValue()) {
|
||||
case Settings::RendererBackend::OpenGL:
|
||||
return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context);
|
||||
return std::make_unique<OpenGL::RendererOpenGL>(system, emu_window, gpu,
|
||||
std::move(context));
|
||||
#ifdef HAS_VULKAN
|
||||
case Settings::RendererBackend::Vulkan:
|
||||
return std::make_unique<Vulkan::RendererVulkan>(emu_window, system);
|
||||
return std::make_unique<Vulkan::RendererVulkan>(system, emu_window, gpu,
|
||||
std::move(context));
|
||||
#endif
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) {
|
||||
std::unique_ptr<Tegra::GPU> gpu;
|
||||
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
|
||||
gpu = std::make_unique<VideoCommon::GPUAsynch>(system);
|
||||
} else {
|
||||
gpu = std::make_unique<VideoCommon::GPUSynch>(system);
|
||||
}
|
||||
|
||||
auto context = emu_window.CreateSharedContext();
|
||||
const auto scope = context->Acquire();
|
||||
auto renderer = CreateRenderer(emu_window, system, *context);
|
||||
|
||||
auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
|
||||
if (!renderer->Init()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
|
||||
return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer),
|
||||
std::move(context));
|
||||
}
|
||||
return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context));
|
||||
gpu->BindRenderer(std::move(renderer));
|
||||
return gpu;
|
||||
}
|
||||
|
||||
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
|
||||
|
||||
@@ -635,6 +635,11 @@ void Config::ReadCpuValues() {
|
||||
ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool();
|
||||
Settings::values.cpuopt_reduce_misalign_checks =
|
||||
ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool();
|
||||
|
||||
Settings::values.cpuopt_unsafe_unfuse_fma =
|
||||
ReadSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), true).toBool();
|
||||
Settings::values.cpuopt_unsafe_reduce_fp_error =
|
||||
ReadSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true).toBool();
|
||||
}
|
||||
|
||||
qt_config->endGroup();
|
||||
@@ -1132,6 +1137,11 @@ void Config::SaveCpuValues() {
|
||||
WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true);
|
||||
WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"),
|
||||
Settings::values.cpuopt_reduce_misalign_checks, true);
|
||||
|
||||
WriteSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"),
|
||||
Settings::values.cpuopt_unsafe_unfuse_fma, true);
|
||||
WriteSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"),
|
||||
Settings::values.cpuopt_unsafe_reduce_fp_error, true);
|
||||
}
|
||||
|
||||
qt_config->endGroup();
|
||||
|
||||
@@ -19,6 +19,8 @@ ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::Config
|
||||
|
||||
connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this,
|
||||
&ConfigureCpu::AccuracyUpdated);
|
||||
connect(ui->accuracy, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&ConfigureCpu::UpdateGroup);
|
||||
}
|
||||
|
||||
ConfigureCpu::~ConfigureCpu() = default;
|
||||
@@ -28,6 +30,12 @@ void ConfigureCpu::SetConfiguration() {
|
||||
|
||||
ui->accuracy->setEnabled(runtime_lock);
|
||||
ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy));
|
||||
UpdateGroup(static_cast<int>(Settings::values.cpu_accuracy));
|
||||
|
||||
ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock);
|
||||
ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma);
|
||||
ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock);
|
||||
ui->cpuopt_unsafe_reduce_fp_error->setChecked(Settings::values.cpuopt_unsafe_reduce_fp_error);
|
||||
}
|
||||
|
||||
void ConfigureCpu::AccuracyUpdated(int index) {
|
||||
@@ -38,14 +46,21 @@ void ConfigureCpu::AccuracyUpdated(int index) {
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (result == QMessageBox::No) {
|
||||
ui->accuracy->setCurrentIndex(static_cast<int>(Settings::CPUAccuracy::Accurate));
|
||||
return;
|
||||
UpdateGroup(static_cast<int>(Settings::CPUAccuracy::Accurate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureCpu::UpdateGroup(int index) {
|
||||
ui->unsafe_group->setVisible(static_cast<Settings::CPUAccuracy>(index) ==
|
||||
Settings::CPUAccuracy::Unsafe);
|
||||
}
|
||||
|
||||
void ConfigureCpu::ApplyConfiguration() {
|
||||
Settings::values.cpu_accuracy =
|
||||
static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex());
|
||||
Settings::values.cpuopt_unsafe_unfuse_fma = ui->cpuopt_unsafe_unfuse_fma->isChecked();
|
||||
Settings::values.cpuopt_unsafe_reduce_fp_error = ui->cpuopt_unsafe_reduce_fp_error->isChecked();
|
||||
}
|
||||
|
||||
void ConfigureCpu::changeEvent(QEvent* event) {
|
||||
|
||||
@@ -26,6 +26,7 @@ private:
|
||||
void RetranslateUI();
|
||||
|
||||
void AccuracyUpdated(int index);
|
||||
void UpdateGroup(int index);
|
||||
|
||||
void SetConfiguration();
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@
|
||||
<string>Accurate</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Unsafe</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enable Debug Mode</string>
|
||||
@@ -62,6 +67,53 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="unsafe_group">
|
||||
<property name="title">
|
||||
<string>Unsafe CPU Optimization Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel">
|
||||
<property name="wordWrap">
|
||||
<bool>1</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>These settings reduce accuracy for speed.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma">
|
||||
<property name="text">
|
||||
<string>Unfuse FMA (improve performance on CPUs without FMA)</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>
|
||||
<div>This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.</div>
|
||||
</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error">
|
||||
<property name="text">
|
||||
<string>Faster FRSQRTE and FRECPE</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>
|
||||
<div>This option improves the speed of some approximate floating-point functions by using less accurate native approximations.</div>
|
||||
</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
Reference in New Issue
Block a user