mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-04 05:51:19 +12:00
Add all the files
This commit is contained in:
parent
e3db07a16a
commit
d60742f52b
1445 changed files with 430238 additions and 0 deletions
266
src/Cafe/HW/Latte/Core/LatteThread.cpp
Normal file
266
src/Cafe/HW/Latte/Core/LatteThread.cpp
Normal file
|
@ -0,0 +1,266 @@
|
|||
#include "Cafe/HW/Latte/ISA/RegDefines.h"
|
||||
#include "Cafe/OS/libs/gx2/GX2.h" // todo - remove dependency
|
||||
#include "Cafe/HW/Latte/Core/Latte.h"
|
||||
#include "Cafe/HW/Latte/Core/LatteDraw.h"
|
||||
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
||||
#include "Cafe/HW/Latte/Core/LatteAsyncCommands.h"
|
||||
#include "Cafe/GameProfile/GameProfile.h"
|
||||
#include "gui/guiWrapper.h"
|
||||
|
||||
#include "Cafe/HW/Latte/Core/LatteBufferCache.h"
|
||||
|
||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||
#include "Cafe/HW/Latte/Core/LatteTexture.h"
|
||||
#include "util/helpers/helpers.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include "config/ActiveSettings.h"
|
||||
|
||||
#include "Cafe/CafeSystem.h"
|
||||
|
||||
LatteGPUState_t LatteGPUState = {};
|
||||
|
||||
std::atomic_bool sLatteThreadRunning = false;
|
||||
std::atomic_bool sLatteThreadFinishedInit = false;
|
||||
|
||||
void LatteThread_Exit();
|
||||
|
||||
void Latte_LoadInitialRegisters()
|
||||
{
|
||||
LatteGPUState.contextNew.CB_TARGET_MASK.set_MASK(0xFFFFFFFF);
|
||||
LatteGPUState.contextNew.VGT_MULTI_PRIM_IB_RESET_INDX.set_RESTART_INDEX(0xFFFFFFFF);
|
||||
LatteGPUState.contextRegister[Latte::REGADDR::PA_CL_CLIP_CNTL] = 0;
|
||||
*(float*)&LatteGPUState.contextRegister[mmDB_DEPTH_CLEAR] = 1.0f;
|
||||
}
|
||||
|
||||
extern bool gx2WriteGatherInited;
|
||||
|
||||
LatteTextureView* osScreenTVTex[2] = { nullptr };
|
||||
LatteTextureView* osScreenDRCTex[2] = { nullptr };
|
||||
|
||||
LatteTextureView* LatteHandleOSScreen_getOrCreateScreenTex(MPTR physAddress, uint32 width, uint32 height, uint32 pitch)
|
||||
{
|
||||
LatteTextureView* texView = LatteTextureViewLookupCache::lookup(physAddress, width, height, 1, pitch, 0, 1, 0, 1, Latte::E_GX2SURFFMT::R8_G8_B8_A8_UNORM, Latte::E_DIM::DIM_2D);
|
||||
if (texView)
|
||||
return texView;
|
||||
return LatteTexture_CreateTexture(0, Latte::E_DIM::DIM_2D, physAddress, 0, Latte::E_GX2SURFFMT::R8_G8_B8_A8_UNORM, width, height, 1, pitch, 1, 0, Latte::E_HWTILEMODE::TM_LINEAR_ALIGNED, false);
|
||||
}
|
||||
|
||||
void LatteHandleOSScreen_prepareTextures()
|
||||
{
|
||||
osScreenTVTex[0] = LatteHandleOSScreen_getOrCreateScreenTex(LatteGPUState.osScreen.screen[0].physPtr, 1280, 720, 1280);
|
||||
osScreenTVTex[1] = LatteHandleOSScreen_getOrCreateScreenTex(LatteGPUState.osScreen.screen[0].physPtr + 1280 * 720 * 4, 1280, 720, 1280);
|
||||
osScreenDRCTex[0] = LatteHandleOSScreen_getOrCreateScreenTex(LatteGPUState.osScreen.screen[1].physPtr, 854, 480, 0x380);
|
||||
osScreenDRCTex[1] = LatteHandleOSScreen_getOrCreateScreenTex(LatteGPUState.osScreen.screen[1].physPtr + 896 * 480 * 4, 854, 480, 0x380);
|
||||
}
|
||||
|
||||
void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPadView);
|
||||
|
||||
bool LatteHandleOSScreen_TV()
|
||||
{
|
||||
if (!LatteGPUState.osScreen.screen[0].isEnabled)
|
||||
return false;
|
||||
if (LatteGPUState.osScreen.screen[0].flipExecuteCount == LatteGPUState.osScreen.screen[0].flipRequestCount)
|
||||
return false;
|
||||
LatteHandleOSScreen_prepareTextures();
|
||||
|
||||
sint32 bufferDisplayTV = (LatteGPUState.osScreen.screen[0].flipRequestCount & 1) ^ 1;
|
||||
sint32 bufferDisplayDRC = (LatteGPUState.osScreen.screen[1].flipRequestCount & 1) ^ 1;
|
||||
|
||||
const uint32 bufferIndexTV = (bufferDisplayTV);
|
||||
const uint32 bufferIndexDRC = bufferDisplayDRC;
|
||||
|
||||
g_renderer->texture_bindAndActivate(osScreenTVTex[bufferIndexTV], 0);
|
||||
LatteTexture_ReloadData(osScreenTVTex[bufferIndexTV]->baseTexture, 0);
|
||||
|
||||
// TV screen
|
||||
LatteRenderTarget_copyToBackbuffer(osScreenTVTex[bufferIndexTV]->baseTexture->baseView, false);
|
||||
|
||||
if (LatteGPUState.osScreen.screen[0].flipExecuteCount != LatteGPUState.osScreen.screen[0].flipRequestCount)
|
||||
LatteGPUState.osScreen.screen[0].flipExecuteCount = LatteGPUState.osScreen.screen[0].flipRequestCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LatteHandleOSScreen_DRC()
|
||||
{
|
||||
if (!LatteGPUState.osScreen.screen[1].isEnabled)
|
||||
return false;
|
||||
if (LatteGPUState.osScreen.screen[1].flipExecuteCount == LatteGPUState.osScreen.screen[1].flipRequestCount)
|
||||
return false;
|
||||
LatteHandleOSScreen_prepareTextures();
|
||||
|
||||
sint32 bufferDisplayDRC = (LatteGPUState.osScreen.screen[1].flipRequestCount & 1) ^ 1;
|
||||
|
||||
const uint32 bufferIndexDRC = bufferDisplayDRC;
|
||||
|
||||
g_renderer->texture_bindAndActivate(osScreenDRCTex[bufferIndexDRC], 0);
|
||||
LatteTexture_ReloadData(osScreenDRCTex[bufferIndexDRC]->baseTexture, 0);
|
||||
|
||||
// GamePad screen
|
||||
LatteRenderTarget_copyToBackbuffer(osScreenDRCTex[bufferIndexDRC]->baseTexture->baseView, true);
|
||||
|
||||
if (LatteGPUState.osScreen.screen[1].flipExecuteCount != LatteGPUState.osScreen.screen[1].flipRequestCount)
|
||||
LatteGPUState.osScreen.screen[1].flipExecuteCount = LatteGPUState.osScreen.screen[1].flipRequestCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LatteThread_HandleOSScreen()
|
||||
{
|
||||
bool swapTV = LatteHandleOSScreen_TV();
|
||||
bool swapDRC = LatteHandleOSScreen_DRC();
|
||||
if(swapTV || swapDRC)
|
||||
g_renderer->SwapBuffers(swapTV, swapDRC);
|
||||
}
|
||||
|
||||
int Latte_ThreadEntry()
|
||||
{
|
||||
SetThreadName("LatteThread");
|
||||
sint32 w,h;
|
||||
gui_getWindowSize(&w,&h);
|
||||
|
||||
// imgui
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.WantSaveIniSettings = false;
|
||||
io.IniFilename = nullptr;
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
// renderer
|
||||
g_renderer->Initialize();
|
||||
RendererOutputShader::InitializeStatic();
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
|
||||
LatteTiming_Init();
|
||||
LatteTexture_init();
|
||||
LatteTC_Init();
|
||||
LatteBufferCache_init(164 * 1024 * 1024);
|
||||
LatteQuery_Init();
|
||||
LatteSHRC_Init();
|
||||
LatteStreamout_InitCache();
|
||||
|
||||
g_renderer->renderTarget_setViewport(0, 0, w, h, 0.0f, 1.0f);
|
||||
|
||||
// enable GLSL gl_PointSize support
|
||||
// glEnable(GL_PROGRAM_POINT_SIZE); // breaks shader caching on AMD (as of 2018)
|
||||
|
||||
LatteGPUState.glVendor = GLVENDOR_UNKNOWN;
|
||||
switch(g_renderer->GetVendor())
|
||||
{
|
||||
case GfxVendor::AMD:
|
||||
LatteGPUState.glVendor = GLVENDOR_AMD;
|
||||
break;
|
||||
case GfxVendor::IntelLegacy:
|
||||
LatteGPUState.glVendor = GLVENDOR_INTEL_LEGACY;
|
||||
break;
|
||||
case GfxVendor::IntelNoLegacy:
|
||||
LatteGPUState.glVendor = GLVENDOR_INTEL_NOLEGACY;
|
||||
break;
|
||||
case GfxVendor::Intel:
|
||||
LatteGPUState.glVendor = GLVENDOR_INTEL;
|
||||
break;
|
||||
case GfxVendor::Nvidia:
|
||||
LatteGPUState.glVendor = GLVENDOR_NVIDIA;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sLatteThreadFinishedInit = true;
|
||||
|
||||
// register debug handler
|
||||
if (cafeLog_isLoggingFlagEnabled(LOG_TYPE_OPENGL))
|
||||
g_renderer->EnableDebugMode();
|
||||
|
||||
// wait till a game is started
|
||||
while( true )
|
||||
{
|
||||
if( CafeSystem::IsTitleRunning() )
|
||||
break;
|
||||
|
||||
g_renderer->DrawEmptyFrame(true);
|
||||
g_renderer->DrawEmptyFrame(false);
|
||||
|
||||
gui_hasScreenshotRequest(); // keep the screenshot request queue empty
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000/60));
|
||||
}
|
||||
|
||||
g_renderer->DrawEmptyFrame(true);
|
||||
|
||||
// load/init shader cache file
|
||||
LatteShaderCache_load();
|
||||
|
||||
// init registers
|
||||
Latte_LoadInitialRegisters();
|
||||
// let CPU thread know the GPU is done initializing
|
||||
g_isGPUInitFinished = true;
|
||||
// wait until CPU has called GX2Init()
|
||||
while (LatteGPUState.gx2InitCalled == 0)
|
||||
{
|
||||
std::this_thread::yield();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
LatteThread_HandleOSScreen();
|
||||
if (!Latte_IsActive())
|
||||
LatteThread_Exit();
|
||||
}
|
||||
gxRingBufferReadPtr = gx2WriteGatherPipe.gxRingBuffer;
|
||||
LatteCP_ProcessRingbuffer();
|
||||
cemu_assert_debug(false); // should never reach
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::thread sLatteThread;
|
||||
std::mutex sLatteThreadStateMutex;
|
||||
|
||||
// initializes GPU thread which in turn also activates graphic packs
|
||||
// does not return until the thread finished initialization
|
||||
void Latte_Start()
|
||||
{
|
||||
std::unique_lock _lock(sLatteThreadStateMutex);
|
||||
cemu_assert_debug(!sLatteThreadRunning);
|
||||
sLatteThreadRunning = true;
|
||||
sLatteThreadFinishedInit = false;
|
||||
sLatteThread = std::thread(Latte_ThreadEntry);
|
||||
// wait until initialized
|
||||
while (!sLatteThreadFinishedInit)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
void Latte_Stop()
|
||||
{
|
||||
std::unique_lock _lock(sLatteThreadStateMutex);
|
||||
sLatteThreadRunning = false;
|
||||
_lock.unlock();
|
||||
sLatteThread.join();
|
||||
}
|
||||
|
||||
bool Latte_IsActive()
|
||||
{
|
||||
return sLatteThreadRunning;
|
||||
}
|
||||
|
||||
void LatteThread_Exit()
|
||||
{
|
||||
if (g_renderer)
|
||||
g_renderer->Shutdown();
|
||||
// clean up texture cache
|
||||
LatteTC_UnloadAllTextures();
|
||||
// clean up runtime shader cache
|
||||
// todo
|
||||
// destroy renderer but make sure that g_renderer remains valid until the destructor has finished
|
||||
if (g_renderer)
|
||||
{
|
||||
Renderer* renderer = g_renderer.get();
|
||||
delete renderer;
|
||||
g_renderer.release();
|
||||
}
|
||||
// reset GPU7 state
|
||||
std::memset(&LatteGPUState, 0, sizeof(LatteGPUState));
|
||||
#if BOOST_OS_WINDOWS
|
||||
ExitThread(0);
|
||||
#else
|
||||
pthread_exit(nullptr);
|
||||
#endif
|
||||
cemu_assert_unimplemented();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue