diff --git a/data/shaders/sp_skinning.vert b/data/shaders/sp_skinning.vert index e8464dc13..241816261 100644 --- a/data/shaders/sp_skinning.vert +++ b/data/shaders/sp_skinning.vert @@ -1,4 +1,4 @@ -#ifdef GL_ES +#ifdef TBO_DISABLED uniform sampler2D skinning_tex; #else uniform samplerBuffer skinning_tex; @@ -56,7 +56,7 @@ void main() vec4 skinned_tangent = vec4(0.0); int skinning_offset = i_misc_data.x; -#ifdef GL_ES +#ifdef TBO_DISABLED mat4 joint_matrix = i_weight[0] * mat4( texelFetch(skinning_tex, ivec2(0, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index b68b0532f..79c518d44 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -56,6 +56,7 @@ void CentralVideoSettings::init() hasInstancedArrays = false; hasBGRA = false; hasColorBufferFloat = false; + hasTextureBufferObject = false; m_need_vertex_id_workaround = false; // Call to glGetIntegerv should not be made if --no-graphics is used @@ -157,6 +158,12 @@ void CentralVideoSettings::init() hasGS = true; Log::info("GLDriver", "Geometry Shaders Present"); } + if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_BUFFER_OBJECT) && + m_glsl == true) + { + hasTextureBufferObject = true; + Log::info("GLDriver", "ARB Texture Buffer Object Present"); + } if (hasGLExtension("GL_ARB_texture_swizzle")) { hasTextureSwizzle = true; @@ -216,7 +223,7 @@ void CentralVideoSettings::init() hasUBO = true; Log::info("GLDriver", "ARB Uniform Buffer Object Present"); } - + if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FORMAT_BGRA8888) && (hasGLExtension("GL_IMG_texture_format_BGRA8888") || hasGLExtension("GL_EXT_texture_format_BGRA8888"))) @@ -449,4 +456,9 @@ bool CentralVideoSettings::isARBInstancedArraysUsable() const (m_gl_major_version > 3 || (m_gl_major_version == 3 && m_gl_minor_version >= 2)); } +bool CentralVideoSettings::isARBTextureBufferObjectUsable() const +{ + return hasTextureBufferObject; +} + #endif // !SERVER_ONLY diff --git a/src/graphics/central_settings.hpp b/src/graphics/central_settings.hpp index d02c4996f..d4ca9a5b3 100644 --- a/src/graphics/central_settings.hpp +++ b/src/graphics/central_settings.hpp @@ -48,6 +48,7 @@ private: bool hasInstancedArrays; bool hasBGRA; bool hasColorBufferFloat; + bool hasTextureBufferObject; bool m_need_vertex_id_workaround; public: static bool m_supports_sp; @@ -81,6 +82,7 @@ public: bool isARBInstancedArraysUsable() const; bool isEXTTextureFormatBGRA8888Usable() const; bool isEXTColorBufferFloatUsable() const; + bool isARBTextureBufferObjectUsable() const; // Are all required extensions available for feature support bool supportsComputeShadersFiltering() const; diff --git a/src/graphics/graphics_restrictions.cpp b/src/graphics/graphics_restrictions.cpp index e7cdb5e53..2c7292750 100644 --- a/src/graphics/graphics_restrictions.cpp +++ b/src/graphics/graphics_restrictions.cpp @@ -44,7 +44,7 @@ namespace GraphicsRestrictions /** The list of names used in the XML file for the graphics * restriction types. They must be in the same order as the types. */ - std::array m_names_of_restrictions = + std::array m_names_of_restrictions = { { "UniformBufferObject", @@ -76,7 +76,8 @@ namespace GraphicsRestrictions "ForceLegacyDevice", "VertexIdWorking", "HardwareSkinning", - "NpotTextures" + "NpotTextures", + "TextureBufferObject" } }; } // namespace Private diff --git a/src/graphics/graphics_restrictions.hpp b/src/graphics/graphics_restrictions.hpp index 09666adbc..26902bc65 100644 --- a/src/graphics/graphics_restrictions.hpp +++ b/src/graphics/graphics_restrictions.hpp @@ -64,6 +64,7 @@ namespace GraphicsRestrictions GR_VERTEX_ID_WORKING, GR_HARDWARE_SKINNING, GR_NPOT_TEXTURES, + GR_TEXTURE_BUFFER_OBJECT, GR_COUNT /** MUST be last entry. */ } ; diff --git a/src/graphics/shader_files_manager.cpp b/src/graphics/shader_files_manager.cpp index dea661fe9..cbc14406a 100644 --- a/src/graphics/shader_files_manager.cpp +++ b/src/graphics/shader_files_manager.cpp @@ -171,6 +171,8 @@ ShaderFilesManager::SharedShader ShaderFilesManager::loadShader code << "//" << full_path << "\n"; if (!CVS->isARBUniformBufferObjectUsable()) code << "#define UBO_DISABLED\n"; + if (!CVS->isARBTextureBufferObjectUsable()) + code << "#define TBO_DISABLED\n"; if (CVS->needsVertexIdWorkaround()) code << "#define Needs_Vertex_Id_Workaround\n"; if (CVS->isDeferredEnabled()) diff --git a/src/graphics/sp/sp_base.cpp b/src/graphics/sp/sp_base.cpp index c1514061a..bcc681f6e 100644 --- a/src/graphics/sp/sp_base.cpp +++ b/src/graphics/sp/sp_base.cpp @@ -237,43 +237,47 @@ void resizeSkinning(unsigned number) const irr::core::matrix4 m; g_skinning_size = number; -#ifdef USE_GLES2 - glBindTexture(GL_TEXTURE_2D, g_skinning_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 4, number, 0, GL_RGBA, - GL_FLOAT, NULL); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 1, GL_RGBA, GL_FLOAT, - m.pointer()); - glBindTexture(GL_TEXTURE_2D, 0); - static std::vector > - tmp_buf(stk_config->m_max_skinning_bones); - g_joint_ptr = tmp_buf.data(); -#else - - glBindBuffer(GL_TEXTURE_BUFFER, g_skinning_buf); - if (CVS->isARBBufferStorageUsable()) + if (!CVS->isARBTextureBufferObjectUsable()) { - glBufferStorage(GL_TEXTURE_BUFFER, number << 6, NULL, - GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); - g_joint_ptr = (std::array*)glMapBufferRange( - GL_TEXTURE_BUFFER, 0, 64, - GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); - memcpy(g_joint_ptr, m.pointer(), 64); - glUnmapBuffer(GL_TEXTURE_BUFFER); - g_joint_ptr = (std::array*)glMapBufferRange( - GL_TEXTURE_BUFFER, 64, (number - 1) << 6, - GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + glBindTexture(GL_TEXTURE_2D, g_skinning_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 4, number, 0, GL_RGBA, + GL_FLOAT, NULL); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 1, GL_RGBA, GL_FLOAT, + m.pointer()); + glBindTexture(GL_TEXTURE_2D, 0); + static std::vector > + tmp_buf(stk_config->m_max_skinning_bones); + g_joint_ptr = tmp_buf.data(); } else { - glBufferData(GL_TEXTURE_BUFFER, number << 6, NULL, GL_DYNAMIC_DRAW); - glBufferSubData(GL_TEXTURE_BUFFER, 0, 64, m.pointer()); - } - glBindTexture(GL_TEXTURE_BUFFER, g_skinning_tex); - glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, g_skinning_buf); - glBindTexture(GL_TEXTURE_BUFFER, 0); +#ifndef USE_GLES2 + glBindBuffer(GL_TEXTURE_BUFFER, g_skinning_buf); + if (CVS->isARBBufferStorageUsable()) + { + glBufferStorage(GL_TEXTURE_BUFFER, number << 6, NULL, + GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + g_joint_ptr = (std::array*)glMapBufferRange( + GL_TEXTURE_BUFFER, 0, 64, + GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + memcpy(g_joint_ptr, m.pointer(), 64); + glUnmapBuffer(GL_TEXTURE_BUFFER); + g_joint_ptr = (std::array*)glMapBufferRange( + GL_TEXTURE_BUFFER, 64, (number - 1) << 6, + GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + } + else + { + glBufferData(GL_TEXTURE_BUFFER, number << 6, NULL, GL_DYNAMIC_DRAW); + glBufferSubData(GL_TEXTURE_BUFFER, 0, 64, m.pointer()); + } + glBindTexture(GL_TEXTURE_BUFFER, g_skinning_tex); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, g_skinning_buf); + glBindTexture(GL_TEXTURE_BUFFER, 0); #endif + } } // resizeSkinning @@ -283,30 +287,35 @@ void initSkinning() static_assert(sizeof(std::array) == 64, "No padding"); int max_size = 0; -#ifdef USE_GLES2 - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); - if (stk_config->m_max_skinning_bones > (unsigned)max_size) + if (!CVS->isARBTextureBufferObjectUsable()) { - Log::warn("SharedGPUObjects", "Too many bones for skinning, max: %d", - max_size); - stk_config->m_max_skinning_bones = max_size; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size); + + if (stk_config->m_max_skinning_bones > (unsigned)max_size) + { + Log::warn("SharedGPUObjects", "Too many bones for skinning, max: %d", + max_size); + stk_config->m_max_skinning_bones = max_size; + } + Log::info("SharedGPUObjects", "Hardware Skinning enabled, method: %u" + " (max bones) * 16 RGBA float texture", + stk_config->m_max_skinning_bones); } - Log::info("SharedGPUObjects", "Hardware Skinning enabled, method: %u" - " (max bones) * 16 RGBA float texture", - stk_config->m_max_skinning_bones); -#else - - glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &max_size); - if (stk_config->m_max_skinning_bones << 6 > (unsigned)max_size) + else { - Log::warn("SharedGPUObjects", "Too many bones for skinning, max: %d", - max_size >> 6); - stk_config->m_max_skinning_bones = max_size >> 6; - } - Log::info("SharedGPUObjects", "Hardware Skinning enabled, method: TBO, " - "max bones: %u", stk_config->m_max_skinning_bones); +#ifndef USE_GLES2 + glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &max_size); + if (stk_config->m_max_skinning_bones << 6 > (unsigned)max_size) + { + Log::warn("SharedGPUObjects", "Too many bones for skinning, max: %d", + max_size >> 6); + stk_config->m_max_skinning_bones = max_size >> 6; + } + Log::info("SharedGPUObjects", "Hardware Skinning enabled, method: TBO, " + "max bones: %u", stk_config->m_max_skinning_bones); #endif + } // Reserve 1 identity matrix for non-weighted vertices @@ -314,7 +323,10 @@ void initSkinning() const irr::core::matrix4 m; glGenTextures(1, &g_skinning_tex); #ifndef USE_GLES2 - glGenBuffers(1, &g_skinning_buf); + if (CVS->isARBTextureBufferObjectUsable()) + { + glGenBuffers(1, &g_skinning_buf); + } #endif resizeSkinning(stk_config->m_max_skinning_bones); @@ -581,7 +593,8 @@ void destroy() SPTextureManager::destroy(); #ifndef USE_GLES2 - if (CVS->isARBBufferStorageUsable()) + if (CVS->isARBTextureBufferObjectUsable() && + CVS->isARBBufferStorageUsable()) { glBindBuffer(GL_TEXTURE_BUFFER, g_skinning_buf); glUnmapBuffer(GL_TEXTURE_BUFFER); @@ -1160,7 +1173,8 @@ void uploadSkinningMatrices() unsigned buffer_offset = 0; #ifndef USE_GLES2 - if (!CVS->isARBBufferStorageUsable()) + if (CVS->isARBTextureBufferObjectUsable() && + !CVS->isARBBufferStorageUsable()) { glBindBuffer(GL_TEXTURE_BUFFER, g_skinning_buf); g_joint_ptr = (std::array*) @@ -1178,13 +1192,17 @@ void uploadSkinningMatrices() buffer_offset += g_skinning_mesh[i]->getTotalJoints(); } -#ifdef USE_GLES2 - glBindTexture(GL_TEXTURE_2D, g_skinning_tex); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 1, 4, buffer_offset, GL_RGBA, - GL_FLOAT, g_joint_ptr); - glBindTexture(GL_TEXTURE_2D, 0); -#else - if (!CVS->isARBBufferStorageUsable()) + if (!CVS->isARBTextureBufferObjectUsable()) + { + glBindTexture(GL_TEXTURE_2D, g_skinning_tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 1, 4, buffer_offset, GL_RGBA, + GL_FLOAT, g_joint_ptr); + glBindTexture(GL_TEXTURE_2D, 0); + } + +#ifndef USE_GLES2 + if (CVS->isARBTextureBufferObjectUsable() && + !CVS->isARBBufferStorageUsable()) { glUnmapBuffer(GL_TEXTURE_BUFFER); glBindBuffer(GL_TEXTURE_BUFFER, 0); diff --git a/src/graphics/sp/sp_shader.cpp b/src/graphics/sp/sp_shader.cpp index c39b33784..466b72cd4 100644 --- a/src/graphics/sp/sp_shader.cpp +++ b/src/graphics/sp/sp_shader.cpp @@ -28,17 +28,37 @@ namespace SP { -const std::map > - g_prefilled_names = - { -#ifdef USE_GLES2 - { "skinning_tex", { 0, ST_NEAREST_CLAMPED } } -#else - { "skinning_tex", { 0, ST_TEXTURE_BUFFER } } -#endif - }; +std::map > + SPShader::m_prefilled_names; bool SPShader::m_sp_shader_debug = false; +SPShader::SPShader(const std::string& name, + const std::function& init_func, + bool transparent_shader, int drawing_priority, + bool use_alpha_channel, bool use_tangents, + const std::array& srgb) + : m_name(name), m_init_function(init_func), + m_drawing_priority(drawing_priority), + m_transparent_shader(transparent_shader), + m_use_alpha_channel(use_alpha_channel), + m_use_tangents(use_tangents), m_srgb(srgb) +{ + if (CVS->isARBTextureBufferObjectUsable()) + { +#ifndef USE_GLES2 + m_prefilled_names["skinning_tex"] = std::make_pair(0, ST_TEXTURE_BUFFER); +#endif + } + else + { + m_prefilled_names["skinning_tex"] = std::make_pair(0, ST_NEAREST_CLAMPED); + } + + memset(m_program, 0, 12); + m_init_function(this); +} // ---------------------------------------------------------------------------- void SPShader::addShaderFile(const std::string& name, GLint shader_type, RenderPass rp) @@ -104,7 +124,7 @@ void SPShader::addAllTextures(RenderPass rp) { #ifndef SERVER_ONLY // Built-in prefilled shaders first - for (auto &p : g_prefilled_names) + for (auto &p : m_prefilled_names) { const char* s = p.first.c_str(); GLuint loc = glGetUniformLocation(m_program[rp], s); @@ -175,8 +195,8 @@ void SPShader::bindPrefilledTextures(RenderPass rp) const for (auto& p : m_prefilled_samplers[rp]) { glActiveTexture(GL_TEXTURE0 + std::get<0>(p)); - auto it = g_prefilled_names.find(std::get<1>(p)); - if (it != g_prefilled_names.end()) + auto it = m_prefilled_names.find(std::get<1>(p)); + if (it != m_prefilled_names.end()) { glBindTexture(std::get<3>(p), sp_prefilled_tex[it->second.first]); glBindSampler(std::get<0>(p), getSampler(std::get<2>(p))); diff --git a/src/graphics/sp/sp_shader.hpp b/src/graphics/sp/sp_shader.hpp index c3c1f37cc..f40ed0943 100644 --- a/src/graphics/sp/sp_shader.hpp +++ b/src/graphics/sp/sp_shader.hpp @@ -113,22 +113,15 @@ private: public: // ------------------------------------------------------------------------ static bool m_sp_shader_debug; + static std::map > + m_prefilled_names; // ------------------------------------------------------------------------ SPShader(const std::string& name, const std::function& init_func, bool transparent_shader = false, int drawing_priority = 0, bool use_alpha_channel = false, bool use_tangents = false, const std::array& srgb = - {{ true, true, false, false, false, false }}) - : m_name(name), m_init_function(init_func), - m_drawing_priority(drawing_priority), - m_transparent_shader(transparent_shader), - m_use_alpha_channel(use_alpha_channel), - m_use_tangents(use_tangents), m_srgb(srgb) - { - memset(m_program, 0, 12); - m_init_function(this); - } + {{ true, true, false, false, false, false }}); // ------------------------------------------------------------------------ ~SPShader() {