File: GLUniformBlock.cpp

package info (click to toggle)
jazz2-native 3.5.0-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid
  • size: 16,912 kB
  • sloc: cpp: 172,557; xml: 113; python: 36; makefile: 5; sh: 2
file content (97 lines) | stat: -rw-r--r-- 3,871 bytes parent folder | download
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);
		}
	}
}