Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenGL(ES) debugging improvements #14772

Merged
merged 6 commits into from Nov 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 29 additions & 2 deletions xbmc/guilib/Shader.cpp
Expand Up @@ -11,6 +11,7 @@
#include "filesystem/File.h"
#include "utils/log.h"
#include "utils/GLUtils.h"
#include "utils/StringUtils.h"
#include "rendering/RenderSystem.h"

#ifdef HAS_GLES
Expand Down Expand Up @@ -51,6 +52,9 @@ bool CShader::LoadSource(const std::string& filename, const std::string& prefix)
pos = versionPos + 1;
}
m_source.insert(pos, prefix);

m_filenames = filename;

return true;
}

Expand All @@ -72,6 +76,9 @@ bool CShader::AppendSource(const std::string& filename)
}
getline(file, temp, '\0');
m_source.append(temp);

m_filenames.append(" " + filename);

return true;
}

Expand Down Expand Up @@ -102,9 +109,27 @@ bool CShader::InsertSource(const std::string& filename, const std::string& loc)

m_source.insert(locPos, temp);

m_filenames.append(" " + filename);

return true;
}

std::string CShader::GetSourceWithLineNumbers() const
{
int i{1};
auto lines = StringUtils::Split(m_source, "\n");
for (auto& line : lines)
{
line.insert(0, StringUtils::Format("%3d: ", i));
i++;
}

auto output = StringUtils::Join(lines, "\n");

return output;
}


//////////////////////////////////////////////////////////////////////
// CGLSLVertexShader
//////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -254,15 +279,17 @@ bool CGLSLShaderProgram::CompileAndLink()
// compiled vertex shader
if (!m_pVP->Compile())
{
CLog::Log(LOGERROR, "GL: Error compiling vertex shader");
CLog::Log(LOGERROR, "GL: Error compiling vertex shader: {}", m_pVP->GetName());
CLog::Log(LOGDEBUG, "GL: vertex shader source:\n{}", m_pVP->GetSourceWithLineNumbers());
return false;
}

// compile pixel shader
if (!m_pFP->Compile())
{
m_pVP->Free();
CLog::Log(LOGERROR, "GL: Error compiling fragment shader");
CLog::Log(LOGERROR, "GL: Error compiling fragment shader: {}", m_pFP->GetName());
CLog::Log(LOGDEBUG, "GL: fragment shader source:\n{}", m_pFP->GetSourceWithLineNumbers());
return false;
}

Expand Down
6 changes: 6 additions & 0 deletions xbmc/guilib/Shader.h
Expand Up @@ -32,11 +32,17 @@ namespace Shaders {
virtual bool InsertSource(const std::string& filename, const std::string& loc);
bool OK() const { return m_compiled; }

std::string GetName() const { return m_filenames; }
std::string GetSourceWithLineNumbers() const;

protected:
std::string m_source;
std::string m_lastLog;
std::vector<std::string> m_attr;
bool m_compiled = false;

private:
std::string m_filenames;
};


Expand Down
31 changes: 30 additions & 1 deletion xbmc/rendering/gles/RenderSystemGLES.cpp
Expand Up @@ -9,17 +9,22 @@
#include "guilib/DirtyRegion.h"
#include "windowing/GraphicContext.h"
#include "settings/AdvancedSettings.h"
#include "settings/SettingsComponent.h"
#include "RenderSystemGLES.h"
#include "rendering/MatrixGL.h"
#include "utils/log.h"
#include "utils/GLUtils.h"
#include "utils/log.h"
#include "utils/TimeUtils.h"
#include "utils/SystemInfo.h"
#include "utils/MathUtils.h"
#ifdef TARGET_POSIX
#include "XTimeUtils.h"
#endif

#if defined(TARGET_LINUX)
#include "utils/EGLUtils.h"
#endif

CRenderSystemGLES::CRenderSystemGLES()
: CRenderSystemBase()
{
Expand Down Expand Up @@ -73,6 +78,30 @@ bool CRenderSystemGLES::InitRenderSystem()

m_RenderExtensions += " ";

//! @todo remove TARGET_RASPBERRY_PI when Raspberry Pi updates their GL headers
#if defined(GL_KHR_debug) && defined(TARGET_LINUX) && !defined(TARGET_RASPBERRY_PI)
if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_openGlDebugging)
{
if (IsExtSupported("GL_KHR_debug"))
{
auto glDebugMessageCallback = CEGLUtils::GetRequiredProcAddress<PFNGLDEBUGMESSAGECALLBACKKHRPROC>("glDebugMessageCallbackKHR");
auto glDebugMessageControl = CEGLUtils::GetRequiredProcAddress<PFNGLDEBUGMESSAGECONTROLKHRPROC>("glDebugMessageControlKHR");

glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
glDebugMessageCallback(KODI::UTILS::GL::GlErrorCallback, nullptr);

// ignore shader compilation information
glDebugMessageControl(GL_DEBUG_SOURCE_SHADER_COMPILER_KHR, GL_DEBUG_TYPE_OTHER_KHR, GL_DONT_CARE, 0, nullptr, GL_FALSE);

CLog::Log(LOGDEBUG, "OpenGL(ES): debugging enabled");
}
else
{
CLog::Log(LOGDEBUG, "OpenGL(ES): debugging requested but the required extension isn't available (GL_KHR_debug)");
}
}
#endif

LogGraphicsInfo();

m_bRenderCreated = true;
Expand Down
4 changes: 4 additions & 0 deletions xbmc/settings/AdvancedSettings.cpp
Expand Up @@ -433,6 +433,8 @@ void CAdvancedSettings::Initialize()
m_extraLogEnabled = false;
m_extraLogLevels = 0;

m_openGlDebugging = false;

m_userAgent = g_sysinfo.GetUserAgent();

m_initialized = true;
Expand Down Expand Up @@ -1229,6 +1231,8 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
m_seekSteps.push_back(atoi((*it).c_str()));
}

XMLUtils::GetBoolean(pRootElement, "opengldebugging", m_openGlDebugging);

// load in the settings overrides
CServiceBroker::GetSettingsComponent()->GetSettings()->LoadHidden(pRootElement);
}
Expand Down
2 changes: 2 additions & 0 deletions xbmc/settings/AdvancedSettings.h
Expand Up @@ -381,6 +381,8 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
False to show at the bottom of video (default) */
bool m_videoAssFixedWorks;

bool m_openGlDebugging;

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


std::string m_userAgent;

private:
Expand Down
96 changes: 94 additions & 2 deletions xbmc/utils/EGLUtils.cpp
Expand Up @@ -17,6 +17,8 @@

#include <EGL/eglext.h>

#include <map>

namespace
{
//! @todo remove when Raspberry Pi updates their EGL headers
Expand All @@ -34,7 +36,7 @@ namespace
#endif

#define X(VAL) std::make_pair(VAL, #VAL)
std::array<std::pair<EGLint, const char*>, 32> eglAttributes =
std::map<EGLint, const char*> eglAttributes =
{
// please keep attributes in accordance to:
// https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetConfigAttrib.xhtml
Expand Down Expand Up @@ -71,8 +73,64 @@ std::array<std::pair<EGLint, const char*>, 32> eglAttributes =
X(EGL_TRANSPARENT_GREEN_VALUE),
X(EGL_TRANSPARENT_BLUE_VALUE)
};

std::map<EGLenum, const char*> eglErrors =
{
// please keep errors in accordance to:
// https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetError.xhtml
X(EGL_SUCCESS),
X(EGL_NOT_INITIALIZED),
X(EGL_BAD_ACCESS),
X(EGL_BAD_ALLOC),
X(EGL_BAD_ATTRIBUTE),
X(EGL_BAD_CONFIG),
X(EGL_BAD_CONTEXT),
X(EGL_BAD_CURRENT_SURFACE),
X(EGL_BAD_DISPLAY),
X(EGL_BAD_MATCH),
X(EGL_BAD_NATIVE_PIXMAP),
X(EGL_BAD_NATIVE_WINDOW),
X(EGL_BAD_PARAMETER),
X(EGL_BAD_SURFACE),
X(EGL_CONTEXT_LOST),
};

std::map<EGLint, const char*> eglErrorType =
{
//! @todo remove when Raspberry Pi updates their EGL headers
#if !defined(TARGET_RASPBERRY_PI)
X(EGL_DEBUG_MSG_CRITICAL_KHR),
X(EGL_DEBUG_MSG_ERROR_KHR),
X(EGL_DEBUG_MSG_WARN_KHR),
X(EGL_DEBUG_MSG_INFO_KHR),
#endif
};
#undef X

} // namespace

//! @todo remove when Raspberry Pi updates their EGL headers
#if !defined(TARGET_RASPBERRY_PI)
void EglErrorCallback(EGLenum error, const char *command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message)
{
std::string errorStr;
std::string typeStr;

auto eglError = eglErrors.find(error);
if (eglError != eglErrors.end())
{
errorStr = eglError->second;
}

auto eglType = eglErrorType.find(messageType);
if (eglType != eglErrorType.end())
{
typeStr = eglType->second;
}

CLog::Log(LOGDEBUG, "EGL Debugging:\nError: {}\nCommand: {}\nType: {}\nMessage: {}", errorStr, command, typeStr, message);
}
#endif

std::set<std::string> CEGLUtils::GetClientExtensions()
{
Expand Down Expand Up @@ -112,7 +170,16 @@ bool CEGLUtils::HasClientExtension(const std::string& name)

void CEGLUtils::LogError(const std::string& what)
{
CLog::Log(LOGERROR, "%s (EGL error %d)", what.c_str(), eglGetError());
EGLenum error = eglGetError();
std::string errorStr = StringUtils::Format("0x%04X", error);

auto eglError = eglErrors.find(error);
if (eglError != eglErrors.end())
{
errorStr = eglError->second;
}

CLog::Log(LOGERROR, "{} ({})", what.c_str(), errorStr);
}

CEGLContextUtils::CEGLContextUtils()
Expand All @@ -122,6 +189,22 @@ CEGLContextUtils::CEGLContextUtils()
CEGLContextUtils::CEGLContextUtils(EGLenum platform, std::string const& platformExtension)
: m_platform{platform}
{
//! @todo remove when Raspberry Pi updates their EGL headers
#if !defined(TARGET_RASPBERRY_PI)
if (CEGLUtils::HasClientExtension("EGL_KHR_debug"))
{
auto eglDebugMessageControl = CEGLUtils::GetRequiredProcAddress<PFNEGLDEBUGMESSAGECONTROLKHRPROC>("eglDebugMessageControlKHR");

EGLAttrib eglDebugAttribs[] = {EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE,
EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE,
EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE,
EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE,
EGL_NONE};

eglDebugMessageControl(EglErrorCallback, eglDebugAttribs);
}
#endif

m_platformSupported = CEGLUtils::HasClientExtension("EGL_EXT_platform_base") && CEGLUtils::HasClientExtension(platformExtension);
}

Expand Down Expand Up @@ -321,6 +404,15 @@ bool CEGLContextUtils::CreateContext(CEGLAttributesVec contextAttribs)
if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_IMG_context_priority"))
contextAttribs.Add({{EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG}});

//! @todo remove when Raspberry Pi updates their EGL headers
#if !defined(TARGET_RASPBERRY_PI)
if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_KHR_create_context") &&
CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_openGlDebugging)
{
contextAttribs.Add({{EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR}});
}
#endif

m_eglContext = eglCreateContext(m_eglDisplay, eglConfig,
EGL_NO_CONTEXT, contextAttribs.Get());

Expand Down