Browse Source

Audio: make it possible to disable OpenAL extensions as well.

Finally, a feature parity.
pull/364/head
Vladimír Vondruš 7 years ago
parent
commit
8af19f21f0
  1. 45
      src/Magnum/Audio/Context.cpp
  2. 32
      src/Magnum/Audio/Context.h
  3. 45
      src/Magnum/Audio/Test/ContextALTest.cpp
  4. 2
      src/Magnum/Audio/al-info.cpp
  5. 12
      src/Magnum/GL/Context.cpp
  6. 2
      src/Magnum/GL/Context.h

45
src/Magnum/Audio/Context.cpp

@ -128,10 +128,16 @@ Context::Context(NoCreateT, Int argc, const char** argv) noexcept: _device{}, _c
Utility::Arguments args{"magnum", Utility::Arguments args{"magnum",
Utility::Arguments::Flag::IgnoreUnknownOptions}; Utility::Arguments::Flag::IgnoreUnknownOptions};
args.addOption("log", "default").setHelp("log", "console logging", "default|quiet|verbose") args.addOption("log", "default").setHelp("log", "console logging", "default|quiet|verbose")
.addOption("disable-extensions").setHelp("disable-extensions", "API extensions to disable", "LIST")
.setFromEnvironment("log") .setFromEnvironment("log")
.parse(argc, argv); .parse(argc, argv);
/* Decide how to display initialization log */
_displayInitializationLog = !(args.value("log") == "quiet" || args.value("log") == "QUIET"); _displayInitializationLog = !(args.value("log") == "quiet" || args.value("log") == "QUIET");
/* Disable extensions */
for(auto&& extension: Utility::String::splitWithoutEmptyParts(args.value("disable-extensions")))
_disabledExtensionStrings.push_back(extension);
} }
void Context::create(const Configuration& configuration) { void Context::create(const Configuration& configuration) {
@ -211,14 +217,43 @@ bool Context::tryCreate(const Configuration& configuration) {
const auto found = extensionMap.find(extension); const auto found = extensionMap.find(extension);
if(found != extensionMap.end()) { if(found != extensionMap.end()) {
_supportedExtensions.push_back(found->second); _supportedExtensions.push_back(found->second);
_extensionStatus.set(found->second.index()); _extensionStatus.set(found->second.index(), true);
} }
} }
if(_displayInitializationLog) { std::ostream* output = _displayInitializationLog ? Debug::output() : nullptr;
/* Print some info */
Debug() << "Audio Renderer:" << rendererString() << "by" << vendorString(); /* Print some info */
Debug() << "OpenAL version:" << versionString(); Debug{output} << "Audio renderer:" << rendererString() << "by" << vendorString();
Debug{output} << "OpenAL version:" << versionString();
/* Disable extensions as requested by the user */
if(!_disabledExtensionStrings.empty()) {
bool headerPrinted = false;
/* Disable extensions that are known and supported and print a message
for each */
for(auto&& extension: _disabledExtensionStrings) {
auto found = extensionMap.find(extension);
/* No error message here because some of the extensions could be
from Vulkan or OpenGL. That also means we print the header only
when we actually have something to say */
if(found == extensionMap.end()) continue;
/* If the extension isn't supported in the first place, don't do
anything. If it is, set its status as unsupported but flip the
corresponding bit in the disabled bitmap so we know it is
supported and only got disabled */
if(!_extensionStatus[found->second.index()]) continue;
_extensionStatus.set(found->second.index(), false);
_disabledExtensions.set(found->second.index(), true);
if(!headerPrinted) {
Debug{output} << "Disabling extensions:";
headerPrinted = true;
}
Debug{output} << " " << extension;
}
} }
return true; return true;

32
src/Magnum/Audio/Context.h

@ -43,6 +43,7 @@
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/Audio/visibility.h" #include "Magnum/Audio/visibility.h"
#include "Magnum/Math/BoolVector.h"
#include "MagnumExternal/OpenAL/extensions.h" #include "MagnumExternal/OpenAL/extensions.h"
namespace Magnum { namespace Audio { namespace Magnum { namespace Audio {
@ -91,13 +92,16 @@ The context is configurable through command-line options, that can be passed
for example from the `Platform::*Application` classes. Usage: for example from the `Platform::*Application` classes. Usage:
@code{.sh} @code{.sh}
<application> [--magnum-help] [--magnum-log default|quiet|verbose] ... <application> [--magnum-help] [--magnum-disable-extensions LIST]
[--magnum-log default|quiet|verbose] ...
@endcode @endcode
Arguments: Arguments:
- `...` --- main application arguments (see `-h` or `--help` for details) - `...` --- main application arguments (see `-h` or `--help` for details)
- `--magnum-help` --- display this help message and exit - `--magnum-help` --- display this help message and exit
- `--magnum-disable-extensions LIST` --- API extensions to disable
(environment: `MAGNUM_DISABLE_EXTENSIONS`)
- `--magnum-log default|quiet|verbose` --- console logging - `--magnum-log default|quiet|verbose` --- console logging
(environment: `MAGNUM_LOG`) (default: `default`) (environment: `MAGNUM_LOG`) (default: `default`)
@ -380,6 +384,28 @@ class MAGNUM_AUDIO_EXPORT Context {
return _extensionStatus[extension.index()]; return _extensionStatus[extension.index()];
} }
/**
* @brief Whether given extension is disabled
*
* Can be used for detecting driver bug workarounds. Disabled
* extensions return @cpp false @ce in @ref isExtensionSupported() even
* if they are advertised as being supported by the driver.
*/
template<class T> bool isExtensionDisabled() const {
return _disabledExtensions[T::Index];
}
/**
* @brief Whether given extension is disabled
*
* Can be used e.g. for listing extensions available on current
* hardware, but for general usage prefer @ref isExtensionDisabled() const,
* as it does most operations in compile time.
*/
bool isExtensionDisabled(const Extension& extension) const {
return _disabledExtensions[extension.index()];
}
private: private:
MAGNUM_AUDIO_LOCAL static Context* _current; MAGNUM_AUDIO_LOCAL static Context* _current;
@ -388,8 +414,10 @@ class MAGNUM_AUDIO_EXPORT Context {
ALCdevice* _device; ALCdevice* _device;
ALCcontext* _context; ALCcontext* _context;
std::bitset<Implementation::ExtensionCount> _extensionStatus; Math::BoolVector<Implementation::ExtensionCount> _extensionStatus;
Math::BoolVector<Implementation::ExtensionCount> _disabledExtensions;
std::vector<Extension> _supportedExtensions; std::vector<Extension> _supportedExtensions;
std::vector<std::string> _disabledExtensionStrings;
}; };
/** /**

45
src/Magnum/Audio/Test/ContextALTest.cpp

@ -43,7 +43,9 @@ struct ContextALTest: TestSuite::Tester {
void ignoreUnrelatedOptions(); void ignoreUnrelatedOptions();
void extensionsString(); void extensionsString();
void isExtensionEnabled(); void isExtensionSupported();
void isExtensionUnsupported();
void isExtensionDisabled();
}; };
ContextALTest::ContextALTest(): ContextALTest::ContextALTest():
@ -57,7 +59,9 @@ ContextALTest::ContextALTest():
addTests({&ContextALTest::ignoreUnrelatedOptions, addTests({&ContextALTest::ignoreUnrelatedOptions,
&ContextALTest::extensionsString, &ContextALTest::extensionsString,
&ContextALTest::isExtensionEnabled}); &ContextALTest::isExtensionSupported,
&ContextALTest::isExtensionUnsupported,
&ContextALTest::isExtensionDisabled});
} }
void ContextALTest::construct() { void ContextALTest::construct() {
@ -110,10 +114,43 @@ void ContextALTest::extensionsString() {
CORRADE_VERIFY(!extensions.empty()); CORRADE_VERIFY(!extensions.empty());
} }
void ContextALTest::isExtensionEnabled() { void ContextALTest::isExtensionSupported() {
Context context; Context context;
CORRADE_VERIFY(context.isExtensionSupported<Extensions::ALC::EXT::ENUMERATION>());
CORRADE_VERIFY(!context.isExtensionDisabled<Extensions::ALC::EXT::ENUMERATION>());
CORRADE_VERIFY(Context::current().isExtensionSupported<Extensions::ALC::EXT::ENUMERATION>()); Extension e{Extensions::ALC::EXT::ENUMERATION::Index,
Extensions::ALC::EXT::ENUMERATION::string()};
CORRADE_VERIFY(context.isExtensionSupported(e));
CORRADE_VERIFY(!context.isExtensionDisabled(e));
}
void ContextALTest::isExtensionUnsupported() {
Context context;
if(context.isExtensionSupported<Extensions::ALC::SOFTX::HRTF>())
CORRADE_SKIP("Extension" + std::string{Extensions::ALC::SOFTX::HRTF::string()} + " is supported, can't test.");
CORRADE_VERIFY(!context.isExtensionSupported<Extensions::ALC::SOFTX::HRTF>());
CORRADE_VERIFY(!context.isExtensionDisabled<Extensions::ALC::SOFTX::HRTF>());
Extension e{Extensions::ALC::SOFTX::HRTF::Index,
Extensions::ALC::SOFTX::HRTF::string()};
CORRADE_VERIFY(!context.isExtensionSupported(e));
CORRADE_VERIFY(!context.isExtensionDisabled(e));
}
void ContextALTest::isExtensionDisabled() {
/* Yes, FFS. this is a weird-ass name */
const char* argv[] = { "", "--magnum-disable-extensions", "ALC_ENUMERATION_EXT" };
Context context{Containers::arraySize(argv), argv};
CORRADE_VERIFY(!context.isExtensionSupported<Extensions::ALC::EXT::ENUMERATION>());
CORRADE_VERIFY(context.isExtensionDisabled<Extensions::ALC::EXT::ENUMERATION>());
Extension e{Extensions::ALC::EXT::ENUMERATION::Index,
Extensions::ALC::EXT::ENUMERATION::string()};
CORRADE_VERIFY(!context.isExtensionSupported(e));
CORRADE_VERIFY(context.isExtensionDisabled(e));
} }
}}}} }}}}

2
src/Magnum/Audio/al-info.cpp

@ -140,6 +140,8 @@ int main(const int argc, const char** const argv) {
d << " " << extensionName << std::string(60-extensionName.size(), ' '); d << " " << extensionName << std::string(60-extensionName.size(), ' ');
if(c.isExtensionSupported(extension)) if(c.isExtensionSupported(extension))
d << "SUPPORTED"; d << "SUPPORTED";
else if(c.isExtensionDisabled(extension))
d << " removed";
else else
d << " -"; d << " -";
} }

12
src/Magnum/GL/Context.cpp

@ -465,7 +465,7 @@ Context::Context(NoCreateT, Utility::Arguments& args, Int argc, const char** arg
CORRADE_INTERNAL_ASSERT(args.prefix() == "magnum"); CORRADE_INTERNAL_ASSERT(args.prefix() == "magnum");
args.addOption("disable-workarounds") args.addOption("disable-workarounds")
.setHelp("disable-workarounds", "driver workarounds to disable\n (see https://doc.magnum.graphics/magnum/opengl-workarounds.html for detailed info)", "LIST") .setHelp("disable-workarounds", "driver workarounds to disable\n (see https://doc.magnum.graphics/magnum/opengl-workarounds.html for detailed info)", "LIST")
.addOption("disable-extensions").setHelp("disable-extensions", "OpenGL extensions to disable", "LIST") .addOption("disable-extensions").setHelp("disable-extensions", "API extensions to disable", "LIST")
.addOption("gpu-validation", "off").setHelp("gpu-validation", "GPU validation using KHR_debug (if present)", "off|on") .addOption("gpu-validation", "off").setHelp("gpu-validation", "GPU validation using KHR_debug (if present)", "off|on")
.addOption("log", "default").setHelp("log", "console logging", "default|quiet|verbose") .addOption("log", "default").setHelp("log", "console logging", "default|quiet|verbose")
.setFromEnvironment("disable-workarounds") .setFromEnvironment("disable-workarounds")
@ -713,7 +713,7 @@ bool Context::tryCreate() {
/* Disable extensions as requested by the user */ /* Disable extensions as requested by the user */
if(!_disabledExtensions.empty()) { if(!_disabledExtensions.empty()) {
Debug{output} << "Disabling extensions:"; bool headerPrinted = false;
/* Put remaining extensions into the hashmap for faster lookup */ /* Put remaining extensions into the hashmap for faster lookup */
std::unordered_map<std::string, Extension> allExtensions{std::move(futureExtensions)}; std::unordered_map<std::string, Extension> allExtensions{std::move(futureExtensions)};
@ -725,10 +725,16 @@ bool Context::tryCreate() {
for each */ for each */
for(auto&& extension: _disabledExtensions) { for(auto&& extension: _disabledExtensions) {
auto found = allExtensions.find(extension); auto found = allExtensions.find(extension);
/** @todo Error message here? I should not clutter the output at this point */ /* No error message here because some of the extensions could be
from Vulkan or OpenAL. That also means we print the header only
when we actually have something to say */
if(found == allExtensions.end()) continue; if(found == allExtensions.end()) continue;
_extensionRequiredVersion[found->second.index()] = Version::None; _extensionRequiredVersion[found->second.index()] = Version::None;
if(!headerPrinted) {
Debug{output} << "Disabling extensions:";
headerPrinted = true;
}
Debug{output} << " " << extension; Debug{output} << " " << extension;
} }
} }

2
src/Magnum/GL/Context.h

@ -134,7 +134,7 @@ Arguments:
- `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see - `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see
@ref opengl-workarounds for detailed info) (environment: @ref opengl-workarounds for detailed info) (environment:
`MAGNUM_DISABLE_WORKAROUNDS`) `MAGNUM_DISABLE_WORKAROUNDS`)
- `--magnum-disable-extensions LIST` --- OpenGL extensions to disable - `--magnum-disable-extensions LIST` --- API extensions to disable
(environment: `MAGNUM_DISABLE_EXTENSIONS`) (environment: `MAGNUM_DISABLE_EXTENSIONS`)
- `--magnum-gpu-validation off|on` --- GPU validation using - `--magnum-gpu-validation off|on` --- GPU validation using
@gl_extension{KHR,debug}, if present (environment: @gl_extension{KHR,debug}, if present (environment:

Loading…
Cancel
Save