Allow to use skinning without tbo

This commit is contained in:
Deve 2018-06-22 23:47:18 +02:00
parent fee6866c6d
commit 9ad3ba1fe2
9 changed files with 135 additions and 86 deletions

View File

@ -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),

View File

@ -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

View File

@ -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;

View File

@ -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<std::string, 30> m_names_of_restrictions =
std::array<std::string, 31> m_names_of_restrictions =
{
{
"UniformBufferObject",
@ -76,7 +76,8 @@ namespace GraphicsRestrictions
"ForceLegacyDevice",
"VertexIdWorking",
"HardwareSkinning",
"NpotTextures"
"NpotTextures",
"TextureBufferObject"
}
};
} // namespace Private

View File

@ -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. */
} ;

View File

@ -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())

View File

@ -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<std::array<float, 16> >
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<float, 16>*)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<float, 16>*)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<std::array<float, 16> >
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<float, 16>*)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<float, 16>*)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<float, 16>) == 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<float, 16>*)
@ -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);

View File

@ -28,17 +28,37 @@
namespace SP
{
const std::map<std::string, std::pair<unsigned, SamplerType> >
g_prefilled_names =
{
#ifdef USE_GLES2
{ "skinning_tex", { 0, ST_NEAREST_CLAMPED } }
#else
{ "skinning_tex", { 0, ST_TEXTURE_BUFFER } }
#endif
};
std::map<std::string, std::pair<unsigned, SamplerType> >
SPShader::m_prefilled_names;
bool SPShader::m_sp_shader_debug = false;
SPShader::SPShader(const std::string& name,
const std::function<void(SPShader*)>& init_func,
bool transparent_shader, int drawing_priority,
bool use_alpha_channel, bool use_tangents,
const std::array<bool, 6>& 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<unsigned,
SamplerType>(0, ST_TEXTURE_BUFFER);
#endif
}
else
{
m_prefilled_names["skinning_tex"] = std::make_pair<unsigned,
SamplerType>(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)));

View File

@ -113,22 +113,15 @@ private:
public:
// ------------------------------------------------------------------------
static bool m_sp_shader_debug;
static std::map<std::string, std::pair<unsigned, SamplerType> >
m_prefilled_names;
// ------------------------------------------------------------------------
SPShader(const std::string& name,
const std::function<void(SPShader*)>& init_func,
bool transparent_shader = false, int drawing_priority = 0,
bool use_alpha_channel = false, bool use_tangents = false,
const std::array<bool, 6>& 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()
{