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:
parent
fefb3ab120
commit
ba84fb2977
|
@ -44,20 +44,8 @@ using GLDEBUGPROC = void(KHRONOS_APIENTRY*)(GLenum source,
|
||||||
GLsizei length,
|
GLsizei length,
|
||||||
const GLchar* message,
|
const GLchar* message,
|
||||||
const void* userParam);
|
const void* userParam);
|
||||||
using GLDEBUGPROCARB = void(KHRONOS_APIENTRY*)(GLenum source,
|
using GLDEBUGPROCARB = GLDEBUGPROC;
|
||||||
GLenum type,
|
using GLDEBUGPROCKHR = GLDEBUGPROC;
|
||||||
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 GLDEBUGPROCAMD = void(KHRONOS_APIENTRY*)(GLuint id,
|
using GLDEBUGPROCAMD = void(KHRONOS_APIENTRY*)(GLuint id,
|
||||||
GLenum category,
|
GLenum category,
|
||||||
GLenum severity,
|
GLenum severity,
|
||||||
|
|
|
@ -15,10 +15,12 @@
|
||||||
#include "dawn_native/opengl/BackendGL.h"
|
#include "dawn_native/opengl/BackendGL.h"
|
||||||
|
|
||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
|
#include "dawn_native/Instance.h"
|
||||||
#include "dawn_native/OpenGLBackend.h"
|
#include "dawn_native/OpenGLBackend.h"
|
||||||
#include "dawn_native/opengl/DeviceGL.h"
|
#include "dawn_native/opengl/DeviceGL.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace dawn_native { namespace opengl {
|
namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
|
@ -47,7 +49,71 @@ namespace dawn_native { namespace opengl {
|
||||||
}
|
}
|
||||||
return vendorId;
|
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.
|
// The OpenGL backend's Adapter.
|
||||||
|
|
||||||
|
@ -60,6 +126,36 @@ namespace dawn_native { namespace opengl {
|
||||||
// Use getProc to populate the dispatch table
|
// Use getProc to populate the dispatch table
|
||||||
DAWN_TRY(mFunctions.Initialize(options->getProc));
|
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.
|
// Set state that never changes between devices.
|
||||||
mFunctions.Enable(GL_DEPTH_TEST);
|
mFunctions.Enable(GL_DEPTH_TEST);
|
||||||
mFunctions.Enable(GL_SCISSOR_TEST);
|
mFunctions.Enable(GL_SCISSOR_TEST);
|
||||||
|
|
|
@ -56,4 +56,14 @@ namespace dawn_native { namespace opengl {
|
||||||
return {};
|
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
|
}} // namespace dawn_native::opengl
|
||||||
|
|
|
@ -23,6 +23,9 @@ namespace dawn_native { namespace opengl {
|
||||||
public:
|
public:
|
||||||
MaybeError Initialize(GetProcAddress getProc);
|
MaybeError Initialize(GetProcAddress getProc);
|
||||||
|
|
||||||
|
bool IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion);
|
||||||
|
bool IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t mMajorVersion;
|
uint32_t mMajorVersion;
|
||||||
uint32_t mMinorVersion;
|
uint32_t mMinorVersion;
|
||||||
|
|
Loading…
Reference in New Issue