OpenGL: Add support for backend validation
This uses the OpenGL debug ouput functionality to make the driver call
us back when an error happens so we can ASSERT and fail.
BUG=dawn:190
Change-Id: I4b6d7a860384dfeccc1c37383fd4cbdc09d7dc05
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9204
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/generator/templates/opengl/opengl_platform.h b/generator/templates/opengl/opengl_platform.h
index 182f50a..9b2a53a 100644
--- a/generator/templates/opengl/opengl_platform.h
+++ b/generator/templates/opengl/opengl_platform.h
@@ -44,20 +44,8 @@
GLsizei length,
const GLchar* message,
const void* userParam);
-using GLDEBUGPROCARB = void(KHRONOS_APIENTRY*)(GLenum source,
- GLenum type,
- GLuint id,
- GLenum severity,
- GLsizei length,
- const GLchar* message,
- const void* userParam);
-using GLDEBUGPROCKHR = void(KHRONOS_APIENTRY*)(GLenum source,
- GLenum type,
- GLuint id,
- GLenum severity,
- GLsizei length,
- const GLchar* message,
- const void* userParam);
+using GLDEBUGPROCARB = GLDEBUGPROC;
+using GLDEBUGPROCKHR = GLDEBUGPROC;
using GLDEBUGPROCAMD = void(KHRONOS_APIENTRY*)(GLuint id,
GLenum category,
GLenum severity,
diff --git a/src/dawn_native/opengl/BackendGL.cpp b/src/dawn_native/opengl/BackendGL.cpp
index 94fc2fa..c168913 100644
--- a/src/dawn_native/opengl/BackendGL.cpp
+++ b/src/dawn_native/opengl/BackendGL.cpp
@@ -15,10 +15,12 @@
#include "dawn_native/opengl/BackendGL.h"
#include "common/Constants.h"
+#include "dawn_native/Instance.h"
#include "dawn_native/OpenGLBackend.h"
#include "dawn_native/opengl/DeviceGL.h"
#include <cstring>
+#include <iostream>
namespace dawn_native { namespace opengl {
@@ -47,7 +49,71 @@
}
return vendorId;
}
- } // namespace
+
+ void KHRONOS_APIENTRY OnGLDebugMessage(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar* message,
+ const void* userParam) {
+ const char* sourceText;
+ switch (source) {
+ case GL_DEBUG_SOURCE_API:
+ sourceText = "OpenGL";
+ break;
+ case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ sourceText = "Window System";
+ break;
+ case GL_DEBUG_SOURCE_SHADER_COMPILER:
+ sourceText = "Shader Compiler";
+ break;
+ case GL_DEBUG_SOURCE_THIRD_PARTY:
+ sourceText = "Third Party";
+ break;
+ case GL_DEBUG_SOURCE_APPLICATION:
+ sourceText = "Application";
+ break;
+ case GL_DEBUG_SOURCE_OTHER:
+ sourceText = "Other";
+ break;
+ default:
+ sourceText = "UNKNOWN";
+ break;
+ }
+
+ const char* severityText;
+ switch (severity) {
+ case GL_DEBUG_SEVERITY_HIGH:
+ severityText = "High";
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ severityText = "Medium";
+ break;
+ case GL_DEBUG_SEVERITY_LOW:
+ severityText = "Low";
+ break;
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ severityText = "Notification";
+ break;
+ default:
+ severityText = "UNKNOWN";
+ break;
+ }
+
+ if (type == GL_DEBUG_TYPE_ERROR) {
+ std::cout << "OpenGL error:" << std::endl;
+ std::cout << " Source: " << sourceText << std::endl;
+ std::cout << " ID: " << id << std::endl;
+ std::cout << " Severity: " << severityText << std::endl;
+ std::cout << " Message: " << message << std::endl;
+
+ // Abort on an error when in Debug mode.
+ UNREACHABLE();
+ }
+ }
+
+ } // anonymous namespace
// The OpenGL backend's Adapter.
@@ -60,6 +126,36 @@
// Use getProc to populate the dispatch table
DAWN_TRY(mFunctions.Initialize(options->getProc));
+ // Use the debug output functionality to get notified about GL errors
+ // TODO(cwallez@chromium.org): add support for the KHR_debug and ARB_debug_output
+ // extensions
+ bool hasDebugOutput = mFunctions.IsAtLeastGL(4, 3) || mFunctions.IsAtLeastGLES(3, 2);
+
+ if (GetInstance()->IsBackendValidationEnabled() && hasDebugOutput) {
+ mFunctions.Enable(GL_DEBUG_OUTPUT);
+ mFunctions.Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+
+ // Any GL error; dangerous undefined behavior; any shader compiler and linker errors
+ mFunctions.DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH,
+ 0, nullptr, GL_TRUE);
+
+ // Severe performance warnings; GLSL or other shader compiler and linker warnings;
+ // use of currently deprecated behavior
+ mFunctions.DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM,
+ 0, nullptr, GL_TRUE);
+
+ // Performance warnings from redundant state changes; trivial undefined behavior
+ // This is disabled because we do an incredible amount of redundant state changes.
+ mFunctions.DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0,
+ nullptr, GL_FALSE);
+
+ // Any message which is not an error or performance concern
+ mFunctions.DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE,
+ GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr,
+ GL_FALSE);
+ mFunctions.DebugMessageCallback(&OnGLDebugMessage, nullptr);
+ }
+
// Set state that never changes between devices.
mFunctions.Enable(GL_DEPTH_TEST);
mFunctions.Enable(GL_SCISSOR_TEST);
diff --git a/src/dawn_native/opengl/OpenGLFunctions.cpp b/src/dawn_native/opengl/OpenGLFunctions.cpp
index d56aa24..5432715 100644
--- a/src/dawn_native/opengl/OpenGLFunctions.cpp
+++ b/src/dawn_native/opengl/OpenGLFunctions.cpp
@@ -56,4 +56,14 @@
return {};
}
+ bool OpenGLFunctions::IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion) {
+ return mStandard == Standard::Desktop &&
+ std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion);
+ }
+
+ bool OpenGLFunctions::IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion) {
+ return mStandard == Standard::ES &&
+ std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion);
+ }
+
}} // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/OpenGLFunctions.h b/src/dawn_native/opengl/OpenGLFunctions.h
index 6f737ec..9fe81a5 100644
--- a/src/dawn_native/opengl/OpenGLFunctions.h
+++ b/src/dawn_native/opengl/OpenGLFunctions.h
@@ -23,6 +23,9 @@
public:
MaybeError Initialize(GetProcAddress getProc);
+ bool IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion);
+ bool IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion);
+
private:
uint32_t mMajorVersion;
uint32_t mMinorVersion;