diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index b11743e6d1..7246c5654c 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -163,9 +163,7 @@ void FramebufferManagerGLES::CompilePostShader() { semantics.push_back({ 0, "a_position" }); semantics.push_back({ 1, "a_texcoord0" }); postShaderProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false); - for (auto iter : shaders) { - render_->DeleteShader(iter); - } + postShaderModules_ = shaders; } else { ERROR_LOG(FRAMEBUF, "Failed to translate post shader!"); } @@ -176,31 +174,7 @@ void FramebufferManagerGLES::CompilePostShader() { // DO NOT turn this into a report, as it will pollute our logs with all kinds of // user shader experiments. ERROR_LOG(FRAMEBUF, "Failed to build post-processing program from %s and %s!\n%s", shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), errorString.c_str()); - // let's show the first line of the error string as an OSM. - std::set blacklistedLines; - // These aren't useful to show, skip to the first interesting line. - blacklistedLines.insert("Fragment shader failed to compile with the following errors:"); - blacklistedLines.insert("Vertex shader failed to compile with the following errors:"); - blacklistedLines.insert("Compile failed."); - blacklistedLines.insert(""); - - std::string firstLine; - size_t start = 0; - for (size_t i = 0; i < errorString.size(); i++) { - if (errorString[i] == '\n') { - firstLine = errorString.substr(start, i - start); - if (blacklistedLines.find(firstLine) == blacklistedLines.end()) { - break; - } - start = i + 1; - firstLine.clear(); - } - } - if (!firstLine.empty()) { - host->NotifyUserMessage("Post-shader error: " + firstLine + "...", 10.0f, 0xFF3090FF); - } else { - host->NotifyUserMessage("Post-shader error, see log for details", 10.0f, 0xFF3090FF); - } + ShowPostShaderError(errorString); usePostShader_ = false; } else { usePostShader_ = true; @@ -211,6 +185,36 @@ void FramebufferManagerGLES::CompilePostShader() { } } +void FramebufferManagerGLES::ShowPostShaderError(const std::string &errorString) { + // let's show the first line of the error string as an OSM. + std::set blacklistedLines; + // These aren't useful to show, skip to the first interesting line. + blacklistedLines.insert("Fragment shader failed to compile with the following errors:"); + blacklistedLines.insert("Vertex shader failed to compile with the following errors:"); + blacklistedLines.insert("Compile failed."); + blacklistedLines.insert(""); + + std::string firstLine; + size_t start = 0; + for (size_t i = 0; i < errorString.size(); i++) { + if (errorString[i] == '\n' && i == start) { + start = i + 1; + } else if (errorString[i] == '\n') { + firstLine = errorString.substr(start, i - start); + if (blacklistedLines.find(firstLine) == blacklistedLines.end()) { + break; + } + start = i + 1; + firstLine.clear(); + } + } + if (!firstLine.empty()) { + host->NotifyUserMessage("Post-shader error: " + firstLine + "...", 10.0f, 0xFF3090FF); + } else { + host->NotifyUserMessage("Post-shader error, see log for details", 10.0f, 0xFF3090FF); + } +} + void FramebufferManagerGLES::Bind2DShader() { render_->BindProgram(draw2dprogram_); } @@ -220,6 +224,30 @@ void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms) if (!postShaderProgram_) { CompileDraw2DProgram(); } + + bool failed = false; + std::string errorMessage; + for (size_t i = 0; i < postShaderModules_.size(); ++i) { + auto &shader = postShaderModules_[i]; + if (shader->failed) { + failed = true; + errorMessage += shader->error + "\n"; + } + + if (shader->valid || shader->failed) { + render_->DeleteShader(shader); + postShaderModules_.erase(postShaderModules_.begin() + i); + // Check this index again. + i--; + } + } + + if (failed) { + ShowPostShaderError(errorMessage); + // Show stuff if possible in an upcoming frame. + usePostShader_ = false; + } + render_->BindProgram(postShaderProgram_); if (deltaLoc_ != -1) render_->SetUniformF(&deltaLoc_, 2, uniforms.texelDelta); @@ -286,6 +314,11 @@ void FramebufferManagerGLES::DestroyDeviceObjects() { render_->DeleteProgram(postShaderProgram_); postShaderProgram_ = nullptr; } + // Will usually be clear already. + for (auto iter : postShaderModules_) { + render_->DeleteShader(iter); + } + postShaderModules_.clear(); if (drawPixelsTex_) { render_->DeleteTexture(drawPixelsTex_); drawPixelsTex_ = 0; diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index fb00c41858..c7ad049210 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -83,6 +83,7 @@ private: void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override; void Bind2DShader() override; void BindPostShader(const PostShaderUniforms &uniforms) override; + void ShowPostShaderError(const std::string &errorMessage); void CompileDraw2DProgram(); void CompilePostShader(); @@ -100,6 +101,7 @@ private: u32 convBufSize_ = 0; GLRProgram *draw2dprogram_ = nullptr; GLRProgram *postShaderProgram_ = nullptr; + std::vector postShaderModules_; GLRProgram *stencilUploadProgram_ = nullptr; int u_stencilUploadTex = -1; diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 1bfb3a4262..c312f468e7 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -215,6 +215,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps) { #endif step.create_shader.shader->valid = false; step.create_shader.shader->failed = true; + step.create_shader.shader->error = infoLog; } // Before we throw away the code, attach it to the shader for debugging. step.create_shader.shader->code = code; diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index e697aa3220..37279ec750 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -79,6 +79,7 @@ public: bool failed = false; std::string desc; std::string code; + std::string error; }; class GLRProgram {