2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "gles-graphics-reflection.h"
19 #include <dali/integration-api/gl-abstraction.h>
20 #include <dali/integration-api/gl-defines.h>
23 #include "egl-graphics-controller.h"
25 #include <GLES3/gl3.h>
26 #include <GLES3/gl31.h>
32 Dali::Graphics::VertexInputAttributeFormat GetVertexAttributeTypeFormat(GLenum type)
37 return Dali::Graphics::VertexInputAttributeFormat::FLOAT;
39 return Dali::Graphics::VertexInputAttributeFormat::VEC2;
41 return Dali::Graphics::VertexInputAttributeFormat::VEC3;
43 return Dali::Graphics::VertexInputAttributeFormat::VEC4;
45 return Dali::Graphics::VertexInputAttributeFormat::INTEGER;
47 return Dali::Graphics::VertexInputAttributeFormat::UNDEFINED;
51 int GetGLDataTypeSize(GLenum type)
53 // There are many more types than what are covered here, but
54 // they are not supported in dali.
57 case GL_FLOAT: // "float", 1 float, 4 bytes
59 case GL_FLOAT_VEC2: // "vec2", 2 floats, 8 bytes
61 case GL_FLOAT_VEC3: // "vec3", 3 floats, 12 bytes
63 case GL_FLOAT_VEC4: // "vec4", 4 floats, 16 bytes
65 case GL_INT: // "int", 1 integer, 4 bytes
67 case GL_FLOAT_MAT2: // "mat2", 4 floats, 16 bytes
69 case GL_FLOAT_MAT3: // "mat3", 3 vec3, 36 bytes
71 case GL_FLOAT_MAT4: // "mat4", 4 vec4, 64 bytes
78 bool IsSampler(GLenum type)
80 return type == GL_SAMPLER_2D || type == GL_SAMPLER_3D;
83 bool SortByLocation(Dali::Graphics::UniformInfo a, Dali::Graphics::UniformInfo b)
85 return a.location < b.location;
96 Reflection::Reflection(Graphics::EglGraphicsController& controller)
97 : Graphics::Reflection(),
98 mController(controller),
103 Reflection::~Reflection()
107 void Reflection::BuildVertexAttributeReflection()
109 int written, size, location, maxLength, nAttribs;
113 auto gl = mController.GetGL();
115 gl->GetProgramiv(mGlProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
116 gl->GetProgramiv(mGlProgram, GL_ACTIVE_ATTRIBUTES, &nAttribs);
118 mVertexInputAttributes.clear();
119 mVertexInputAttributes.resize(nAttribs);
121 name = new GLchar[maxLength];
122 for(int i = 0; i < nAttribs; i++)
124 gl->GetActiveAttrib(mGlProgram, i, maxLength, &written, &size, &type, name);
125 location = gl->GetAttribLocation(mGlProgram, name);
127 AttributeInfo attributeInfo;
128 attributeInfo.location = location;
129 attributeInfo.name = name;
130 attributeInfo.format = GetVertexAttributeTypeFormat(type);
132 mVertexInputAttributes.insert(mVertexInputAttributes.begin() + location, attributeInfo);
137 void Reflection::BuildUniformReflection()
144 auto gl = mController.GetGL();
146 gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
147 gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
149 mUniformBlocks.clear();
150 mDefaultUniformBlock.members.clear();
151 mUniformOpaques.clear();
153 name = new char[maxLen];
155 int maxUniformLocations;
156 gl->GetProgramiv(mGlProgram, GL_MAX_UNIFORM_LOCATIONS, &maxUniformLocations);
158 std::vector<int> uniformSize;
159 uniformSize.reserve(maxUniformLocations);
161 for(int i = 0; i < numUniforms; ++i)
166 gl->GetActiveUniform(mGlProgram, i, maxLen, &written, &size, &type, name);
167 int location = gl->GetUniformLocation(mGlProgram, name);
168 uniformSize[location] = GetGLDataTypeSize(type);
170 Dali::Graphics::UniformInfo uniformInfo;
171 uniformInfo.name = name;
172 uniformInfo.uniformClass = IsSampler(type) ? Dali::Graphics::UniformClass::COMBINED_IMAGE_SAMPLER : Dali::Graphics::UniformClass::UNIFORM;
173 uniformInfo.location = IsSampler(type) ? 0 : location;
174 uniformInfo.binding = IsSampler(type) ? location : 0;
175 uniformInfo.bufferIndex = 0;
179 mUniformOpaques.push_back(uniformInfo);
183 mDefaultUniformBlock.members.push_back(uniformInfo);
187 // Re-order according to uniform locations.
188 if(mDefaultUniformBlock.members.size() > 1)
190 std::sort(mDefaultUniformBlock.members.begin(), mDefaultUniformBlock.members.end(), SortByLocation);
193 if(mUniformOpaques.size() > 1)
195 std::sort(mUniformOpaques.begin(), mUniformOpaques.end(), SortByLocation);
198 // Calculate the uniform offset
199 for(unsigned int i = 0; i < mDefaultUniformBlock.members.size(); ++i)
201 mDefaultUniformBlock.members[i].offset = i == 0 ? 0 : mDefaultUniformBlock.members[i - 1].offset + uniformSize[mDefaultUniformBlock.members[i - 1].location];
204 mDefaultUniformBlock.size = mDefaultUniformBlock.members.back().offset + uniformSize[mDefaultUniformBlock.members.back().location];
206 mUniformBlocks.push_back(mDefaultUniformBlock);
211 // TODO: Maybe this is not needed if uniform block is not support by dali shaders?
212 void Reflection::BuildUniformBlockReflection()
214 auto gl = mController.GetGL();
216 int numUniformBlocks = 0;
217 gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
219 mUniformBlocks.clear();
220 mUniformBlocks.resize(numUniformBlocks);
222 int uniformBlockMaxLength = 0;
223 gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &uniformBlockMaxLength);
225 char* uniformBlockName = new char[uniformBlockMaxLength];
226 for(int i = 0; i < numUniformBlocks; i++)
231 gl->GetActiveUniformBlockName(mGlProgram, i, uniformBlockMaxLength, &length, uniformBlockName);
232 gl->GetActiveUniformBlockiv(mGlProgram, i, GL_UNIFORM_BLOCK_BINDING, &blockBinding);
233 gl->GetActiveUniformBlockiv(mGlProgram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &blockDataSize);
235 Dali::Graphics::UniformBlockInfo uniformBlockInfo;
236 uniformBlockInfo.name = uniformBlockName;
237 uniformBlockInfo.size = blockDataSize;
238 uniformBlockInfo.binding = blockBinding;
241 gl->GetActiveUniformBlockiv(mGlProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &nUnis);
242 int* unifIndexes = new GLint[nUnis];
243 gl->GetActiveUniformBlockiv(mGlProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, unifIndexes);
246 gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniLen);
248 for(int unif = 0; unif < nUnis; ++unif)
250 int uniIndex = unifIndexes[unif];
254 gl->GetActiveUniform(mGlProgram, uniIndex, maxUniLen, &length, &size, &type, uniformName);
255 int location = gl->GetUniformLocation(mGlProgram, uniformName);
257 Dali::Graphics::UniformInfo uniform;
258 uniform.name = uniformName;
259 uniform.location = location;
260 uniformBlockInfo.members.push_back(uniform);
263 delete[] unifIndexes;
265 mUniformBlocks.push_back(uniformBlockInfo);
267 delete[] uniformBlockName;
270 uint32_t Reflection::GetVertexAttributeLocation(const std::string& name) const
272 for(auto&& attr : mVertexInputAttributes)
274 if(attr.name == name)
276 return attr.location;
279 return ERROR_ATTRIBUTE_NOT_FOUND;
282 Dali::Graphics::VertexInputAttributeFormat Reflection::GetVertexAttributeFormat(uint32_t location) const
284 if(location >= mVertexInputAttributes.size())
286 return Dali::Graphics::VertexInputAttributeFormat::UNDEFINED;
289 return mVertexInputAttributes[location].format;
292 std::string Reflection::GetVertexAttributeName(uint32_t location) const
294 if(location >= mVertexInputAttributes.size())
296 return std::string();
299 return mVertexInputAttributes[location].name;
302 std::vector<uint32_t> Reflection::GetVertexAttributeLocations() const
304 std::vector<uint32_t> locations;
305 for(auto&& attr : mVertexInputAttributes)
307 if(attr.format != Dali::Graphics::VertexInputAttributeFormat::UNDEFINED)
309 locations.push_back(attr.location);
316 uint32_t Reflection::GetUniformBlockCount() const
318 return mUniformBlocks.size();
321 uint32_t Reflection::GetUniformBlockBinding(uint32_t index) const
323 return index < mUniformBlocks.size() ? mUniformBlocks[index].binding : 0u;
326 uint32_t Reflection::GetUniformBlockSize(uint32_t index) const
328 return index < mUniformBlocks.size() ? mUniformBlocks[index].size : 0u;
331 bool Reflection::GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const
333 if(index >= mUniformBlocks.size())
338 const auto& block = mUniformBlocks[index];
340 out.name = block.name;
341 out.binding = block.binding;
342 out.descriptorSet = block.descriptorSet;
343 auto membersSize = block.members.size();
344 out.members.resize(membersSize);
345 out.size = block.size;
346 for(auto i = 0u; i < out.members.size(); ++i)
348 const auto& memberUniform = block.members[i];
349 out.members[i].name = memberUniform.name;
350 out.members[i].binding = block.binding;
351 out.members[i].uniformClass = Graphics::UniformClass::UNIFORM;
352 out.members[i].offset = memberUniform.offset;
353 out.members[i].location = memberUniform.location;
359 std::vector<uint32_t> Reflection::GetUniformBlockLocations() const
361 std::vector<uint32_t> retval{};
362 for(auto&& ubo : mUniformBlocks)
364 retval.emplace_back(ubo.binding);
369 std::string Reflection::GetUniformBlockName(uint32_t blockIndex) const
371 if(blockIndex < mUniformBlocks.size())
373 return mUniformBlocks[blockIndex].name;
377 return std::string();
381 uint32_t Reflection::GetUniformBlockMemberCount(uint32_t blockIndex) const
383 if(blockIndex < mUniformBlocks.size())
385 return static_cast<uint32_t>(mUniformBlocks[blockIndex].members.size());
393 std::string Reflection::GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const
395 if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size())
397 return mUniformBlocks[blockIndex].members[memberLocation].name;
401 return std::string();
405 uint32_t Reflection::GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const
407 if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size())
409 return mUniformBlocks[blockIndex].members[memberLocation].offset;
417 bool Reflection::GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const
420 for(auto&& ubo : mUniformBlocks)
422 for(auto&& member : ubo.members)
424 if(name == member.name || name == (ubo.name + "." + member.name))
427 out.location = member.location;
428 out.binding = ubo.binding;
429 out.bufferIndex = index;
430 out.offset = member.offset;
431 out.uniformClass = Graphics::UniformClass::UNIFORM;
439 for(auto&& uniform : mUniformOpaques)
441 if(uniform.name == name)
443 out.uniformClass = Graphics::UniformClass::COMBINED_IMAGE_SAMPLER;
444 out.binding = uniform.binding;
447 out.location = uniform.location;
455 std::vector<Dali::Graphics::UniformInfo> Reflection::GetSamplers() const
457 return mUniformOpaques;
460 Graphics::ShaderLanguage Reflection::GetLanguage() const
462 auto gl = mController.GetGL();
464 int majorVersion, minorVersion;
465 gl->GetIntegerv(GL_MAJOR_VERSION, &majorVersion);
466 gl->GetIntegerv(GL_MINOR_VERSION, &minorVersion);
467 printf("GL Version (integer) : %d.%d\n", majorVersion, minorVersion);
468 printf("GLSL Version : %s\n", gl->GetString(GL_SHADING_LANGUAGE_VERSION));
470 // TODO: the language version is hardcoded for now, but we may use what we get
471 // from GL_SHADING_LANGUAGE_VERSION?
472 return Graphics::ShaderLanguage::GLSL_3_2;
475 void Reflection::SetGlProgram(uint32_t glProgram)
477 mGlProgram = glProgram;
479 BuildVertexAttributeReflection();
480 BuildUniformReflection();
484 } // namespace Graphics