Browse Source

GL,Audio: use plain old binary search for extension setup.

Because the cost of hundreds of tiny allocations when filling a
std::unordered_map (and then the cache unfriendliness of the whole
thing) definitely overweights the potential speedup by searching in O(1)
instead of O(log n). Same approach is chosen in the upcoming Vulkan
wrapper, I just backported it here.

This strips about 8 kB off the Emscripten build.
pull/454/head
Vladimír Vondruš 6 years ago
parent
commit
e2621fac3c
  1. 28
      src/Magnum/Audio/Context.cpp
  2. 270
      src/Magnum/GL/Context.cpp

28
src/Magnum/Audio/Context.cpp

@ -27,12 +27,10 @@
#include "Context.h" #include "Context.h"
#include <unordered_map>
#include <al.h> #include <al.h>
#include <alc.h> #include <alc.h>
#include <cstring> #include <cstring>
#include <algorithm>
#include <Corrade/Utility/Arguments.h> #include <Corrade/Utility/Arguments.h>
#include <Corrade/Utility/Assert.h> #include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/Debug.h>
@ -270,18 +268,13 @@ bool Context::tryCreate(const Configuration& configuration) {
alcMakeContextCurrent(_context); alcMakeContextCurrent(_context);
currentContext = this; currentContext = this;
/* Add all extensions to a map for faster lookup */
std::unordered_map<std::string, Extension> extensionMap;
for(const Extension& extension: Extension::extensions())
extensionMap.emplace(extension.string(), extension);
/* Check for presence of extensions */ /* Check for presence of extensions */
const std::vector<std::string> extensions = extensionStrings(); const std::vector<std::string> extensions = extensionStrings();
for(const std::string& extension: extensions) { for(const std::string& extension: extensions) {
const auto found = extensionMap.find(extension); const auto found = std::lower_bound(std::begin(ExtensionList), std::end(ExtensionList), extension, [](const Extension& a, const std::string& b) { return a.string() < b; });
if(found != extensionMap.end()) { if(found != std::end(ExtensionList) && found->string() == extension) {
_supportedExtensions.push_back(found->second); _supportedExtensions.push_back(*found);
_extensionStatus.set(found->second.index(), true); _extensionStatus.set(found->index(), true);
} }
} }
@ -298,19 +291,20 @@ bool Context::tryCreate(const Configuration& configuration) {
/* Disable extensions that are known and supported and print a message /* Disable extensions that are known and supported and print a message
for each */ for each */
for(auto&& extension: _disabledExtensionStrings) { for(auto&& extension: _disabledExtensionStrings) {
auto found = extensionMap.find(extension); const auto found = std::lower_bound(std::begin(ExtensionList), std::end(ExtensionList), extension, [](const Extension& a, const std::string& b) { return a.string() < b; });
/* No error message here because some of the extensions could be /* No error message here because some of the extensions could be
from Vulkan or OpenGL. That also means we print the header only from Vulkan or OpenGL. That also means we print the header only
when we actually have something to say */ when we actually have something to say */
if(found == extensionMap.end()) continue; if(found == std::end(ExtensionList) || found->string() != extension)
continue;
/* If the extension isn't supported in the first place, don't do /* 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 anything. If it is, set its status as unsupported but flip the
corresponding bit in the disabled bitmap so we know it is corresponding bit in the disabled bitmap so we know it is
supported and only got disabled */ supported and only got disabled */
if(!_extensionStatus[found->second.index()]) continue; if(!_extensionStatus[found->index()]) continue;
_extensionStatus.set(found->second.index(), false); _extensionStatus.set(found->index(), false);
_disabledExtensions.set(found->second.index(), true); _disabledExtensions.set(found->index(), true);
if(!headerPrinted) { if(!headerPrinted) {
Debug{output} << "Disabling extensions:"; Debug{output} << "Disabling extensions:";

270
src/Magnum/GL/Context.cpp

@ -25,12 +25,9 @@
#include "Context.h" #include "Context.h"
#ifndef MAGNUM_TARGET_GLES #include <algorithm>
#include <algorithm> /* std::find in isCoreProfileImplementationNV() */
#endif
#include <iostream> /* for initialization log redirection */ #include <iostream> /* for initialization log redirection */
#include <string> #include <string>
#include <unordered_map>
#include <Corrade/Containers/EnumSet.hpp> #include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Utility/Arguments.h> #include <Corrade/Utility/Arguments.h>
#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/Debug.h>
@ -71,9 +68,9 @@
namespace Magnum { namespace GL { namespace Magnum { namespace GL {
/* When adding a new list, Extension::extensions() needs to be adapted. Binary /* When adding a new list, Extension::extensions() and Context::Context() needs
search is performed on the extensions, thus they have to be sorted to be adapted. Binary search is performed on the extensions, thus they have
alphabetically. */ to be sorted alphabetically. */
namespace { namespace {
#define _extension(vendor, extension) \ #define _extension(vendor, extension) \
@ -260,49 +257,53 @@ constexpr Extension ExtensionList460[]{
_extension(KHR,no_error)}; _extension(KHR,no_error)};
#elif defined(MAGNUM_TARGET_WEBGL) #elif defined(MAGNUM_TARGET_WEBGL)
constexpr Extension ExtensionList[]{ constexpr Extension ExtensionList[]{
_extension(EXT,texture_filter_anisotropic), #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,clip_cull_distance),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,color_buffer_float),
#endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(EXT,disjoint_timer_query), _extension(EXT,disjoint_timer_query),
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,color_buffer_float),
_extension(EXT,disjoint_timer_query_webgl2), _extension(EXT,disjoint_timer_query_webgl2),
#endif #endif
_extension(EXT,texture_compression_rgtc),
_extension(EXT,texture_compression_bptc),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,clip_cull_distance),
_extension(EXT,draw_buffers_indexed), _extension(EXT,draw_buffers_indexed),
#endif #endif
_extension(EXT,texture_compression_bptc),
_extension(EXT,texture_compression_rgtc),
_extension(EXT,texture_filter_anisotropic),
_extension(OES,texture_float_linear), _extension(OES,texture_float_linear),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(OVR,multiview2), _extension(OVR,multiview2),
#endif #endif
_extension(WEBGL,compressed_texture_s3tc),
_extension(WEBGL,compressed_texture_pvrtc),
_extension(WEBGL,compressed_texture_astc), _extension(WEBGL,compressed_texture_astc),
_extension(WEBGL,compressed_texture_pvrtc),
_extension(WEBGL,compressed_texture_s3tc),
_extension(WEBGL,compressed_texture_s3tc_srgb)}; _extension(WEBGL,compressed_texture_s3tc_srgb)};
constexpr Extension ExtensionListES300[]{ constexpr Extension ExtensionListES300[]{
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(ANGLE,instanced_arrays), _extension(ANGLE,instanced_arrays),
_extension(EXT,blend_minmax),
_extension(EXT,color_buffer_half_float), _extension(EXT,color_buffer_half_float),
_extension(EXT,sRGB), _extension(EXT,sRGB),
_extension(EXT,blend_minmax),
_extension(EXT,shader_texture_lod), _extension(EXT,shader_texture_lod),
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(MAGNUM,shader_vertex_id), _extension(MAGNUM,shader_vertex_id),
#endif #endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(OES,element_index_uint),
_extension(OES,fbo_render_mipmap),
_extension(OES,standard_derivatives),
_extension(OES,texture_float), _extension(OES,texture_float),
_extension(OES,texture_half_float), _extension(OES,texture_half_float),
_extension(OES,standard_derivatives),
_extension(OES,vertex_array_object),
_extension(OES,element_index_uint),
_extension(OES,texture_half_float_linear), _extension(OES,texture_half_float_linear),
_extension(OES,fbo_render_mipmap), _extension(OES,vertex_array_object),
_extension(WEBGL,depth_texture),
_extension(WEBGL,color_buffer_float), _extension(WEBGL,color_buffer_float),
_extension(WEBGL,depth_texture),
_extension(WEBGL,draw_buffers) _extension(WEBGL,draw_buffers)
#endif #endif
}; };
@ -314,152 +315,182 @@ constexpr Extension ExtensionList[]{
_extension(ANGLE,texture_compression_dxt1), _extension(ANGLE,texture_compression_dxt1),
_extension(ANGLE,texture_compression_dxt3), _extension(ANGLE,texture_compression_dxt3),
_extension(ANGLE,texture_compression_dxt5), _extension(ANGLE,texture_compression_dxt5),
_extension(APPLE,texture_format_BGRA8888),
_extension(APPLE,clip_distance), _extension(APPLE,clip_distance),
_extension(APPLE,texture_format_BGRA8888),
_extension(ARM,shader_framebuffer_fetch), _extension(ARM,shader_framebuffer_fetch),
_extension(ARM,shader_framebuffer_fetch_depth_stencil), _extension(ARM,shader_framebuffer_fetch_depth_stencil),
_extension(EXT,texture_filter_anisotropic), #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,texture_compression_dxt1), _extension(EXT,clip_cull_distance),
_extension(EXT,texture_format_BGRA8888), #endif
_extension(EXT,read_format_bgra),
_extension(EXT,multi_draw_arrays),
_extension(EXT,debug_label), _extension(EXT,debug_label),
_extension(EXT,debug_marker), _extension(EXT,debug_marker),
_extension(EXT,separate_shader_objects), _extension(EXT,disjoint_timer_query),
_extension(EXT,multi_draw_arrays),
_extension(EXT,multisampled_render_to_texture), _extension(EXT,multisampled_render_to_texture),
_extension(EXT,polygon_offset_clamp),
_extension(EXT,pvrtc_sRGB),
_extension(EXT,read_format_bgra),
_extension(EXT,robustness), _extension(EXT,robustness),
_extension(EXT,shader_framebuffer_fetch),
_extension(EXT,disjoint_timer_query),
_extension(EXT,texture_sRGB_decode),
_extension(EXT,sRGB_write_control), _extension(EXT,sRGB_write_control),
_extension(EXT,texture_compression_s3tc), _extension(EXT,separate_shader_objects),
_extension(EXT,pvrtc_sRGB), _extension(EXT,shader_framebuffer_fetch),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,shader_integer_mix), _extension(EXT,shader_integer_mix),
_extension(EXT,texture_sRGB_R8),
_extension(EXT,texture_sRGB_RG8),
#endif #endif
_extension(EXT,polygon_offset_clamp),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,clip_cull_distance),
_extension(EXT,texture_compression_rgtc),
_extension(EXT,texture_compression_bptc), _extension(EXT,texture_compression_bptc),
#endif #endif
_extension(EXT,texture_compression_dxt1),
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,texture_compression_rgtc),
#endif
_extension(EXT,texture_compression_s3tc),
_extension(EXT,texture_compression_s3tc_srgb), _extension(EXT,texture_compression_s3tc_srgb),
_extension(EXT,texture_filter_anisotropic),
_extension(EXT,texture_format_BGRA8888),
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,texture_sRGB_R8),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,texture_sRGB_RG8),
#endif
_extension(EXT,texture_sRGB_decode),
_extension(IMG,texture_compression_pvrtc), _extension(IMG,texture_compression_pvrtc),
_extension(KHR,texture_compression_astc_hdr),
_extension(KHR,blend_equation_advanced_coherent), _extension(KHR,blend_equation_advanced_coherent),
_extension(KHR,context_flush_control), _extension(KHR,context_flush_control),
_extension(KHR,no_error), _extension(KHR,no_error),
_extension(KHR,texture_compression_astc_hdr),
_extension(KHR,texture_compression_astc_sliced_3d), _extension(KHR,texture_compression_astc_sliced_3d),
#ifndef MAGNUM_TARGET_GLES2
_extension(NV,fragment_shader_barycentric),
#endif
_extension(NV,polygon_mode),
_extension(NV,read_buffer_front), _extension(NV,read_buffer_front),
_extension(NV,read_depth), _extension(NV,read_depth),
_extension(NV,read_stencil),
_extension(NV,read_depth_stencil), _extension(NV,read_depth_stencil),
_extension(NV,texture_border_clamp), _extension(NV,read_stencil),
#ifndef MAGNUM_TARGET_GLES2
_extension(NV,shader_noperspective_interpolation),
#endif
_extension(NV,sample_locations), _extension(NV,sample_locations),
_extension(NV,polygon_mode),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(NV,fragment_shader_barycentric), _extension(NV,shader_noperspective_interpolation),
#endif #endif
_extension(NV,texture_border_clamp),
_extension(OES,depth32), _extension(OES,depth32),
_extension(OES,mapbuffer), _extension(OES,mapbuffer),
_extension(OES,stencil1), _extension(OES,stencil1),
_extension(OES,stencil4), _extension(OES,stencil4),
_extension(OES,texture_float_linear),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(OES,texture_compression_astc), _extension(OES,texture_compression_astc),
#endif
_extension(OES,texture_float_linear),
#ifndef MAGNUM_TARGET_GLES2
_extension(OVR,multiview), _extension(OVR,multiview),
_extension(OVR,multiview2) #endif
#ifndef MAGNUM_TARGET_GLES2
_extension(OVR,multiview2),
#endif #endif
}; };
constexpr Extension ExtensionListES300[]{ constexpr Extension ExtensionListES300[]{
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(ANGLE,depth_texture),
_extension(ANGLE,framebuffer_blit), _extension(ANGLE,framebuffer_blit),
_extension(ANGLE,framebuffer_multisample), _extension(ANGLE,framebuffer_multisample),
_extension(ANGLE,instanced_arrays), _extension(ANGLE,instanced_arrays),
_extension(ANGLE,depth_texture),
_extension(APPLE,framebuffer_multisample), _extension(APPLE,framebuffer_multisample),
_extension(APPLE,texture_max_level), _extension(APPLE,texture_max_level),
_extension(ARM,rgba8), _extension(ARM,rgba8),
_extension(EXT,texture_type_2_10_10_10_REV),
_extension(EXT,discard_framebuffer),
_extension(EXT,blend_minmax), _extension(EXT,blend_minmax),
_extension(EXT,shader_texture_lod), _extension(EXT,discard_framebuffer),
_extension(EXT,unpack_subimage), _extension(EXT,draw_buffers),
_extension(EXT,draw_instanced),
_extension(EXT,instanced_arrays),
_extension(EXT,map_buffer_range),
_extension(EXT,occlusion_query_boolean), _extension(EXT,occlusion_query_boolean),
_extension(EXT,sRGB),
_extension(EXT,shader_texture_lod),
_extension(EXT,shadow_samplers), _extension(EXT,shadow_samplers),
_extension(EXT,texture_rg), _extension(EXT,texture_rg),
_extension(EXT,sRGB),
_extension(EXT,texture_storage), _extension(EXT,texture_storage),
_extension(EXT,map_buffer_range), _extension(EXT,texture_type_2_10_10_10_REV),
_extension(EXT,draw_buffers), _extension(EXT,unpack_subimage),
_extension(EXT,instanced_arrays),
_extension(EXT,draw_instanced),
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(MAGNUM,shader_vertex_id), _extension(MAGNUM,shader_vertex_id),
#endif #endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(NV,draw_buffers), _extension(NV,draw_buffers),
_extension(NV,fbo_color_attachments),
_extension(NV,read_buffer),
_extension(NV,pack_subimage),
_extension(NV,draw_instanced), _extension(NV,draw_instanced),
_extension(NV,fbo_color_attachments),
_extension(NV,framebuffer_blit), _extension(NV,framebuffer_blit),
_extension(NV,framebuffer_multisample), _extension(NV,framebuffer_multisample),
_extension(NV,instanced_arrays), _extension(NV,instanced_arrays),
_extension(NV,pack_subimage),
_extension(NV,read_buffer),
_extension(NV,shadow_samplers_array), _extension(NV,shadow_samplers_array),
_extension(NV,shadow_samplers_cube), _extension(NV,shadow_samplers_cube),
_extension(OES,depth24), _extension(OES,depth24),
_extension(OES,depth_texture),
_extension(OES,element_index_uint), _extension(OES,element_index_uint),
_extension(OES,fbo_render_mipmap), _extension(OES,fbo_render_mipmap),
_extension(OES,packed_depth_stencil),
_extension(OES,required_internalformat),
_extension(OES,rgb8_rgba8), _extension(OES,rgb8_rgba8),
_extension(OES,standard_derivatives),
_extension(OES,surfaceless_context),
_extension(OES,texture_3D), _extension(OES,texture_3D),
_extension(OES,texture_half_float_linear),
_extension(OES,texture_half_float),
_extension(OES,texture_float), _extension(OES,texture_float),
_extension(OES,texture_half_float),
_extension(OES,texture_half_float_linear),
_extension(OES,texture_npot), _extension(OES,texture_npot),
_extension(OES,vertex_half_float),
_extension(OES,packed_depth_stencil),
_extension(OES,depth_texture),
_extension(OES,standard_derivatives),
_extension(OES,vertex_array_object), _extension(OES,vertex_array_object),
_extension(OES,required_internalformat), _extension(OES,vertex_half_float),
_extension(OES,surfaceless_context)
#endif #endif
}; };
constexpr Extension ExtensionListES320[]{ constexpr Extension ExtensionListES320[]{
_extension(EXT,color_buffer_half_float),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,color_buffer_float), _extension(EXT,color_buffer_float),
#endif
_extension(EXT,color_buffer_half_float),
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,copy_image), _extension(EXT,copy_image),
#endif #endif
_extension(EXT,draw_buffers_indexed), _extension(EXT,draw_buffers_indexed),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,geometry_shader), _extension(EXT,geometry_shader),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,gpu_shader5), _extension(EXT,gpu_shader5),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,primitive_bounding_box),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,shader_io_blocks), _extension(EXT,shader_io_blocks),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,tessellation_shader), _extension(EXT,tessellation_shader),
#endif #endif
_extension(EXT,texture_border_clamp), _extension(EXT,texture_border_clamp),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(EXT,texture_buffer), _extension(EXT,texture_buffer),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,texture_cube_map_array), _extension(EXT,texture_cube_map_array),
_extension(EXT,primitive_bounding_box),
#endif #endif
_extension(KHR,texture_compression_astc_ldr),
_extension(KHR,debug),
_extension(KHR,blend_equation_advanced), _extension(KHR,blend_equation_advanced),
_extension(KHR,robustness), _extension(KHR,debug),
_extension(KHR,robust_buffer_access_behavior), _extension(KHR,robust_buffer_access_behavior),
_extension(KHR,robustness),
_extension(KHR,texture_compression_astc_ldr),
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_extension(OES,sample_shading), _extension(OES,sample_shading),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(OES,sample_variables), _extension(OES,sample_variables),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(OES,shader_image_atomic), _extension(OES,shader_image_atomic),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(OES,shader_multisample_interpolation), _extension(OES,shader_multisample_interpolation),
#endif #endif
_extension(OES,texture_stencil8), _extension(OES,texture_stencil8),
@ -756,55 +787,51 @@ bool Context::tryCreate() {
glGetIntegerv(GL_CONTEXT_FLAGS, reinterpret_cast<GLint*>(&_flags)); glGetIntegerv(GL_CONTEXT_FLAGS, reinterpret_cast<GLint*>(&_flags));
#endif #endif
std::vector<Version> versions{ constexpr struct {
Version version;
Containers::ArrayView<const Extension> extensions;
} versions[]{
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Version::GL300, {Version::GL300, Containers::arrayView(ExtensionList300)},
Version::GL310, {Version::GL310, Containers::arrayView(ExtensionList310)},
Version::GL320, {Version::GL320, Containers::arrayView(ExtensionList320)},
Version::GL330, {Version::GL330, Containers::arrayView(ExtensionList330)},
Version::GL400, {Version::GL400, Containers::arrayView(ExtensionList400)},
Version::GL410, {Version::GL410, Containers::arrayView(ExtensionList410)},
Version::GL420, {Version::GL420, Containers::arrayView(ExtensionList420)},
Version::GL430, {Version::GL430, Containers::arrayView(ExtensionList430)},
Version::GL440, {Version::GL440, Containers::arrayView(ExtensionList440)},
Version::GL450, {Version::GL450, Containers::arrayView(ExtensionList450)},
Version::GL460, {Version::GL460, Containers::arrayView(ExtensionList460)},
#else #else
Version::GLES200, {Version::GLES300, Containers::arrayView(ExtensionListES300)},
Version::GLES300,
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
Version::GLES310, /* No extensions in ES 3.1 */
Version::GLES320, {Version::GLES320, Containers::arrayView(ExtensionListES320)},
#endif #endif
#endif #endif
Version::None {Version::None, Containers::arrayView(ExtensionList)}
}; };
/* Get first future (not supported) version */ /* Get first future (not supported) version */
std::size_t future = 0; std::size_t future = 0;
while(versions[future] != Version::None && isVersionSupported(versions[future])) while(versions[future].version != Version::None && isVersionSupported(versions[future].version))
++future; ++future;
/* Mark all extensions from past versions as supported */ /* Mark all extensions from past versions as supported */
for(std::size_t i = 0; i != future; ++i) for(std::size_t i = 0; i != future; ++i)
for(const Extension& extension: Extension::extensions(versions[i])) for(const Extension& extension: versions[i].extensions)
_extensionStatus.set(extension.index(), true); _extensionStatus.set(extension.index(), true);
/* List of extensions from future versions (extensions from current and
previous versions should be supported automatically, so we don't need
to check for them) */
std::unordered_map<std::string, Extension> futureExtensions;
for(std::size_t i = future; i != versions.size(); ++i)
for(const Extension& extension: Extension::extensions(versions[i]))
futureExtensions.emplace(extension.string(), extension);
/* Check for presence of future and vendor extensions */ /* Check for presence of future and vendor extensions */
const std::vector<std::string> extensions = extensionStrings(); const std::vector<std::string> extensions = extensionStrings();
for(const std::string& extension: extensions) { for(const std::string& extension: extensions) {
const auto found = futureExtensions.find(extension); for(std::size_t i = future; i != Containers::arraySize(versions); ++i) {
if(found != futureExtensions.end()) { const auto found = std::lower_bound(versions[i].extensions.begin(), versions[i].extensions.end(), extension, [](const Extension& a, const std::string& b) { return a.string() < b; });
_supportedExtensions.push_back(found->second); if(found != versions[i].extensions.end() && found->string() == extension) {
_extensionStatus.set(found->second.index(), true); _supportedExtensions.push_back(*found);
_extensionStatus.set(found->index(), true);
}
} }
} }
@ -812,8 +839,8 @@ bool Context::tryCreate() {
for(auto& i: _extensionRequiredVersion) i = Version::None; for(auto& i: _extensionRequiredVersion) i = Version::None;
/* Initialize required versions from extension info */ /* Initialize required versions from extension info */
for(const auto version: versions) for(const auto& version: versions)
for(const Extension& extension: Extension::extensions(version)) for(const Extension& extension: version.extensions)
_extensionRequiredVersion[extension.index()] = extension.requiredVersion(); _extensionRequiredVersion[extension.index()] = extension.requiredVersion();
/* Setup driver workarounds (increase required version for particular /* Setup driver workarounds (increase required version for particular
@ -836,27 +863,24 @@ bool Context::tryCreate() {
if(!_disabledExtensions.empty()) { if(!_disabledExtensions.empty()) {
bool headerPrinted = false; bool headerPrinted = false;
/* Put remaining extensions into the hashmap for faster lookup */
std::unordered_map<std::string, Extension> allExtensions{std::move(futureExtensions)};
for(std::size_t i = 0; i != future; ++i)
for(const Extension& extension: Extension::extensions(versions[i]))
allExtensions.emplace(extension.string(), extension);
/* Disable extensions that are known and supported and print a message /* Disable extensions that are known and supported and print a message
for each */ for each */
for(auto&& extension: _disabledExtensions) { for(auto&& extension: _disabledExtensions) {
auto found = allExtensions.find(extension); for(const auto& version: versions) {
/* No error message here because some of the extensions could be const auto found = std::lower_bound(version.extensions.begin(), version.extensions.end(), extension, [](const Extension& a, const std::string& b) { return a.string() < b; });
from Vulkan or OpenAL. That also means we print the header only /* No error message here because some of the extensions could
when we actually have something to say */ be from Vulkan or OpenAL. That also means we print the
if(found == allExtensions.end()) continue; header only when we actually have something to say */
if(found == version.extensions.end() || found->string() != extension)
_extensionRequiredVersion[found->second.index()] = Version::None; continue;
if(!headerPrinted) {
Debug{output} << "Disabling extensions:"; _extensionRequiredVersion[found->index()] = Version::None;
headerPrinted = true; if(!headerPrinted) {
Debug{output} << "Disabling extensions:";
headerPrinted = true;
}
Debug{output} << " " << extension;
} }
Debug{output} << " " << extension;
} }
} }

Loading…
Cancel
Save