1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
#include "GLUniformBlock.h"
#include "GLShaderProgram.h"
#include "GLDebug.h"
#include "../IGfxCapabilities.h"
#include "../../ServiceLocator.h"
namespace nCine
{
GLUniformBlock::GLUniformBlock()
: program_(0), index_(0), size_(0), alignAmount_(0), bindingIndex_(-1)
{
name_[0] = '\0';
}
GLUniformBlock::GLUniformBlock(GLuint program, GLuint index, DiscoverUniforms discover)
: GLUniformBlock()
{
GLint nameLength = 0;
GLint uniformCount = 0;
program_ = program;
index_ = index;
glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_DATA_SIZE, &size_);
glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_NAME_LENGTH, &nameLength);
DEATH_ASSERT(nameLength <= MaxNameLength);
glGetActiveUniformBlockName(program, index, MaxNameLength, &nameLength, name_);
glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &uniformCount);
if (discover == DiscoverUniforms::ENABLED && uniformCount > 0) {
DEATH_ASSERT(uniformCount <= MaxNumBlockUniforms);
GLuint uniformIndices[MaxNumBlockUniforms];
GLint uniformTypes[MaxNumBlockUniforms];
GLint uniformSizes[MaxNumBlockUniforms];
GLint uniformOffsets[MaxNumBlockUniforms];
GLint uniformNameLengths[MaxNumBlockUniforms];
GLint uniformQueryIndices[MaxNumBlockUniforms];
glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, uniformQueryIndices);
for (std::int32_t i = 0; i < uniformCount; i++)
uniformIndices[i] = static_cast<GLuint>(uniformQueryIndices[i]);
glGetActiveUniformsiv(program, uniformCount, uniformIndices, GL_UNIFORM_TYPE, uniformTypes);
glGetActiveUniformsiv(program, uniformCount, uniformIndices, GL_UNIFORM_SIZE, uniformSizes);
glGetActiveUniformsiv(program, uniformCount, uniformIndices, GL_UNIFORM_OFFSET, uniformOffsets);
#if !defined(DEATH_TARGET_EMSCRIPTEN)
glGetActiveUniformsiv(program, uniformCount, uniformIndices, GL_UNIFORM_NAME_LENGTH, uniformNameLengths);
#endif
for (std::int32_t i = 0; i < uniformCount; i++) {
GLUniform blockUniform;
blockUniform.index_ = uniformIndices[i];
blockUniform.blockIndex_ = static_cast<GLint>(index);
blockUniform.type_ = static_cast<GLenum>(uniformTypes[i]);
blockUniform.size_ = uniformSizes[i];
blockUniform.offset_ = uniformOffsets[i];
#if !defined(DEATH_TARGET_EMSCRIPTEN)
DEATH_ASSERT(uniformNameLengths[i] <= GLUniform::MaxNameLength,
("Uniform {} name length is {}, which is more than {}", i, uniformNameLengths[i], GLUniform::MaxNameLength), );
#endif
#if !defined(WITH_OPENGLES) && !defined(DEATH_TARGET_EMSCRIPTEN)
glGetActiveUniformName(program, uniformIndices[i], MaxNameLength, &uniformNameLengths[i], blockUniform.name_);
#else
// Some drivers do not accept a `nullptr` for size and type
GLint unusedSize;
GLenum unusedType;
glGetActiveUniform(program, uniformIndices[i], MaxNameLength, &uniformNameLengths[i], &unusedSize, &unusedType, blockUniform.name_);
#endif
blockUniforms_[blockUniform.name_] = blockUniform;
}
}
GL_LOG_ERRORS();
// Align to the uniform buffer offset alignment or `glBindBufferRange()` will generate an `INVALID_VALUE` error
static const std::int32_t offsetAlignment = theServiceLocator().GetGfxCapabilities().GetValue(IGfxCapabilities::GLIntValues::UNIFORM_BUFFER_OFFSET_ALIGNMENT);
alignAmount_ = (offsetAlignment - size_ % offsetAlignment) % offsetAlignment;
size_ += alignAmount_;
}
GLUniformBlock::GLUniformBlock(GLuint program, GLuint index)
: GLUniformBlock(program, index, DiscoverUniforms::ENABLED)
{
}
void GLUniformBlock::SetBlockBinding(GLuint blockBinding)
{
DEATH_ASSERT(program_ != 0);
if (bindingIndex_ != static_cast<GLint>(blockBinding)) {
glUniformBlockBinding(program_, index_, blockBinding);
GL_LOG_ERRORS();
bindingIndex_ = static_cast<GLint>(blockBinding);
}
}
}
|