From 5313fc5b368b8d7c92d47b0560563ae613461188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 18 Aug 2020 09:18:24 +0200 Subject: [PATCH 1/3] More work on GL state leaks. Some things really need a redesign. --- Core/HLE/sceKernel.cpp | 1 + Core/HLE/sceKernelModule.cpp | 2 +- Core/System.cpp | 6 +++--- GPU/GLES/DrawEngineGLES.cpp | 1 + UI/EmuScreen.cpp | 1 - ext/native/thin3d/GLQueueRunner.h | 1 + ext/native/thin3d/thin3d_gl.cpp | 23 +++++++++++++++++++---- 7 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 6521f3e79cbe..51aed70022dd 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -107,6 +107,7 @@ void __KernelInit() ERROR_LOG(SCEKERNEL, "Can't init kernel when kernel is running"); return; } + INFO_LOG(SCEKERNEL, "Initializing kernel..."); __KernelTimeInit(); __InterruptsInit(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 0173045ce27c..486bd06bd058 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1654,7 +1654,7 @@ void __KernelLoadReset() { bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_string) { SceKernelLoadExecParam param; - PSP_SetLoading("Loading game..."); + PSP_SetLoading("Loading exec..."); if (paramPtr) Memory::ReadStruct(paramPtr, ¶m); diff --git a/Core/System.cpp b/Core/System.cpp index 29fc5e0a30b3..6f9b58ad7b5a 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -108,9 +108,9 @@ static GPUBackend gpuBackend; static std::string gpuBackendDevice; // Ugly! -static bool pspIsInited = false; -static bool pspIsIniting = false; -static bool pspIsQuitting = false; +static volatile bool pspIsInited = false; +static volatile bool pspIsIniting = false; +static volatile bool pspIsQuitting = false; void ResetUIState() { globalUIState = UISTATE_MENU; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 215d80c07a2a..b07e819d4318 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -314,6 +314,7 @@ void DrawEngineGLES::DoFlush() { if (lastRenderStepId_ != curRenderStepId) { // Dirty everything that has dynamic state that will need re-recording. gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE); + textureCache_->ForgetLastTexture(); lastRenderStepId_ = curRenderStepId; } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index a6d5b600e104..b3557c076b94 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1090,7 +1090,6 @@ void EmuScreen::CreateViews() { loadingSpinner->SetTag("LoadingSpinner"); // Don't really need this, and it creates a lot of strings to translate... - // Maybe just show "Loading game..." only? loadingTextView->SetVisibility(V_GONE); loadingTextView->SetShadow(true); diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 2c0d49fbe807..031c17b06f6e 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -416,6 +416,7 @@ class GLQueueRunner { GLuint currentReadHandle_ = 0; GLuint AllocTextureName(); + // Texture name cache. Ripped straight from TextureCacheGLES. std::vector nameCache_; std::unordered_map glStrings_; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index c42b186b54a7..d6a2a8ee8bbe 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -483,14 +483,16 @@ class OpenGLContext : public DrawContext { private: void ApplySamplers(); + void Unbind(); GLRenderManager renderManager_; - OpenGLSamplerState *boundSamplers_[MAX_TEXTURE_SLOTS]{}; - OpenGLTexture *boundTextures_[MAX_TEXTURE_SLOTS]{}; DeviceCaps caps_{}; // Bound state + OpenGLSamplerState *boundSamplers_[MAX_TEXTURE_SLOTS]{}; + OpenGLTexture *boundTextures_[MAX_TEXTURE_SLOTS]{}; + OpenGLPipeline *curPipeline_ = nullptr; OpenGLBuffer *curVBuffers_[4]{}; int curVBufferOffsets_[4]{}; @@ -610,10 +612,14 @@ void OpenGLContext::BeginFrame() { } void OpenGLContext::EndFrame() { + Unbind(); + FrameData &frameData = frameData_[renderManager_.GetCurFrame()]; renderManager_.EndPushBuffer(frameData.push); // upload the data! renderManager_.Finish(); +} +void OpenGLContext::Unbind() { // Unbind stuff. for (auto &texture : boundTextures_) { texture = nullptr; @@ -621,6 +627,9 @@ void OpenGLContext::EndFrame() { for (auto &sampler : boundSamplers_) { sampler = nullptr; } + for (int i = 0; i < ARRAY_SIZE(boundTextures_); i++) { + renderManager_.BindTexture(i, nullptr); + } curPipeline_ = nullptr; } @@ -679,7 +688,6 @@ class OpenGLTexture : public Texture { OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : render_(render) { generatedMips_ = false; - canWrap_ = true; width_ = desc.width; height_ = desc.height; depth_ = desc.depth; @@ -1022,7 +1030,9 @@ void OpenGLContext::ApplySamplers() { for (int i = 0; i < MAX_TEXTURE_SLOTS; i++) { const OpenGLSamplerState *samp = boundSamplers_[i]; const OpenGLTexture *tex = boundTextures_[i]; - if (!samp || !tex) { + if (tex) { + _assert_(samp); + } else { continue; } GLenum wrapS; @@ -1037,6 +1047,8 @@ void OpenGLContext::ApplySamplers() { GLenum magFilt = samp->magFilt; GLenum minFilt = tex->HasMips() ? samp->mipMinFilt : samp->minFilt; renderManager_.SetTextureSampler(i, wrapS, wrapT, magFilt, minFilt, 0.0f); + // TODO: Improve this to allow mipmaps. We don't care about those right now though for thin3d stuff. + renderManager_.SetTextureLod(i, 0.0, 0.0, 0.0); } } @@ -1098,6 +1110,9 @@ void OpenGLContext::BindPipeline(Pipeline *pipeline) { curPipeline_->depthStencil->Apply(&renderManager_, stencilRef_); curPipeline_->raster->Apply(&renderManager_); renderManager_.BindProgram(curPipeline_->program_); + } else { + // Wipe bound textures and samplers. + Unbind(); } } From 06ab2159e919a08d1fb78856ccfe51491f7c5d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 18 Aug 2020 09:18:50 +0200 Subject: [PATCH 2/3] Windows: Auto-enable GL validation (debug messages) in debug builds --- Windows/GPU/WindowsGLContext.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index dc9037a7836d..01933b27018a 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -131,8 +131,13 @@ void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenu void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { // Ignore buffer mapping messages from NVIDIA - if (source == GL_DEBUG_SOURCE_API_ARB && type == GL_DEBUG_TYPE_OTHER_ARB && id == 131185) + if (source == GL_DEBUG_SOURCE_API_ARB && type == GL_DEBUG_TYPE_OTHER_ARB && id == 131185) { return; + } + // Ignore application messages + if (source == GL_DEBUG_SOURCE_APPLICATION) { + return; + } (void)length; FILE *outFile = (FILE *)userParam; @@ -366,7 +371,14 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) { hRC = m_hrc; - if (g_Config.bGfxDebugOutput) { + bool validation = g_Config.bGfxDebugOutput; + + // Always run OpenGL validation in debug mode, just like we do with Vulkan if debug layers are installed. +#ifdef _DEBUG + validation = true; +#endif + + if (validation) { if (wglewIsSupported("GL_KHR_debug") == 1) { glGetError(); glDebugMessageCallback((GLDEBUGPROC)&DebugCallbackARB, nullptr); From 06a528927e61e1bf5a14945202a85766fb3952f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 18 Aug 2020 12:57:33 +0200 Subject: [PATCH 3/3] GL: Re-enable mipmaps for thin3d textures. --- ext/native/thin3d/thin3d_gl.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index d6a2a8ee8bbe..3a7c0f958c56 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -672,6 +672,9 @@ class OpenGLTexture : public Texture { void Bind(int stage) { render_->BindTexture(stage, tex_); } + int NumMipmaps() const { + return mipLevels_; + } private: void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback); @@ -1047,8 +1050,7 @@ void OpenGLContext::ApplySamplers() { GLenum magFilt = samp->magFilt; GLenum minFilt = tex->HasMips() ? samp->mipMinFilt : samp->minFilt; renderManager_.SetTextureSampler(i, wrapS, wrapT, magFilt, minFilt, 0.0f); - // TODO: Improve this to allow mipmaps. We don't care about those right now though for thin3d stuff. - renderManager_.SetTextureLod(i, 0.0, 0.0, 0.0); + renderManager_.SetTextureLod(i, 0.0, (float)(tex->NumMipmaps() - 1), 0.0); } }