From 553b2439ac97c68c1be066d2eab8124b4c8f0ca6 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Oct 2017 01:27:44 +0800 Subject: [PATCH] Allow using SSBO for skinning if supported --- data/shaders/header.txt | 4 ++- data/shaders/instanced_skinning.vert | 4 +++ data/shaders/instanced_skinning_shadow.vert | 4 +++ data/shaders/skinning.vert | 4 ++- data/shaders/skinning_shadow.vert | 10 ++++++ src/graphics/draw_calls.cpp | 21 +++++++++--- src/graphics/shader.hpp | 37 +++++++++++++++------ src/graphics/shader_files_manager.cpp | 4 ++- src/graphics/shared_gpu_objects.cpp | 19 +++++++---- src/graphics/stk_animated_mesh.cpp | 4 ++- 10 files changed, 84 insertions(+), 27 deletions(-) diff --git a/data/shaders/header.txt b/data/shaders/header.txt index c5d5326b7..158a55612 100644 --- a/data/shaders/header.txt +++ b/data/shaders/header.txt @@ -64,10 +64,12 @@ layout (std140) uniform LightingData float rL22; }; -layout (std140) uniform SkinningData +#ifdef SSBO_SKINNING +layout (std140, binding = 0) readonly buffer SkinningData { mat4 joint_matrices[MAX_BONES]; }; +#endif #endif #endif // HEADER_TXT diff --git a/data/shaders/instanced_skinning.vert b/data/shaders/instanced_skinning.vert index 0c2812ccd..ee4d12638 100644 --- a/data/shaders/instanced_skinning.vert +++ b/data/shaders/instanced_skinning.vert @@ -78,11 +78,15 @@ void main(void) { break; } +#ifdef SSBO_SKINNING + mat4 joint_matrix = joint_matrices[Joint[i] + skinning_offset]; +#else mat4 joint_matrix = mat4( texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 1), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 2), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 3)); +#endif skinned_position += Weight[i] * joint_matrix * idle_position; skinned_normal += Weight[i] * joint_matrix * idle_normal; skinned_tangent += Weight[i] * joint_matrix * idle_tangent; diff --git a/data/shaders/instanced_skinning_shadow.vert b/data/shaders/instanced_skinning_shadow.vert index f2b726d00..2fc326218 100644 --- a/data/shaders/instanced_skinning_shadow.vert +++ b/data/shaders/instanced_skinning_shadow.vert @@ -57,11 +57,15 @@ void main(void) { break; } +#ifdef SSBO_SKINNING + mat4 joint_matrix = joint_matrices[Joint[i] + skinning_offset]; +#else mat4 joint_matrix = mat4( texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 1), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 2), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 3)); +#endif skinned_position += Weight[i] * joint_matrix * idle_position; } } diff --git a/data/shaders/skinning.vert b/data/shaders/skinning.vert index 64aacc5e6..d1496f4f8 100644 --- a/data/shaders/skinning.vert +++ b/data/shaders/skinning.vert @@ -75,7 +75,9 @@ void main(void) { break; } -#ifdef GL_ES +#ifdef SSBO_SKINNING + mat4 joint_matrix = joint_matrices[Joint[i] + skinning_offset]; +#elif defined(GL_ES) mat4 joint_matrix = mat4( texelFetch(skinning_tex, ivec2(0, skinning_offset + Joint[i]), 0), texelFetch(skinning_tex, ivec2(1, skinning_offset + Joint[i]), 0), diff --git a/data/shaders/skinning_shadow.vert b/data/shaders/skinning_shadow.vert index 1e9573a3f..71af0b9ae 100644 --- a/data/shaders/skinning_shadow.vert +++ b/data/shaders/skinning_shadow.vert @@ -38,11 +38,21 @@ void main(void) { break; } +#ifdef SSBO_SKINNING + mat4 joint_matrix = joint_matrices[Joint[i] + skinning_offset]; +#elif defined(GL_ES) + mat4 joint_matrix = mat4( + texelFetch(skinning_tex, ivec2(0, skinning_offset + Joint[i]), 0), + texelFetch(skinning_tex, ivec2(1, skinning_offset + Joint[i]), 0), + texelFetch(skinning_tex, ivec2(2, skinning_offset + Joint[i]), 0), + texelFetch(skinning_tex, ivec2(3, skinning_offset + Joint[i]), 0)); +#else mat4 joint_matrix = mat4( texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 1), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 2), texelFetch(skinning_tex, (Joint[i] + skinning_offset) * 4 + 3)); +#endif skinned_position += Weight[i] * joint_matrix * idle_position; } } diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 70aaacfde..b68d5aead 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -685,19 +685,30 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices, PROFILER_PUSH_CPU_MARKER("- Animations/Buffer upload", 0x0, 0x0, 0x0); shadow_matrices.updateUBO(); + if (CVS->supportsHardwareSkinning()) + { #ifdef USE_GLES2 - glBindTexture(GL_TEXTURE_2D, SharedGPUObjects::getSkinningTexture()); + glBindTexture(GL_TEXTURE_2D, SharedGPUObjects::getSkinningTexture()); #else - glBindBuffer(GL_TEXTURE_BUFFER, SharedGPUObjects::getSkinningBuffer()); + glBindBuffer(CVS->isARBShaderStorageBufferObjectUsable() ? + GL_SHADER_STORAGE_BUFFER : GL_TEXTURE_BUFFER, + SharedGPUObjects::getSkinningBuffer()); #endif + } for (unsigned i = 0; i < m_deferred_update.size(); i++) + { m_deferred_update[i]->updateGL(); - PROFILER_POP_CPU_MARKER(); + } + if (CVS->supportsHardwareSkinning()) + { #ifdef USE_GLES2 - glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, 0); #else - glBindBuffer(GL_TEXTURE_BUFFER, 0); + glBindBuffer(CVS->isARBShaderStorageBufferObjectUsable() ? + GL_SHADER_STORAGE_BUFFER : GL_TEXTURE_BUFFER, 0); #endif + } + PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("- cpu particle upload", 0x3F, 0x03, 0x61); CPUParticleManager::getInstance()->uploadAll(); diff --git a/src/graphics/shader.hpp b/src/graphics/shader.hpp index 280ab2582..41a385864 100644 --- a/src/graphics/shader.hpp +++ b/src/graphics/shader.hpp @@ -146,9 +146,8 @@ private: /** End of recursive implementation of assignUniforms. */ void assignUniformsImpl() { - bindPoint("MatrixData", 0); + bindPoint("MatrixesData", 0); bindPoint("LightingData", 1); - bindPoint("SkinningData", 2); } // assignUniformsImpl // ------------------------------------------------------------------------ @@ -384,28 +383,44 @@ public: class SkinnedMeshShader { private: - GLuint m_skinning_tex_location; + GLuint m_skinning_location; public: - SkinnedMeshShader() : m_skinning_tex_location(0) {} + SkinnedMeshShader() : m_skinning_location(0) {} // ------------------------------------------------------------------------ template void init(Shader* s) { s->use(); - m_skinning_tex_location = s->getUniformLocation("skinning_tex"); - glUniform1i(m_skinning_tex_location, 15); +#ifndef USE_GLES2 + if (CVS->isARBShaderStorageBufferObjectUsable() && + CVS->supportsHardwareSkinning()) + { + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, + SharedGPUObjects::getSkinningBuffer()); + } + else +#endif + { + m_skinning_location = s->getUniformLocation("skinning_tex"); + glUniform1i(m_skinning_location, 15); + } } // ------------------------------------------------------------------------ void bindSkinningTexture() { - glActiveTexture(GL_TEXTURE0 + 15); #ifdef USE_GLES2 + glActiveTexture(GL_TEXTURE0 + 15); glBindTexture(GL_TEXTURE_2D, SharedGPUObjects::getSkinningTexture()); -#else - glBindTexture(GL_TEXTURE_BUFFER, - SharedGPUObjects::getSkinningTexture()); -#endif glBindSampler(15, 0); +#else + if (!CVS->isARBShaderStorageBufferObjectUsable()) + { + glActiveTexture(GL_TEXTURE0 + 15); + glBindTexture(GL_TEXTURE_BUFFER, + SharedGPUObjects::getSkinningTexture()); + glBindSampler(15, 0); + } +#endif } }; diff --git a/src/graphics/shader_files_manager.cpp b/src/graphics/shader_files_manager.cpp index f08597719..189887ff5 100644 --- a/src/graphics/shader_files_manager.cpp +++ b/src/graphics/shader_files_manager.cpp @@ -170,7 +170,9 @@ GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type) code << "#define Advanced_Lighting_Enabled\n"; if (CVS->isARBSRGBFramebufferUsable()) code << "#define sRGB_Framebuffer_Usable\n"; - + if (CVS->isARBShaderStorageBufferObjectUsable() && + CVS->supportsHardwareSkinning()) + code << "#define SSBO_SKINNING\n"; #if !defined(USE_GLES2) // shader compilation fails with some drivers if there is no precision // qualifier diff --git a/src/graphics/shared_gpu_objects.cpp b/src/graphics/shared_gpu_objects.cpp index 5dcc3ed5f..38fa5c5b8 100644 --- a/src/graphics/shared_gpu_objects.cpp +++ b/src/graphics/shared_gpu_objects.cpp @@ -174,14 +174,19 @@ void SharedGPUObjects::initSkinning() glBindTexture(GL_TEXTURE_2D, 0); #else glGenBuffers(1, &m_skinning_buf); - glBindBuffer(GL_TEXTURE_BUFFER, m_skinning_buf); - glBufferData(GL_TEXTURE_BUFFER, 65536, NULL, GL_DYNAMIC_DRAW); - glBindTexture(GL_TEXTURE_BUFFER, m_skinning_tex); - glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_skinning_buf); - glBindTexture(GL_TEXTURE_BUFFER, 0); - glBindBuffer(GL_TEXTURE_BUFFER, 0); + const bool ssbo = CVS->isARBShaderStorageBufferObjectUsable(); + const GLenum buffer = ssbo ? GL_SHADER_STORAGE_BUFFER : GL_TEXTURE_BUFFER; + glBindBuffer(buffer, m_skinning_buf); + glBufferData(buffer, 65536, NULL, GL_DYNAMIC_DRAW); + if (!ssbo) + { + glBindTexture(GL_TEXTURE_BUFFER, m_skinning_tex); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_skinning_buf); + glBindTexture(GL_TEXTURE_BUFFER, 0); + } + glBindBuffer(buffer, 0); #endif -} // initSkinningTBO +} // initSkinning // ---------------------------------------------------------------------------- void SharedGPUObjects::init() diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp index 6ea9f8238..2d8d69c59 100644 --- a/src/graphics/stk_animated_mesh.cpp +++ b/src/graphics/stk_animated_mesh.cpp @@ -382,7 +382,9 @@ void STKAnimatedMesh::uploadJoints(const irr::core::matrix4& m, glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (offset >> 6) + joint, 16, 1, GL_RGBA, GL_FLOAT, m.pointer()); #else - glBufferSubData(GL_TEXTURE_BUFFER, offset + joint * 16 * sizeof(float), + glBufferSubData(CVS->isARBShaderStorageBufferObjectUsable() ? + GL_SHADER_STORAGE_BUFFER : GL_TEXTURE_BUFFER, + offset + joint * 16 * sizeof(float), 16 * sizeof(float), m.pointer()); #endif }