mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 11:09:37 -06:00
Feature/opengldebug (#290)
* Add InLIstVerifier * Initial implementation of OpenGL debug messages * Moving functionality into Ghoul * Compile fix * Update Ghoul repository Make use of the moved OpenGL debug functions * Update Ghoul to fix GCC and Clang compiler errors * Add unit test for IntListVerifier
This commit is contained in:
Submodule ext/ghoul updated: 9788308e69...598d54bc70
@@ -216,6 +216,19 @@ struct StringListVerifier : public TableVerifier {
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Verifier that checks whether all values contained in a Table are of type \c int.
|
||||
*/
|
||||
struct IntListVerifier : public TableVerifier {
|
||||
/**
|
||||
* Constructor for a IntListVerifier.
|
||||
* \param elementDocumentation The documentation for each string in the list
|
||||
*/
|
||||
IntListVerifier(std::string elementDocumentation = "");
|
||||
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// Vector verifiers
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@@ -126,7 +126,22 @@ public:
|
||||
static const std::string PartHttpProxyUser;
|
||||
/// The key that stores the password to use for authentication to access the http proxy
|
||||
static const std::string PartHttpProxyPassword;
|
||||
|
||||
/// The key that stores the dictionary containing information about debug contexts
|
||||
static const std::string KeyOpenGLDebugContext;
|
||||
/// The part of the key storing whether an OpenGL Debug context should be created
|
||||
static const std::string PartActivate;
|
||||
/// The part of the key storing whether the debug callbacks are performed synchronous
|
||||
static const std::string PartSynchronous;
|
||||
/// The part of the key storing a list of identifiers that should be filtered out
|
||||
static const std::string PartFilterIdentifier;
|
||||
/// The part of the key that stores the source of the ignored identifier
|
||||
static const std::string PartFilterIdentifierSource;
|
||||
/// The part of the key that stores the type of the ignored identifier
|
||||
static const std::string PartFilterIdentifierType;
|
||||
/// The part of the key that stores the identifier of the ignored identifier
|
||||
static const std::string PartFilterIdentifierIdentifier;
|
||||
/// The part of the key storing a list of severities that should be filtered out
|
||||
static const std::string PartFilterSeverity;
|
||||
|
||||
/**
|
||||
* Iteratively walks the directory structure starting with \p filename to find the
|
||||
|
||||
@@ -90,6 +90,14 @@ return {
|
||||
-- DisableRenderingOnMaster = true,
|
||||
KeyDisableSceneOnMaster = true,
|
||||
DownloadRequestURL = "http://data.openspaceproject.com/request.cgi",
|
||||
RenderingMethod = "Framebuffer"
|
||||
RenderingMethod = "Framebuffer",
|
||||
OpenGLDebugContext = {
|
||||
Activate = true,
|
||||
FilterIdentifier = {
|
||||
{ Type = "Other", Source = "API", Identifier = 131185 }
|
||||
},
|
||||
-- FilterSeverity = { }
|
||||
|
||||
}
|
||||
--RenderingMethod = "ABuffer" -- alternative: "Framebuffer"
|
||||
}
|
||||
|
||||
@@ -206,6 +206,14 @@ std::string StringListVerifier::type() const {
|
||||
return "List of strings";
|
||||
}
|
||||
|
||||
IntListVerifier::IntListVerifier(std::string elementDocumentation)
|
||||
: TableVerifier({ { "*", new IntVerifier, std::move(elementDocumentation) } })
|
||||
{}
|
||||
|
||||
std::string IntListVerifier::type() const {
|
||||
return "List of ints";
|
||||
}
|
||||
|
||||
ReferencingVerifier::ReferencingVerifier(std::string id)
|
||||
: identifier(std::move(id))
|
||||
{
|
||||
|
||||
@@ -87,6 +87,15 @@ const string ConfigurationManager::PartHttpProxyAuthentication = "Authentication
|
||||
const string ConfigurationManager::PartHttpProxyUser = "User";
|
||||
const string ConfigurationManager::PartHttpProxyPassword = "Password";
|
||||
|
||||
const string ConfigurationManager::KeyOpenGLDebugContext = "OpenGLDebugContext";
|
||||
const string ConfigurationManager::PartActivate = "Activate";
|
||||
const string ConfigurationManager::PartSynchronous = "Synchronous";
|
||||
const string ConfigurationManager::PartFilterIdentifier = "FilterIdentifier";
|
||||
const string ConfigurationManager::PartFilterIdentifierSource = "Source";
|
||||
const string ConfigurationManager::PartFilterIdentifierType = "Type";
|
||||
const string ConfigurationManager::PartFilterIdentifierIdentifier = "Identifier";
|
||||
const string ConfigurationManager::PartFilterSeverity = "PartFilterSeverity";
|
||||
|
||||
string ConfigurationManager::findConfiguration(const string& filename) {
|
||||
using ghoul::filesystem::Directory;
|
||||
|
||||
|
||||
@@ -385,7 +385,80 @@ documentation::Documentation ConfigurationManager::Documentation() {
|
||||
"This defines the use for a proxy when fetching data over http."
|
||||
"No proxy will be used if this is left out.",
|
||||
Optional::Yes
|
||||
}
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyOpenGLDebugContext,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartActivate,
|
||||
new BoolVerifier,
|
||||
"Determines whether the OpenGL context should be a debug context",
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartSynchronous,
|
||||
new BoolVerifier,
|
||||
"Determines whether the OpenGL debug callbacks are performed "
|
||||
"synchronously. If set to <True> the callbacks are in the same thead "
|
||||
"as the context and in the scope of the OpenGL function that "
|
||||
"triggered the message. The default value is <True>.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFilterIdentifier,
|
||||
new TableVerifier({{
|
||||
"*",
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartFilterIdentifierIdentifier,
|
||||
new IntVerifier,
|
||||
"The identifier that is to be filtered",
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFilterIdentifierSource,
|
||||
new StringInListVerifier({
|
||||
// Taken from ghoul::debugcontext.cpp
|
||||
"API", "Window System", "Shader Compiler",
|
||||
"Third Party", "Application", "Other", "Don't care"
|
||||
}),
|
||||
"The source of the identifier to be filtered",
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFilterIdentifierType,
|
||||
new StringInListVerifier({
|
||||
// Taken from ghoul::debugcontext.cpp
|
||||
"Error", "Deprecated", "Undefined", "Portability",
|
||||
"Performance", "Marker", "Push group", "Pop group",
|
||||
"Other", "Don't care"
|
||||
}),
|
||||
"The type of the identifier to be filtered"
|
||||
}
|
||||
}),
|
||||
"Individual OpenGL debug message identifiers"
|
||||
}}),
|
||||
"A list of OpenGL debug messages identifiers that are filtered",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFilterSeverity,
|
||||
new TableVerifier({
|
||||
{
|
||||
"*",
|
||||
new StringInListVerifier(
|
||||
// ghoul::debugcontext.cpp
|
||||
{ "High", "Medium", "Low", "Notification" }
|
||||
)
|
||||
}
|
||||
}),
|
||||
"A list of severities that can are filtered out",
|
||||
Optional::Yes
|
||||
}
|
||||
}),
|
||||
"Determines the settings for the creation of an OpenGL debug context.",
|
||||
Optional::Yes
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/logging/consolelog.h>
|
||||
#include <ghoul/logging/visualstudiooutputlog.h>
|
||||
#include <ghoul/opengl/debugcontext.h>
|
||||
#include <ghoul/systemcapabilities/systemcapabilities>
|
||||
|
||||
|
||||
@@ -907,6 +908,111 @@ void OpenSpaceEngine::configureLogging() {
|
||||
void OpenSpaceEngine::initializeGL() {
|
||||
LTRACE("OpenSpaceEngine::initializeGL(begin)");
|
||||
|
||||
const std::string key = ConfigurationManager::KeyOpenGLDebugContext;
|
||||
if (_configurationManager->hasKey(key)) {
|
||||
ghoul::Dictionary dict = _configurationManager->value<ghoul::Dictionary>(key);
|
||||
bool debug = dict.value<bool>(ConfigurationManager::PartActivate);
|
||||
|
||||
// Debug output is not available before 4.3
|
||||
const ghoul::systemcapabilities::Version minVersion = { 4, 3, 0 };
|
||||
if (OpenGLCap.openGLVersion() < minVersion) {
|
||||
LINFO("OpenGL Debug context requested, but insufficient version available");
|
||||
debug = false;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
using namespace ghoul::opengl::debug;
|
||||
|
||||
bool synchronous = true;
|
||||
if (dict.hasKey(ConfigurationManager::PartSynchronous)) {
|
||||
synchronous = dict.value<bool>(ConfigurationManager::PartSynchronous);
|
||||
}
|
||||
|
||||
setDebugOutput(DebugOutput(debug), SynchronousOutput(synchronous));
|
||||
|
||||
|
||||
if (dict.hasKey(ConfigurationManager::PartFilterIdentifier)) {
|
||||
ghoul::Dictionary filterDict = dict.value<ghoul::Dictionary>(
|
||||
ConfigurationManager::PartFilterIdentifier
|
||||
);
|
||||
|
||||
for (int i = 1; i <= filterDict.size(); ++i) {
|
||||
ghoul::Dictionary id = filterDict.value<ghoul::Dictionary>(
|
||||
std::to_string(i)
|
||||
);
|
||||
|
||||
const unsigned int identifier = static_cast<unsigned int>(
|
||||
id.value<double>(
|
||||
ConfigurationManager::PartFilterIdentifierIdentifier
|
||||
)
|
||||
);
|
||||
|
||||
const std::string s = id.value<std::string>(
|
||||
ConfigurationManager::PartFilterIdentifierSource
|
||||
);
|
||||
|
||||
const std::string t = id.value<std::string>(
|
||||
ConfigurationManager::PartFilterIdentifierType
|
||||
);
|
||||
|
||||
setDebugMessageControl(
|
||||
ghoul::from_string<Source>(s),
|
||||
ghoul::from_string<Type>(t),
|
||||
{ identifier },
|
||||
Enabled::No
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (dict.hasKey(ConfigurationManager::PartFilterSeverity)) {
|
||||
ghoul::Dictionary filterDict = dict.value<ghoul::Dictionary>(
|
||||
ConfigurationManager::PartFilterIdentifier
|
||||
);
|
||||
|
||||
for (int i = 1; i <= filterDict.size(); ++i) {
|
||||
std::string severity = filterDict.value<std::string>(
|
||||
std::to_string(i)
|
||||
);
|
||||
|
||||
setDebugMessageControl(
|
||||
Source::DontCare,
|
||||
Type::DontCare,
|
||||
ghoul::from_string<Severity>(severity),
|
||||
Enabled::No
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
auto callback = [](Source source, Type type, Severity severity,
|
||||
unsigned int id, std::string message) -> void
|
||||
{
|
||||
const std::string s = std::to_string(source);
|
||||
const std::string t = std::to_string(type);
|
||||
|
||||
const std::string category =
|
||||
"OpenGL (" + s + ") [" + t + "] {" + std::to_string(id) + "}";
|
||||
switch (severity) {
|
||||
case Severity::High:
|
||||
LERRORC(category, std::string(message));
|
||||
break;
|
||||
case Severity::Medium:
|
||||
LWARNINGC(category, std::string(message));
|
||||
break;
|
||||
case Severity::Low:
|
||||
LINFOC(category, std::string(message));
|
||||
break;
|
||||
case Severity::Notification:
|
||||
LDEBUGC(category, std::string(message));
|
||||
break;
|
||||
default:
|
||||
ghoul_assert(false, "Missing case label");
|
||||
}
|
||||
};
|
||||
ghoul::opengl::debug::setDebugCallback(callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LINFO("Initializing Rendering Engine");
|
||||
// @CLEANUP: Remove the return statement and replace with exceptions ---abock
|
||||
_renderEngine->initializeGL();
|
||||
|
||||
@@ -80,6 +80,9 @@ TEST_F(DocumentationTest, Constructor) {
|
||||
doc.entries.emplace_back("NotInListInt", new IntNotInListVerifier({ 0, 1 }));
|
||||
doc.entries.emplace_back("NotInListString", new StringNotInListVerifier({ "", "a" }));
|
||||
|
||||
doc.entries.emplace_back("StringListVerifier", new StringListVerifier);
|
||||
doc.entries.emplace_back("IntListVerifier", new IntListVerifier);
|
||||
|
||||
// Range Verifiers
|
||||
doc.entries.emplace_back("InListDouble", new DoubleInRangeVerifier({ 0.0, 1.0 }));
|
||||
doc.entries.emplace_back("InListInt", new IntInRangeVerifier({ 0, 1 }));
|
||||
@@ -393,6 +396,63 @@ TEST_F(DocumentationTest, StringListVerifierType) {
|
||||
EXPECT_EQ(TestResult::Offense::Reason::MissingKey, negativeRes.offenses[0].reason);
|
||||
}
|
||||
|
||||
TEST_F(DocumentationTest, IntListVerifierType) {
|
||||
using namespace openspace::documentation;
|
||||
using namespace std::string_literals;
|
||||
|
||||
Documentation doc {
|
||||
{ { "IntList", new IntListVerifier } }
|
||||
};
|
||||
|
||||
ghoul::Dictionary positive {
|
||||
{
|
||||
"IntList",
|
||||
ghoul::Dictionary{
|
||||
{ "1", 1 },
|
||||
{ "2", 2 },
|
||||
{ "3", 3 }
|
||||
}
|
||||
}
|
||||
};
|
||||
TestResult positiveRes = testSpecification(doc, positive);
|
||||
EXPECT_TRUE(positiveRes.success);
|
||||
EXPECT_EQ(0, positiveRes.offenses.size());
|
||||
|
||||
ghoul::Dictionary negative{
|
||||
{ "IntList", 0 }
|
||||
};
|
||||
TestResult negativeRes = testSpecification(doc, negative);
|
||||
EXPECT_FALSE(negativeRes.success);
|
||||
ASSERT_EQ(1, negativeRes.offenses.size());
|
||||
EXPECT_EQ("IntList", negativeRes.offenses[0].offender);
|
||||
EXPECT_EQ(TestResult::Offense::Reason::WrongType, negativeRes.offenses[0].reason);
|
||||
|
||||
ghoul::Dictionary negative2 {
|
||||
{
|
||||
"IntList",
|
||||
ghoul::Dictionary{
|
||||
{ "1", "a"s },
|
||||
{ "2", 1 },
|
||||
{ "3", 2 }
|
||||
}
|
||||
}
|
||||
};
|
||||
negativeRes = testSpecification(doc, negative2);
|
||||
EXPECT_FALSE(negativeRes.success);
|
||||
ASSERT_EQ(1, negativeRes.offenses.size());
|
||||
EXPECT_EQ("IntList.1", negativeRes.offenses[0].offender);
|
||||
EXPECT_EQ(TestResult::Offense::Reason::WrongType, negativeRes.offenses[0].reason);
|
||||
|
||||
ghoul::Dictionary negativeExist {
|
||||
{ "IntList2", ghoul::Dictionary{} }
|
||||
};
|
||||
negativeRes = testSpecification(doc, negativeExist);
|
||||
EXPECT_FALSE(negativeRes.success);
|
||||
ASSERT_EQ(1, negativeRes.offenses.size());
|
||||
EXPECT_EQ("IntList", negativeRes.offenses[0].offender);
|
||||
EXPECT_EQ(TestResult::Offense::Reason::MissingKey, negativeRes.offenses[0].reason);
|
||||
}
|
||||
|
||||
TEST_F(DocumentationTest, MixedVerifiers) {
|
||||
using namespace openspace::documentation;
|
||||
using namespace std::string_literals;
|
||||
|
||||
Reference in New Issue
Block a user