Skip to content

Commit

Permalink
Show an error on screen if a shader fails to compile.
Browse files Browse the repository at this point in the history
Part of #1 investigation of #13541
  • Loading branch information
hrydgard committed Nov 5, 2020
1 parent 28da995 commit a5af0e3
Show file tree
Hide file tree
Showing 13 changed files with 64 additions and 10 deletions.
3 changes: 2 additions & 1 deletion Common/GPU/OpenGL/GLFeatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ void CheckGLExtensions() {
gl_extensions.ARB_cull_distance = g_set_gl_extensions.count("GL_ARB_cull_distance") != 0;
gl_extensions.ARB_depth_clamp = g_set_gl_extensions.count("GL_ARB_depth_clamp") != 0;
gl_extensions.ARB_uniform_buffer_object = g_set_gl_extensions.count("GL_ARB_uniform_buffer_object") != 0;
gl_extensions.ARB_explicit_attrib_location = g_set_gl_extensions.count("GL_ARB_explicit_attrib_location") != 0;

if (gl_extensions.IsGLES) {
gl_extensions.OES_texture_npot = g_set_gl_extensions.count("GL_OES_texture_npot") != 0;
Expand Down Expand Up @@ -507,7 +508,7 @@ void CheckGLExtensions() {
}
if (gl_extensions.VersionGEThan(3, 3)) {
gl_extensions.ARB_blend_func_extended = true;
// ARB_explicit_attrib_location = true;
gl_extensions.ARB_explicit_attrib_location = true;
}
if (gl_extensions.VersionGEThan(4, 0)) {
// ARB_gpu_shader5 = true;
Expand Down
1 change: 1 addition & 0 deletions Common/GPU/OpenGL/GLFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct GLExtensions {
bool ARB_pixel_buffer_object;
bool ARB_blend_func_extended; // dual source blending
bool EXT_blend_func_extended; // dual source blending (GLES, new 2015)
bool ARB_explicit_attrib_location;
bool ARB_shader_image_load_store;
bool ARB_shading_language_420pack;
bool ARB_conservative_depth;
Expand Down
23 changes: 14 additions & 9 deletions Common/GPU/OpenGL/GLQueueRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,21 +277,26 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
glCompileShader(shader);
GLint success = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
std::string infoLog = GetInfoLog(shader, glGetShaderiv, glGetShaderInfoLog);
if (!success) {
std::string infoLog = GetInfoLog(shader, glGetShaderiv, glGetShaderInfoLog);
#if PPSSPP_PLATFORM(ANDROID)
ERROR_LOG(G3D, "Error in shader compilation! %s\n", infoLog.c_str());
ERROR_LOG(G3D, "Shader source:\n%s\n", (const char *)code);
#endif
ERROR_LOG(G3D, "Error in shader compilation for: %s", step.create_shader.shader->desc.c_str());
ERROR_LOG(G3D, "Info log: %s", infoLog.c_str());
ERROR_LOG(G3D, "Shader source:\n%s\n", (const char *)code);
std::string errorString = StringFromFormat(
"Error in shader compilation for: %s\n"
"Info log: %s\n"
"Shader source:\n%s\n//END\n\n",
step.create_shader.shader->desc.c_str(),
infoLog.c_str(),
LineNumberString(code).c_str());
if (errorCallback_) {
std::string desc = StringFromFormat("Shader compilation failed: %s", step.create_shader.stage == GL_VERTEX_SHADER ? "vertex" : "fragment");
errorCallback_(desc.c_str(), errorString.c_str(), errorCallbackUserData_);
}
Reporting::ReportMessage("Error in shader compilation: info: %s\n%s\n%s", infoLog.c_str(), step.create_shader.shader->desc.c_str(), (const char *)code);
} else {
#ifdef SHADERLOG
OutputDebugStringUTF8(infoLog.c_str());
#endif
step.create_shader.shader->failed = true;
step.create_shader.shader->error = infoLog;
step.create_shader.shader->error = infoLog; // Hm, we never use this.
}
// Before we throw away the code, attach it to the shader for debugging.
step.create_shader.shader->code = code;
Expand Down
9 changes: 9 additions & 0 deletions Common/GPU/OpenGL/GLQueueRunner.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "Common/GPU/OpenGL/GLCommon.h"
#include "Common/GPU/DataFormat.h"
#include "Common/GPU/Shader.h"
#include "Common/Data/Collections/TinySet.h"

struct GLRViewport {
Expand Down Expand Up @@ -341,6 +342,11 @@ class GLQueueRunner {
public:
GLQueueRunner() {}

void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {
errorCallback_ = callback;
errorCallbackUserData_ = userdata;
}

void RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls);

void RunSteps(const std::vector<GLRStep *> &steps, bool skipGLCalls);
Expand Down Expand Up @@ -423,4 +429,7 @@ class GLQueueRunner {

bool sawOutOfMemory_ = false;
bool useDebugGroups_ = false;

ErrorCallbackFn errorCallback_ = nullptr;
void *errorCallbackUserData_ = nullptr;
};
4 changes: 4 additions & 0 deletions Common/GPU/OpenGL/GLRenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ class GLRenderManager {
GLRenderManager();
~GLRenderManager();

void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {
queueRunner_.SetErrorCallback(callback, userdata);
}

void ThreadStart(Draw::DrawContext *draw);
void ThreadEnd();
bool ThreadFrame(); // Returns false to request exiting the loop.
Expand Down
4 changes: 4 additions & 0 deletions Common/GPU/OpenGL/thin3d_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ class OpenGLContext : public DrawContext {
}
uint32_t GetDataFormatSupport(DataFormat fmt) const override;

void SetErrorCallback(ErrorCallbackFn callback, void *userdata) override {
renderManager_.SetErrorCallback(callback, userdata);
}

DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override;
BlendState *CreateBlendState(const BlendStateDesc &desc) override;
SamplerState *CreateSamplerState(const SamplerStateDesc &desc) override;
Expand Down
5 changes: 5 additions & 0 deletions Common/GPU/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,8 @@ struct ShaderLanguageDesc {
bool forceMatrix4x4 = false;
bool coefsFromBuffers = false;
};

// For passing error messages from shader compilation (and other critical issues) back to the host.
// This can run on any thread - be aware!
// TODO: See if we can find a less generic name for this.
typedef void (*ErrorCallbackFn)(const char *shortDesc, const char *details, void *userdata);
2 changes: 2 additions & 0 deletions Common/GPU/thin3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,8 @@ class DrawContext {

virtual uint32_t GetSupportedShaderLanguages() const = 0;

virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {}

// Partial pipeline state, used to create pipelines. (in practice, in d3d11 they'll use the native state objects directly).
virtual DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) = 0;
virtual BlendState *CreateBlendState(const BlendStateDesc &desc) = 0;
Expand Down
2 changes: 2 additions & 0 deletions GPU/Common/FragmentShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu

ShaderWriter p(buffer, compat, ShaderStage::Fragment, gl_exts.data(), gl_exts.size());

p.C("SABOTAGE");

bool lmode = id.Bit(FS_BIT_LMODE);
bool doTexture = id.Bit(FS_BIT_DO_TEXTURE);
bool enableFog = id.Bit(FS_BIT_ENABLE_FOG);
Expand Down
1 change: 1 addition & 0 deletions GPU/GLES/ShaderManagerGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ LinkedShader *ShaderManagerGLES::ApplyFragmentShader(VShaderID VSID, Shader *vs,
Shader *fs = fsCache_.Get(FSID);
if (!fs) {
// Fragment shader not in cache. Let's compile it.
// Can't really tell if we succeeded since the compile is on the GPU thread later.
fs = CompileFragmentShader(FSID);
fsCache_.Insert(FSID, fs);
diskCacheDirty_ = true;
Expand Down
5 changes: 5 additions & 0 deletions Windows/GPU/WindowsGLContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "Core/Config.h"
#include "Core/ConfigValues.h"
#include "Core/Core.h"
#include "Core/Host.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/Data/Text/I18n.h"
#include "UI/OnScreenDisplay.h"
Expand Down Expand Up @@ -420,6 +421,10 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) {
return false;
}

draw_->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) {
host->NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback");
}, nullptr);

// These are auto-reset events.
pauseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
resumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
Expand Down
10 changes: 10 additions & 0 deletions android/jni/app-android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ struct JNIEnv {};
#include "Core/System.h"
#include "Core/HLE/sceUsbCam.h"
#include "Core/HLE/sceUsbGps.h"
#include "Core/Host.h"
#include "Common/CPUDetect.h"
#include "Common/Log.h"
#include "UI/GameInfoCache.h"
Expand Down Expand Up @@ -777,6 +778,10 @@ extern "C" bool Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env,
return false;
}

graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) {
host->NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback");
}, nullptr);

if (useCPUThread) {
EmuThreadStart();
} else {
Expand All @@ -795,6 +800,11 @@ extern "C" bool Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env,
SystemToast("Graphics initialization failed. Quitting.");
return false;
}

graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) {
host->NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback");
}, nullptr);

graphicsContext->ThreadStart();
renderer_inited = true;
}
Expand Down
5 changes: 5 additions & 0 deletions ios/ViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "Core/System.h"
#include "Core/HLE/sceUsbCam.h"
#include "Core/HLE/sceUsbGps.h"
#include "Core/Host.h"

#include <sys/types.h>
#include <sys/sysctl.h>
Expand Down Expand Up @@ -202,6 +203,10 @@ - (void)viewDidLoad {

graphicsContext = new IOSGraphicsContext();

graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) {
host->NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback");
}, nullptr);

graphicsContext->ThreadStart();

dp_xscale = (float)dp_xres / (float)pixel_xres;
Expand Down

0 comments on commit a5af0e3

Please sign in to comment.