Make the NDS teardown more robust (#1798)
* Make cleanup a little more robust to mitigate undefined behavior - Add some null checks before cleaning up the GPU3D renderer - Make sure that all deleted objects are null - Move cleanup logic out of an assert call - Note that deleting a null pointer is a no-op, so there's no need to check for null beforehand - Use RAII for GLCompositor instead of Init/DeInit methods * Replace a DeInit call that I missed * Make ARMJIT_Memory less likely to generate errors - Set FastMem7/9Start to nullptr at the end - Only close and unmap the file if it's initialized * Make Renderer3D manage its resources with RAII * Don't try to deallocate frontend resources that aren't loaded * Make ARMJIT_Memory::DeInit more robust on the Switch * Reset MemoryFile on Windows to INVALID_HANDLE_VALUE, not nullptr - There is a difference * Don't explicitly store a Valid state in GLCompositor or the 3D renderers - Instead, create them with static methods while making the actual constructors private * Make initialization of OpenGL resources fail if OpenGL isn't loaded * assert that OpenGL is loaded instead of returning failure
This commit is contained in:
parent
1aaf22d181
commit
db963aa002
|
@ -330,6 +330,7 @@ void DeInit()
|
||||||
ARMJIT_Memory::DeInit();
|
ARMJIT_Memory::DeInit();
|
||||||
|
|
||||||
delete JITCompiler;
|
delete JITCompiler;
|
||||||
|
JITCompiler = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
|
|
|
@ -308,7 +308,7 @@ HANDLE MemoryFile;
|
||||||
LPVOID ExceptionHandlerHandle;
|
LPVOID ExceptionHandlerHandle;
|
||||||
#else
|
#else
|
||||||
u8* MemoryBase;
|
u8* MemoryBase;
|
||||||
int MemoryFile;
|
int MemoryFile = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
|
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
|
||||||
|
@ -811,25 +811,58 @@ void DeInit()
|
||||||
{
|
{
|
||||||
#if defined(__SWITCH__)
|
#if defined(__SWITCH__)
|
||||||
virtmemLock();
|
virtmemLock();
|
||||||
|
if (FastMem9Reservation)
|
||||||
virtmemRemoveReservation(FastMem9Reservation);
|
virtmemRemoveReservation(FastMem9Reservation);
|
||||||
|
|
||||||
|
if (FastMem7Reservation)
|
||||||
virtmemRemoveReservation(FastMem7Reservation);
|
virtmemRemoveReservation(FastMem7Reservation);
|
||||||
|
|
||||||
|
FastMem9Reservation = nullptr;
|
||||||
|
FastMem7Reservation = nullptr;
|
||||||
virtmemUnlock();
|
virtmemUnlock();
|
||||||
|
|
||||||
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
|
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
|
||||||
free(MemoryBase);
|
free(MemoryBase);
|
||||||
|
MemoryBase = nullptr;
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
assert(UnmapViewOfFile(MemoryBase));
|
if (MemoryBase)
|
||||||
CloseHandle(MemoryFile);
|
{
|
||||||
|
bool viewUnmapped = UnmapViewOfFile(MemoryBase);
|
||||||
|
assert(viewUnmapped);
|
||||||
|
MemoryBase = nullptr;
|
||||||
|
FastMem9Start = nullptr;
|
||||||
|
FastMem7Start = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MemoryFile)
|
||||||
|
{
|
||||||
|
CloseHandle(MemoryFile);
|
||||||
|
MemoryFile = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ExceptionHandlerHandle)
|
||||||
|
{
|
||||||
RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
|
RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
|
||||||
|
ExceptionHandlerHandle = nullptr;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
sigaction(SIGSEGV, &OldSaSegv, nullptr);
|
sigaction(SIGSEGV, &OldSaSegv, nullptr);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
sigaction(SIGBUS, &OldSaBus, nullptr);
|
sigaction(SIGBUS, &OldSaBus, nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
if (MemoryBase)
|
||||||
|
{
|
||||||
munmap(MemoryBase, MemoryTotalSize);
|
munmap(MemoryBase, MemoryTotalSize);
|
||||||
|
MemoryBase = nullptr;
|
||||||
|
FastMem9Start = nullptr;
|
||||||
|
FastMem7Start = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MemoryFile >= 0)
|
||||||
|
{
|
||||||
close(MemoryFile);
|
close(MemoryFile);
|
||||||
|
MemoryFile = -1;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
if (Libandroid)
|
if (Libandroid)
|
||||||
|
|
12
src/DSi.cpp
12
src/DSi.cpp
|
@ -128,6 +128,10 @@ void DeInit()
|
||||||
delete[] NWRAM_A;
|
delete[] NWRAM_A;
|
||||||
delete[] NWRAM_B;
|
delete[] NWRAM_B;
|
||||||
delete[] NWRAM_C;
|
delete[] NWRAM_C;
|
||||||
|
|
||||||
|
NWRAM_A = nullptr;
|
||||||
|
NWRAM_B = nullptr;
|
||||||
|
NWRAM_C = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DSi_I2C::DeInit();
|
DSi_I2C::DeInit();
|
||||||
|
@ -135,10 +139,16 @@ void DeInit()
|
||||||
DSi_AES::DeInit();
|
DSi_AES::DeInit();
|
||||||
DSi_DSP::DeInit();
|
DSi_DSP::DeInit();
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) delete NDMAs[i];
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
delete NDMAs[i];
|
||||||
|
NDMAs[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
delete SDMMC;
|
delete SDMMC;
|
||||||
|
SDMMC = nullptr;
|
||||||
delete SDIO;
|
delete SDIO;
|
||||||
|
SDIO = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
|
|
|
@ -63,6 +63,9 @@ void DeInit()
|
||||||
{
|
{
|
||||||
delete Camera0;
|
delete Camera0;
|
||||||
delete Camera1;
|
delete Camera1;
|
||||||
|
|
||||||
|
Camera0 = nullptr;
|
||||||
|
Camera1 = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
|
|
28
src/GPU.cpp
28
src/GPU.cpp
|
@ -171,6 +171,11 @@ void DeInit()
|
||||||
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
|
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
|
||||||
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
|
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
|
||||||
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
|
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
|
||||||
|
|
||||||
|
Framebuffer[0][0] = nullptr;
|
||||||
|
Framebuffer[0][1] = nullptr;
|
||||||
|
Framebuffer[1][0] = nullptr;
|
||||||
|
Framebuffer[1][1] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetVRAMCache()
|
void ResetVRAMCache()
|
||||||
|
@ -388,20 +393,18 @@ void InitRenderer(int renderer)
|
||||||
#ifdef OGLRENDERER_ENABLED
|
#ifdef OGLRENDERER_ENABLED
|
||||||
if (renderer == 1)
|
if (renderer == 1)
|
||||||
{
|
{
|
||||||
CurGLCompositor = std::make_unique<GLCompositor>();
|
CurGLCompositor = GLCompositor::New();
|
||||||
// Create opengl rendrerer
|
// Create opengl renderer
|
||||||
if (!CurGLCompositor->Init())
|
if (!CurGLCompositor)
|
||||||
{
|
{
|
||||||
// Fallback on software renderer
|
// Fallback on software renderer
|
||||||
renderer = 0;
|
renderer = 0;
|
||||||
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
||||||
GPU3D::CurrentRenderer->Init();
|
|
||||||
}
|
}
|
||||||
GPU3D::CurrentRenderer = std::make_unique<GPU3D::GLRenderer>();
|
GPU3D::CurrentRenderer = GPU3D::GLRenderer::New();
|
||||||
if (!GPU3D::CurrentRenderer->Init())
|
if (!GPU3D::CurrentRenderer)
|
||||||
{
|
{
|
||||||
// Fallback on software renderer
|
// Fallback on software renderer
|
||||||
CurGLCompositor->DeInit();
|
|
||||||
CurGLCompositor.reset();
|
CurGLCompositor.reset();
|
||||||
renderer = 0;
|
renderer = 0;
|
||||||
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
||||||
|
@ -411,7 +414,6 @@ void InitRenderer(int renderer)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
|
||||||
GPU3D::CurrentRenderer->Init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer = renderer;
|
Renderer = renderer;
|
||||||
|
@ -419,12 +421,12 @@ void InitRenderer(int renderer)
|
||||||
|
|
||||||
void DeInitRenderer()
|
void DeInitRenderer()
|
||||||
{
|
{
|
||||||
GPU3D::CurrentRenderer->DeInit();
|
// Delete the 3D renderer, if it exists
|
||||||
|
GPU3D::CurrentRenderer.reset();
|
||||||
|
|
||||||
#ifdef OGLRENDERER_ENABLED
|
#ifdef OGLRENDERER_ENABLED
|
||||||
if (Renderer == 1)
|
// Delete the compositor, if one exists
|
||||||
{
|
CurGLCompositor.reset();
|
||||||
CurGLCompositor->DeInit();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,14 +137,11 @@ void Write32(u32 addr, u32 val);
|
||||||
class Renderer3D
|
class Renderer3D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Renderer3D(bool Accelerated);
|
virtual ~Renderer3D() = default;
|
||||||
virtual ~Renderer3D() {};
|
|
||||||
|
|
||||||
Renderer3D(const Renderer3D&) = delete;
|
Renderer3D(const Renderer3D&) = delete;
|
||||||
Renderer3D& operator=(const Renderer3D&) = delete;
|
Renderer3D& operator=(const Renderer3D&) = delete;
|
||||||
|
|
||||||
virtual bool Init() = 0;
|
|
||||||
virtual void DeInit() = 0;
|
|
||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
|
|
||||||
// This "Accelerated" flag currently communicates if the framebuffer should
|
// This "Accelerated" flag currently communicates if the framebuffer should
|
||||||
|
@ -159,6 +156,8 @@ public:
|
||||||
virtual void RenderFrame() = 0;
|
virtual void RenderFrame() = 0;
|
||||||
virtual void RestartFrame() {};
|
virtual void RestartFrame() {};
|
||||||
virtual u32* GetLine(int line) = 0;
|
virtual u32* GetLine(int line) = 0;
|
||||||
|
protected:
|
||||||
|
Renderer3D(bool Accelerated);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int Renderer;
|
extern int Renderer;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "GPU3D_OpenGL.h"
|
#include "GPU3D_OpenGL.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "NDS.h"
|
#include "NDS.h"
|
||||||
|
@ -96,14 +97,20 @@ void SetupDefaultTexParams(GLuint tex)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLRenderer::GLRenderer()
|
GLRenderer::GLRenderer() noexcept : Renderer3D(true)
|
||||||
: Renderer3D(true)
|
|
||||||
{
|
{
|
||||||
|
// GLRenderer::New() will be used to actually initialize the renderer;
|
||||||
|
// The various glDelete* functions silently ignore invalid IDs,
|
||||||
|
// so we can just let the destructor clean up a half-initialized renderer.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLRenderer::Init()
|
std::unique_ptr<GLRenderer> GLRenderer::New() noexcept
|
||||||
{
|
{
|
||||||
GLint uni_id;
|
assert(glEnable != nullptr);
|
||||||
|
|
||||||
|
// Will be returned if the initialization succeeds,
|
||||||
|
// or cleaned up via RAII if it fails.
|
||||||
|
std::unique_ptr<GLRenderer> result = std::unique_ptr<GLRenderer>(new GLRenderer());
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_STENCIL_TEST);
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
@ -112,86 +119,93 @@ bool GLRenderer::Init()
|
||||||
glClearDepth(1.0);
|
glClearDepth(1.0);
|
||||||
|
|
||||||
|
|
||||||
if (!OpenGL::BuildShaderProgram(kClearVS, kClearFS, ClearShaderPlain, "ClearShader"))
|
if (!OpenGL::BuildShaderProgram(kClearVS, kClearFS, result->ClearShaderPlain, "ClearShader"))
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
glBindAttribLocation(ClearShaderPlain[2], 0, "vPosition");
|
glBindAttribLocation(result->ClearShaderPlain[2], 0, "vPosition");
|
||||||
glBindFragDataLocation(ClearShaderPlain[2], 0, "oColor");
|
glBindFragDataLocation(result->ClearShaderPlain[2], 0, "oColor");
|
||||||
glBindFragDataLocation(ClearShaderPlain[2], 1, "oAttr");
|
glBindFragDataLocation(result->ClearShaderPlain[2], 1, "oAttr");
|
||||||
|
|
||||||
if (!OpenGL::LinkShaderProgram(ClearShaderPlain))
|
if (!OpenGL::LinkShaderProgram(result->ClearShaderPlain))
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
ClearUniformLoc[0] = glGetUniformLocation(ClearShaderPlain[2], "uColor");
|
result->ClearUniformLoc[0] = glGetUniformLocation(result->ClearShaderPlain[2], "uColor");
|
||||||
ClearUniformLoc[1] = glGetUniformLocation(ClearShaderPlain[2], "uDepth");
|
result->ClearUniformLoc[1] = glGetUniformLocation(result->ClearShaderPlain[2], "uDepth");
|
||||||
ClearUniformLoc[2] = glGetUniformLocation(ClearShaderPlain[2], "uOpaquePolyID");
|
result->ClearUniformLoc[2] = glGetUniformLocation(result->ClearShaderPlain[2], "uOpaquePolyID");
|
||||||
ClearUniformLoc[3] = glGetUniformLocation(ClearShaderPlain[2], "uFogFlag");
|
result->ClearUniformLoc[3] = glGetUniformLocation(result->ClearShaderPlain[2], "uFogFlag");
|
||||||
|
|
||||||
memset(RenderShader, 0, sizeof(RenderShader));
|
memset(result->RenderShader, 0, sizeof(RenderShader));
|
||||||
|
|
||||||
if (!BuildRenderShader(0,
|
if (!result->BuildRenderShader(0, kRenderVS_Z, kRenderFS_ZO))
|
||||||
kRenderVS_Z, kRenderFS_ZO)) return false;
|
return nullptr;
|
||||||
if (!BuildRenderShader(RenderFlag_WBuffer,
|
|
||||||
kRenderVS_W, kRenderFS_WO)) return false;
|
|
||||||
if (!BuildRenderShader(RenderFlag_Edge,
|
|
||||||
kRenderVS_Z, kRenderFS_ZE)) return false;
|
|
||||||
if (!BuildRenderShader(RenderFlag_Edge | RenderFlag_WBuffer,
|
|
||||||
kRenderVS_W, kRenderFS_WE)) return false;
|
|
||||||
if (!BuildRenderShader(RenderFlag_Trans,
|
|
||||||
kRenderVS_Z, kRenderFS_ZT)) return false;
|
|
||||||
if (!BuildRenderShader(RenderFlag_Trans | RenderFlag_WBuffer,
|
|
||||||
kRenderVS_W, kRenderFS_WT)) return false;
|
|
||||||
if (!BuildRenderShader(RenderFlag_ShadowMask,
|
|
||||||
kRenderVS_Z, kRenderFS_ZSM)) return false;
|
|
||||||
if (!BuildRenderShader(RenderFlag_ShadowMask | RenderFlag_WBuffer,
|
|
||||||
kRenderVS_W, kRenderFS_WSM)) return false;
|
|
||||||
|
|
||||||
|
if (!result->BuildRenderShader(RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WO))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, FinalPassEdgeShader, "FinalPassEdgeShader"))
|
if (!result->BuildRenderShader(RenderFlag_Edge, kRenderVS_Z, kRenderFS_ZE))
|
||||||
return false;
|
return nullptr;
|
||||||
if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, FinalPassFogShader, "FinalPassFogShader"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
glBindAttribLocation(FinalPassEdgeShader[2], 0, "vPosition");
|
if (!result->BuildRenderShader(RenderFlag_Edge | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WE))
|
||||||
glBindFragDataLocation(FinalPassEdgeShader[2], 0, "oColor");
|
return nullptr;
|
||||||
|
|
||||||
if (!OpenGL::LinkShaderProgram(FinalPassEdgeShader))
|
if (!result->BuildRenderShader(RenderFlag_Trans, kRenderVS_Z, kRenderFS_ZT))
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
uni_id = glGetUniformBlockIndex(FinalPassEdgeShader[2], "uConfig");
|
if (!result->BuildRenderShader(RenderFlag_Trans | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WT))
|
||||||
glUniformBlockBinding(FinalPassEdgeShader[2], uni_id, 0);
|
return nullptr;
|
||||||
|
|
||||||
glUseProgram(FinalPassEdgeShader[2]);
|
if (!result->BuildRenderShader(RenderFlag_ShadowMask, kRenderVS_Z, kRenderFS_ZSM))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
uni_id = glGetUniformLocation(FinalPassEdgeShader[2], "DepthBuffer");
|
if (!result->BuildRenderShader(RenderFlag_ShadowMask | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WSM))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, result->FinalPassEdgeShader, "FinalPassEdgeShader"))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, result->FinalPassFogShader, "FinalPassFogShader"))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
glBindAttribLocation(result->FinalPassEdgeShader[2], 0, "vPosition");
|
||||||
|
glBindFragDataLocation(result->FinalPassEdgeShader[2], 0, "oColor");
|
||||||
|
|
||||||
|
if (!OpenGL::LinkShaderProgram(result->FinalPassEdgeShader))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
GLint uni_id = glGetUniformBlockIndex(result->FinalPassEdgeShader[2], "uConfig");
|
||||||
|
glUniformBlockBinding(result->FinalPassEdgeShader[2], uni_id, 0);
|
||||||
|
|
||||||
|
glUseProgram(result->FinalPassEdgeShader[2]);
|
||||||
|
|
||||||
|
uni_id = glGetUniformLocation(result->FinalPassEdgeShader[2], "DepthBuffer");
|
||||||
glUniform1i(uni_id, 0);
|
glUniform1i(uni_id, 0);
|
||||||
uni_id = glGetUniformLocation(FinalPassEdgeShader[2], "AttrBuffer");
|
uni_id = glGetUniformLocation(result->FinalPassEdgeShader[2], "AttrBuffer");
|
||||||
glUniform1i(uni_id, 1);
|
glUniform1i(uni_id, 1);
|
||||||
|
|
||||||
glBindAttribLocation(FinalPassFogShader[2], 0, "vPosition");
|
glBindAttribLocation(result->FinalPassFogShader[2], 0, "vPosition");
|
||||||
glBindFragDataLocation(FinalPassFogShader[2], 0, "oColor");
|
glBindFragDataLocation(result->FinalPassFogShader[2], 0, "oColor");
|
||||||
|
|
||||||
if (!OpenGL::LinkShaderProgram(FinalPassFogShader))
|
if (!OpenGL::LinkShaderProgram(result->FinalPassFogShader))
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
uni_id = glGetUniformBlockIndex(FinalPassFogShader[2], "uConfig");
|
uni_id = glGetUniformBlockIndex(result->FinalPassFogShader[2], "uConfig");
|
||||||
glUniformBlockBinding(FinalPassFogShader[2], uni_id, 0);
|
glUniformBlockBinding(result->FinalPassFogShader[2], uni_id, 0);
|
||||||
|
|
||||||
glUseProgram(FinalPassFogShader[2]);
|
glUseProgram(result->FinalPassFogShader[2]);
|
||||||
|
|
||||||
uni_id = glGetUniformLocation(FinalPassFogShader[2], "DepthBuffer");
|
uni_id = glGetUniformLocation(result->FinalPassFogShader[2], "DepthBuffer");
|
||||||
glUniform1i(uni_id, 0);
|
glUniform1i(uni_id, 0);
|
||||||
uni_id = glGetUniformLocation(FinalPassFogShader[2], "AttrBuffer");
|
uni_id = glGetUniformLocation(result->FinalPassFogShader[2], "AttrBuffer");
|
||||||
glUniform1i(uni_id, 1);
|
glUniform1i(uni_id, 1);
|
||||||
|
|
||||||
|
|
||||||
memset(&ShaderConfig, 0, sizeof(ShaderConfig));
|
memset(&result->ShaderConfig, 0, sizeof(ShaderConfig));
|
||||||
|
|
||||||
glGenBuffers(1, &ShaderConfigUBO);
|
glGenBuffers(1, &result->ShaderConfigUBO);
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, ShaderConfigUBO);
|
glBindBuffer(GL_UNIFORM_BUFFER, result->ShaderConfigUBO);
|
||||||
static_assert((sizeof(ShaderConfig) & 15) == 0, "");
|
static_assert((sizeof(ShaderConfig) & 15) == 0);
|
||||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(ShaderConfig), &ShaderConfig, GL_STATIC_DRAW);
|
glBufferData(GL_UNIFORM_BUFFER, sizeof(ShaderConfig), &result->ShaderConfig, GL_STATIC_DRAW);
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, ShaderConfigUBO);
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, result->ShaderConfigUBO);
|
||||||
|
|
||||||
|
|
||||||
float clearvtx[6*2] =
|
float clearvtx[6*2] =
|
||||||
|
@ -205,22 +219,22 @@ bool GLRenderer::Init()
|
||||||
1.0, 1.0
|
1.0, 1.0
|
||||||
};
|
};
|
||||||
|
|
||||||
glGenBuffers(1, &ClearVertexBufferID);
|
glGenBuffers(1, &result->ClearVertexBufferID);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID);
|
glBindBuffer(GL_ARRAY_BUFFER, result->ClearVertexBufferID);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(clearvtx), clearvtx, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(clearvtx), clearvtx, GL_STATIC_DRAW);
|
||||||
|
|
||||||
glGenVertexArrays(1, &ClearVertexArrayID);
|
glGenVertexArrays(1, &result->ClearVertexArrayID);
|
||||||
glBindVertexArray(ClearVertexArrayID);
|
glBindVertexArray(result->ClearVertexArrayID);
|
||||||
glEnableVertexAttribArray(0); // position
|
glEnableVertexAttribArray(0); // position
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
|
||||||
|
|
||||||
|
|
||||||
glGenBuffers(1, &VertexBufferID);
|
glGenBuffers(1, &result->VertexBufferID);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID);
|
glBindBuffer(GL_ARRAY_BUFFER, result->VertexBufferID);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexBuffer), NULL, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexBuffer), nullptr, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
glGenVertexArrays(1, &VertexArrayID);
|
glGenVertexArrays(1, &result->VertexArrayID);
|
||||||
glBindVertexArray(VertexArrayID);
|
glBindVertexArray(result->VertexArrayID);
|
||||||
glEnableVertexAttribArray(0); // position
|
glEnableVertexAttribArray(0); // position
|
||||||
glVertexAttribIPointer(0, 4, GL_UNSIGNED_SHORT, 7*4, (void*)(0));
|
glVertexAttribIPointer(0, 4, GL_UNSIGNED_SHORT, 7*4, (void*)(0));
|
||||||
glEnableVertexAttribArray(1); // color
|
glEnableVertexAttribArray(1); // color
|
||||||
|
@ -230,43 +244,43 @@ bool GLRenderer::Init()
|
||||||
glEnableVertexAttribArray(3); // attrib
|
glEnableVertexAttribArray(3); // attrib
|
||||||
glVertexAttribIPointer(3, 3, GL_UNSIGNED_INT, 7*4, (void*)(4*4));
|
glVertexAttribIPointer(3, 3, GL_UNSIGNED_INT, 7*4, (void*)(4*4));
|
||||||
|
|
||||||
glGenBuffers(1, &IndexBufferID);
|
glGenBuffers(1, &result->IndexBufferID);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result->IndexBufferID);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(IndexBuffer), NULL, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(IndexBuffer), nullptr, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
glGenFramebuffers(4, &FramebufferID[0]);
|
glGenFramebuffers(4, &result->FramebufferID[0]);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[0]);
|
glBindFramebuffer(GL_FRAMEBUFFER, result->FramebufferID[0]);
|
||||||
|
|
||||||
glGenTextures(8, &FramebufferTex[0]);
|
glGenTextures(8, &result->FramebufferTex[0]);
|
||||||
FrontBuffer = 0;
|
result->FrontBuffer = 0;
|
||||||
|
|
||||||
// color buffers
|
// color buffers
|
||||||
SetupDefaultTexParams(FramebufferTex[0]);
|
SetupDefaultTexParams(result->FramebufferTex[0]);
|
||||||
SetupDefaultTexParams(FramebufferTex[1]);
|
SetupDefaultTexParams(result->FramebufferTex[1]);
|
||||||
|
|
||||||
// depth/stencil buffer
|
// depth/stencil buffer
|
||||||
SetupDefaultTexParams(FramebufferTex[4]);
|
SetupDefaultTexParams(result->FramebufferTex[4]);
|
||||||
SetupDefaultTexParams(FramebufferTex[6]);
|
SetupDefaultTexParams(result->FramebufferTex[6]);
|
||||||
|
|
||||||
// attribute buffer
|
// attribute buffer
|
||||||
// R: opaque polyID (for edgemarking)
|
// R: opaque polyID (for edgemarking)
|
||||||
// G: edge flag
|
// G: edge flag
|
||||||
// B: fog flag
|
// B: fog flag
|
||||||
SetupDefaultTexParams(FramebufferTex[5]);
|
SetupDefaultTexParams(result->FramebufferTex[5]);
|
||||||
SetupDefaultTexParams(FramebufferTex[7]);
|
SetupDefaultTexParams(result->FramebufferTex[7]);
|
||||||
|
|
||||||
// downscale framebuffer for display capture (always 256x192)
|
// downscale framebuffer for display capture (always 256x192)
|
||||||
SetupDefaultTexParams(FramebufferTex[3]);
|
SetupDefaultTexParams(result->FramebufferTex[3]);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
|
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
|
||||||
|
|
||||||
glGenBuffers(1, &PixelbufferID);
|
glGenBuffers(1, &result->PixelbufferID);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glGenTextures(1, &TexMemID);
|
glGenTextures(1, &result->TexMemID);
|
||||||
glBindTexture(GL_TEXTURE_2D, TexMemID);
|
glBindTexture(GL_TEXTURE_2D, result->TexMemID);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
@ -274,8 +288,8 @@ bool GLRenderer::Init()
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 1024, 512, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 1024, 512, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glGenTextures(1, &TexPalMemID);
|
glGenTextures(1, &result->TexPalMemID);
|
||||||
glBindTexture(GL_TEXTURE_2D, TexPalMemID);
|
glBindTexture(GL_TEXTURE_2D, result->TexPalMemID);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
@ -284,11 +298,13 @@ bool GLRenderer::Init()
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLRenderer::DeInit()
|
GLRenderer::~GLRenderer()
|
||||||
{
|
{
|
||||||
|
assert(glDeleteTextures != nullptr);
|
||||||
|
|
||||||
glDeleteTextures(1, &TexMemID);
|
glDeleteTextures(1, &TexMemID);
|
||||||
glDeleteTextures(1, &TexPalMemID);
|
glDeleteTextures(1, &TexPalMemID);
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,7 @@ namespace GPU3D
|
||||||
class GLRenderer : public Renderer3D
|
class GLRenderer : public Renderer3D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GLRenderer();
|
virtual ~GLRenderer() override;
|
||||||
virtual ~GLRenderer() override {};
|
|
||||||
virtual bool Init() override;
|
|
||||||
virtual void DeInit() override;
|
|
||||||
virtual void Reset() override;
|
virtual void Reset() override;
|
||||||
|
|
||||||
virtual void SetRenderSettings(GPU::RenderSettings& settings) override;
|
virtual void SetRenderSettings(GPU::RenderSettings& settings) override;
|
||||||
|
@ -42,7 +39,11 @@ public:
|
||||||
|
|
||||||
void SetupAccelFrame();
|
void SetupAccelFrame();
|
||||||
void PrepareCaptureFrame();
|
void PrepareCaptureFrame();
|
||||||
|
|
||||||
|
static std::unique_ptr<GLRenderer> New() noexcept;
|
||||||
private:
|
private:
|
||||||
|
// Used by New()
|
||||||
|
GLRenderer() noexcept;
|
||||||
|
|
||||||
// GL version requirements
|
// GL version requirements
|
||||||
// * texelFetch: 3.0 (GLSL 1.30) (3.2/1.50 for MS)
|
// * texelFetch: 3.0 (GLSL 1.30) (3.2/1.50 for MS)
|
||||||
|
@ -62,7 +63,7 @@ private:
|
||||||
u32 RenderKey;
|
u32 RenderKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
RendererPolygon PolygonList[2048];
|
RendererPolygon PolygonList[2048] {};
|
||||||
|
|
||||||
bool BuildRenderShader(u32 flags, const char* vs, const char* fs);
|
bool BuildRenderShader(u32 flags, const char* vs, const char* fs);
|
||||||
void UseRenderShader(u32 flags);
|
void UseRenderShader(u32 flags);
|
||||||
|
@ -83,13 +84,13 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
GLuint ClearShaderPlain[3];
|
GLuint ClearShaderPlain[3] {};
|
||||||
|
|
||||||
GLuint RenderShader[16][3];
|
GLuint RenderShader[16][3] {};
|
||||||
GLuint CurShaderID = -1;
|
GLuint CurShaderID = -1;
|
||||||
|
|
||||||
GLuint FinalPassEdgeShader[3];
|
GLuint FinalPassEdgeShader[3] {};
|
||||||
GLuint FinalPassFogShader[3];
|
GLuint FinalPassFogShader[3] {};
|
||||||
|
|
||||||
// std140 compliant structure
|
// std140 compliant structure
|
||||||
struct
|
struct
|
||||||
|
@ -104,13 +105,13 @@ private:
|
||||||
u32 uFogOffset; // int 304 / 1
|
u32 uFogOffset; // int 304 / 1
|
||||||
u32 uFogShift; // int 305 / 1
|
u32 uFogShift; // int 305 / 1
|
||||||
u32 _pad1[2]; // int 306 / 2
|
u32 _pad1[2]; // int 306 / 2
|
||||||
} ShaderConfig;
|
} ShaderConfig {};
|
||||||
|
|
||||||
GLuint ShaderConfigUBO;
|
GLuint ShaderConfigUBO {};
|
||||||
int NumFinalPolys, NumOpaqueFinalPolys;
|
int NumFinalPolys {}, NumOpaqueFinalPolys {};
|
||||||
|
|
||||||
GLuint ClearVertexBufferID, ClearVertexArrayID;
|
GLuint ClearVertexBufferID = 0, ClearVertexArrayID {};
|
||||||
GLint ClearUniformLoc[4];
|
GLint ClearUniformLoc[4] {};
|
||||||
|
|
||||||
// vertex buffer
|
// vertex buffer
|
||||||
// * XYZW: 4x16bit
|
// * XYZW: 4x16bit
|
||||||
|
@ -124,28 +125,28 @@ private:
|
||||||
// * bit8: front-facing (?)
|
// * bit8: front-facing (?)
|
||||||
// * bit9: W-buffering (?)
|
// * bit9: W-buffering (?)
|
||||||
|
|
||||||
GLuint VertexBufferID;
|
GLuint VertexBufferID {};
|
||||||
u32 VertexBuffer[10240 * 7];
|
u32 VertexBuffer[10240 * 7] {};
|
||||||
u32 NumVertices;
|
u32 NumVertices {};
|
||||||
|
|
||||||
GLuint VertexArrayID;
|
GLuint VertexArrayID {};
|
||||||
GLuint IndexBufferID;
|
GLuint IndexBufferID {};
|
||||||
u16 IndexBuffer[2048 * 40];
|
u16 IndexBuffer[2048 * 40] {};
|
||||||
u32 NumIndices, NumEdgeIndices;
|
u32 NumIndices {}, NumEdgeIndices {};
|
||||||
|
|
||||||
const u32 EdgeIndicesOffset = 2048 * 30;
|
const u32 EdgeIndicesOffset = 2048 * 30;
|
||||||
|
|
||||||
GLuint TexMemID;
|
GLuint TexMemID {};
|
||||||
GLuint TexPalMemID;
|
GLuint TexPalMemID {};
|
||||||
|
|
||||||
int ScaleFactor;
|
int ScaleFactor {};
|
||||||
bool BetterPolygons;
|
bool BetterPolygons {};
|
||||||
int ScreenW, ScreenH;
|
int ScreenW {}, ScreenH {};
|
||||||
|
|
||||||
GLuint FramebufferTex[8];
|
GLuint FramebufferTex[8] {};
|
||||||
int FrontBuffer;
|
int FrontBuffer {};
|
||||||
GLuint FramebufferID[4], PixelbufferID;
|
GLuint FramebufferID[4] {}, PixelbufferID {};
|
||||||
u32 Framebuffer[256*192];
|
u32 Framebuffer[256*192] {};
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,13 +71,8 @@ void SoftRenderer::SetupRenderThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SoftRenderer::SoftRenderer()
|
SoftRenderer::SoftRenderer() noexcept
|
||||||
: Renderer3D(false)
|
: Renderer3D(false)
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SoftRenderer::Init()
|
|
||||||
{
|
{
|
||||||
Sema_RenderStart = Platform::Semaphore_Create();
|
Sema_RenderStart = Platform::Semaphore_Create();
|
||||||
Sema_RenderDone = Platform::Semaphore_Create();
|
Sema_RenderDone = Platform::Semaphore_Create();
|
||||||
|
@ -86,11 +81,9 @@ bool SoftRenderer::Init()
|
||||||
Threaded = false;
|
Threaded = false;
|
||||||
RenderThreadRunning = false;
|
RenderThreadRunning = false;
|
||||||
RenderThreadRendering = false;
|
RenderThreadRendering = false;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftRenderer::DeInit()
|
SoftRenderer::~SoftRenderer()
|
||||||
{
|
{
|
||||||
StopRenderThread();
|
StopRenderThread();
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,8 @@ namespace GPU3D
|
||||||
class SoftRenderer : public Renderer3D
|
class SoftRenderer : public Renderer3D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SoftRenderer();
|
SoftRenderer() noexcept;
|
||||||
virtual ~SoftRenderer() override {};
|
virtual ~SoftRenderer() override;
|
||||||
virtual bool Init() override;
|
|
||||||
virtual void DeInit() override;
|
|
||||||
virtual void Reset() override;
|
virtual void Reset() override;
|
||||||
|
|
||||||
virtual void SetRenderSettings(GPU::RenderSettings& settings) override;
|
virtual void SetRenderSettings(GPU::RenderSettings& settings) override;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "GPU_OpenGL.h"
|
#include "GPU_OpenGL.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -32,34 +33,37 @@ namespace GPU
|
||||||
|
|
||||||
using namespace OpenGL;
|
using namespace OpenGL;
|
||||||
|
|
||||||
bool GLCompositor::Init()
|
std::unique_ptr<GLCompositor> GLCompositor::New() noexcept
|
||||||
{
|
{
|
||||||
if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, CompShader[0], "CompositorShader"))
|
assert(glBindAttribLocation != nullptr);
|
||||||
//if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Linear, CompShader[0], "CompositorShader"))
|
|
||||||
//if (!OpenGL::BuildShaderProgram(kCompositorVS_xBRZ, kCompositorFS_xBRZ, CompShader[0], "CompositorShader"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (int i = 0; i < 1; i++)
|
std::array<GLuint, 3> CompShader {};
|
||||||
{
|
if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, &CompShader[0], "CompositorShader"))
|
||||||
GLint uni_id;
|
return nullptr;
|
||||||
|
|
||||||
glBindAttribLocation(CompShader[i][2], 0, "vPosition");
|
glBindAttribLocation(CompShader[2], 0, "vPosition");
|
||||||
glBindAttribLocation(CompShader[i][2], 1, "vTexcoord");
|
glBindAttribLocation(CompShader[2], 1, "vTexcoord");
|
||||||
glBindFragDataLocation(CompShader[i][2], 0, "oColor");
|
glBindFragDataLocation(CompShader[2], 0, "oColor");
|
||||||
|
|
||||||
if (!OpenGL::LinkShaderProgram(CompShader[i]))
|
if (!OpenGL::LinkShaderProgram(CompShader.data()))
|
||||||
return false;
|
// OpenGL::LinkShaderProgram already deletes the shader program object
|
||||||
|
// if linking the shaders together failed.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
CompScaleLoc[i] = glGetUniformLocation(CompShader[i][2], "u3DScale");
|
return std::unique_ptr<GLCompositor>(new GLCompositor(CompShader));
|
||||||
Comp3DXPosLoc[i] = glGetUniformLocation(CompShader[i][2], "u3DXPos");
|
|
||||||
|
|
||||||
glUseProgram(CompShader[i][2]);
|
|
||||||
uni_id = glGetUniformLocation(CompShader[i][2], "ScreenTex");
|
|
||||||
glUniform1i(uni_id, 0);
|
|
||||||
uni_id = glGetUniformLocation(CompShader[i][2], "_3DTex");
|
|
||||||
glUniform1i(uni_id, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLCompositor::GLCompositor(std::array<GLuint, 3> compShader) noexcept : CompShader(compShader)
|
||||||
|
{
|
||||||
|
CompScaleLoc = glGetUniformLocation(CompShader[2], "u3DScale");
|
||||||
|
Comp3DXPosLoc = glGetUniformLocation(CompShader[2], "u3DXPos");
|
||||||
|
|
||||||
|
glUseProgram(CompShader[2]);
|
||||||
|
GLuint screenTextureUniform = glGetUniformLocation(CompShader[2], "ScreenTex");
|
||||||
|
glUniform1i(screenTextureUniform, 0);
|
||||||
|
GLuint _3dTextureUniform = glGetUniformLocation(CompShader[2], "_3DTex");
|
||||||
|
glUniform1i(_3dTextureUniform, 1);
|
||||||
|
|
||||||
// all this mess is to prevent bleeding
|
// all this mess is to prevent bleeding
|
||||||
#define SETVERTEX(i, x, y, offset) \
|
#define SETVERTEX(i, x, y, offset) \
|
||||||
CompVertices[i].Position[0] = x; \
|
CompVertices[i].Position[0] = x; \
|
||||||
|
@ -119,12 +123,12 @@ bool GLCompositor::Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCompositor::DeInit()
|
GLCompositor::~GLCompositor()
|
||||||
{
|
{
|
||||||
|
assert(glDeleteFramebuffers != nullptr);
|
||||||
|
|
||||||
glDeleteFramebuffers(2, CompScreenOutputFB);
|
glDeleteFramebuffers(2, CompScreenOutputFB);
|
||||||
glDeleteTextures(1, &CompScreenInputTex);
|
glDeleteTextures(1, &CompScreenInputTex);
|
||||||
glDeleteTextures(2, CompScreenOutputTex);
|
glDeleteTextures(2, CompScreenOutputTex);
|
||||||
|
@ -132,8 +136,7 @@ void GLCompositor::DeInit()
|
||||||
glDeleteVertexArrays(1, &CompVertexArrayID);
|
glDeleteVertexArrays(1, &CompVertexArrayID);
|
||||||
glDeleteBuffers(1, &CompVertexBufferID);
|
glDeleteBuffers(1, &CompVertexBufferID);
|
||||||
|
|
||||||
for (int i = 0; i < 1; i++)
|
OpenGL::DeleteShaderProgram(CompShader.data());
|
||||||
OpenGL::DeleteShaderProgram(CompShader[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCompositor::Reset()
|
void GLCompositor::Reset()
|
||||||
|
@ -197,11 +200,11 @@ void GLCompositor::RenderFrame()
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// TODO: select more shaders (filtering, etc)
|
// TODO: select more shaders (filtering, etc)
|
||||||
OpenGL::UseShaderProgram(CompShader[0]);
|
OpenGL::UseShaderProgram(CompShader.data());
|
||||||
glUniform1ui(CompScaleLoc[0], Scale);
|
glUniform1ui(CompScaleLoc, Scale);
|
||||||
|
|
||||||
// TODO: support setting this midframe, if ever needed
|
// TODO: support setting this midframe, if ever needed
|
||||||
glUniform1i(Comp3DXPosLoc[0], ((int)GPU3D::RenderXPos << 23) >> 23);
|
glUniform1i(Comp3DXPosLoc, ((int)GPU3D::RenderXPos << 23) >> 23);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, CompScreenInputTex);
|
glBindTexture(GL_TEXTURE_2D, CompScreenInputTex);
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
|
|
||||||
#include "OpenGLSupport.h"
|
#include "OpenGLSupport.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace GPU
|
namespace GPU
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -28,12 +31,11 @@ struct RenderSettings;
|
||||||
class GLCompositor
|
class GLCompositor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GLCompositor() = default;
|
static std::unique_ptr<GLCompositor> New() noexcept;
|
||||||
GLCompositor(const GLCompositor&) = delete;
|
GLCompositor(const GLCompositor&) = delete;
|
||||||
GLCompositor& operator=(const GLCompositor&) = delete;
|
GLCompositor& operator=(const GLCompositor&) = delete;
|
||||||
|
~GLCompositor();
|
||||||
|
|
||||||
bool Init();
|
|
||||||
void DeInit();
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
void SetRenderSettings(RenderSettings& settings);
|
void SetRenderSettings(RenderSettings& settings);
|
||||||
|
@ -42,13 +44,14 @@ public:
|
||||||
void RenderFrame();
|
void RenderFrame();
|
||||||
void BindOutputTexture(int buf);
|
void BindOutputTexture(int buf);
|
||||||
private:
|
private:
|
||||||
|
GLCompositor(std::array<GLuint, 3> CompShader) noexcept;
|
||||||
|
|
||||||
int Scale;
|
int Scale;
|
||||||
int ScreenH, ScreenW;
|
int ScreenH, ScreenW;
|
||||||
|
|
||||||
GLuint CompShader[1][3];
|
std::array<GLuint, 3> CompShader;
|
||||||
GLuint CompScaleLoc[1];
|
GLuint CompScaleLoc;
|
||||||
GLuint Comp3DXPosLoc[1];
|
GLuint Comp3DXPosLoc;
|
||||||
|
|
||||||
GLuint CompVertexBufferID;
|
GLuint CompVertexBufferID;
|
||||||
GLuint CompVertexArrayID;
|
GLuint CompVertexArrayID;
|
||||||
|
|
|
@ -226,10 +226,16 @@ void DeInit()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
delete ARM9;
|
delete ARM9;
|
||||||
|
ARM9 = nullptr;
|
||||||
|
|
||||||
delete ARM7;
|
delete ARM7;
|
||||||
|
ARM7 = nullptr;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
delete DMAs[i];
|
delete DMAs[i];
|
||||||
|
DMAs[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
NDSCart::DeInit();
|
NDSCart::DeInit();
|
||||||
GBACart::DeInit();
|
GBACart::DeInit();
|
||||||
|
|
|
@ -29,6 +29,12 @@ bool BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char*
|
||||||
int len;
|
int len;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
if (!glCreateShader)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, "OpenGL: Cannot build shader program, OpenGL hasn't been loaded\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ids[0] = glCreateShader(GL_VERTEX_SHADER);
|
ids[0] = glCreateShader(GL_VERTEX_SHADER);
|
||||||
len = strlen(vs);
|
len = strlen(vs);
|
||||||
glShaderSource(ids[0], 1, &vs, &len);
|
glShaderSource(ids[0], 1, &vs, &len);
|
||||||
|
@ -87,6 +93,12 @@ bool LinkShaderProgram(GLuint* ids)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
if (!glLinkProgram)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, "OpenGL: Cannot link shader program, OpenGL hasn't been loaded\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glLinkProgram(ids[2]);
|
glLinkProgram(ids[2]);
|
||||||
|
|
||||||
glDetachShader(ids[2], ids[0]);
|
glDetachShader(ids[2], ids[0]);
|
||||||
|
@ -115,12 +127,18 @@ bool LinkShaderProgram(GLuint* ids)
|
||||||
|
|
||||||
void DeleteShaderProgram(GLuint* ids)
|
void DeleteShaderProgram(GLuint* ids)
|
||||||
{
|
{
|
||||||
|
if (glDeleteProgram)
|
||||||
|
{ // If OpenGL isn't loaded, then there's no shader program to delete
|
||||||
glDeleteProgram(ids[2]);
|
glDeleteProgram(ids[2]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UseShaderProgram(GLuint* ids)
|
void UseShaderProgram(GLuint* ids)
|
||||||
{
|
{
|
||||||
|
if (glUseProgram)
|
||||||
|
{ // If OpenGL isn't loaded, then there's no shader program to use
|
||||||
glUseProgram(ids[2]);
|
glUseProgram(ids[2]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@ bool Init()
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
if (Firmware) delete[] Firmware;
|
if (Firmware) delete[] Firmware;
|
||||||
|
Firmware = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 FixFirmwareLength(u32 originalLength)
|
u32 FixFirmwareLength(u32 originalLength)
|
||||||
|
|
|
@ -135,12 +135,18 @@ bool Init()
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
delete Channels[i];
|
delete Channels[i];
|
||||||
|
Channels[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
delete Capture[0];
|
delete Capture[0];
|
||||||
delete Capture[1];
|
delete Capture[1];
|
||||||
|
Capture[0] = nullptr;
|
||||||
|
Capture[1] = nullptr;
|
||||||
|
|
||||||
Platform::Mutex_Free(AudioLock);
|
Platform::Mutex_Free(AudioLock);
|
||||||
|
AudioLock = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
|
|
|
@ -334,12 +334,17 @@ void Init()
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
if (audioDevice) SDL_CloseAudioDevice(audioDevice);
|
if (audioDevice) SDL_CloseAudioDevice(audioDevice);
|
||||||
|
audioDevice = 0;
|
||||||
MicClose();
|
MicClose();
|
||||||
|
|
||||||
SDL_DestroyCond(audioSync);
|
if (audioSync) SDL_DestroyCond(audioSync);
|
||||||
SDL_DestroyMutex(audioSyncLock);
|
audioSync = nullptr;
|
||||||
|
|
||||||
|
if (audioSyncLock) SDL_DestroyMutex(audioSyncLock);
|
||||||
|
audioSyncLock = nullptr;
|
||||||
|
|
||||||
if (micWavBuffer) delete[] micWavBuffer;
|
if (micWavBuffer) delete[] micWavBuffer;
|
||||||
|
micWavBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSync()
|
void AudioSync()
|
||||||
|
|
|
@ -296,6 +296,8 @@ bool Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeInit()
|
void DeInit()
|
||||||
|
{
|
||||||
|
if (MPQueue)
|
||||||
{
|
{
|
||||||
MPQueue->lock();
|
MPQueue->lock();
|
||||||
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
|
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
|
||||||
|
@ -307,6 +309,9 @@ void DeInit()
|
||||||
SemPoolDeinit();
|
SemPoolDeinit();
|
||||||
|
|
||||||
MPQueue->detach();
|
MPQueue->detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
MPQueue = nullptr;
|
||||||
delete MPQueue;
|
delete MPQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue