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>
This commit is contained in:
Corentin Wallez 2019-07-22 10:02:49 +00:00 committed by Commit Bot service account
parent fefb3ab120
commit ba84fb2977
4 changed files with 112 additions and 15 deletions

View File

@ -44,20 +44,8 @@ using GLDEBUGPROC = void(KHRONOS_APIENTRY*)(GLenum source,
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,

View File

@ -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 @@ namespace dawn_native { namespace opengl {
}
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 @@ namespace dawn_native { namespace opengl {
// 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);

View File

@ -56,4 +56,14 @@ namespace dawn_native { namespace opengl {
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

View File

@ -23,6 +23,9 @@ namespace dawn_native { namespace opengl {
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;