Removing GL usage from dali core
[platform/core/uifw/dali-core.git] / dali / internal / render / shaders / program.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/shaders/program.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring>
23 #include <map>
24
25 // INTERNAL INCLUDES
26 #include <dali/devel-api/common/hash.h>
27 #include <dali/graphics-api/graphics-controller.h>
28 #include <dali/graphics-api/graphics-program.h>
29 #include <dali/graphics-api/graphics-reflection.h>
30 #include <dali/integration-api/debug.h>
31 #include <dali/internal/common/shader-data.h>
32 #include <dali/internal/render/common/performance-monitor.h>
33 #include <dali/internal/render/shaders/program-cache.h>
34 #include <dali/public-api/common/constants.h>
35 #include <dali/public-api/common/dali-common.h>
36 #include <dali/public-api/common/dali-vector.h>
37
38 namespace Dali
39 {
40 namespace Internal
41 {
42 // LOCAL STUFF
43 namespace
44 {
45 const unsigned int NUMBER_OF_DEFAULT_UNIFORMS = static_cast<unsigned int>(Program::DefaultUniformIndex::COUNT);
46
47 /**
48  * List of all default uniforms used for quicker lookup
49  */
50 size_t DEFAULT_UNIFORM_HASHTABLE[NUMBER_OF_DEFAULT_UNIFORMS] =
51   {
52     CalculateHash(std::string("uModelMatrix")),
53     CalculateHash(std::string("uMvpMatrix")),
54     CalculateHash(std::string("uViewMatrix")),
55     CalculateHash(std::string("uModelView")),
56     CalculateHash(std::string("uNormalMatrix")),
57     CalculateHash(std::string("uProjection")),
58     CalculateHash(std::string("uSize")),
59     CalculateHash(std::string("uColor"))};
60
61 } // namespace
62
63 // IMPLEMENTATION
64
65 Program* Program::New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController, Graphics::UniquePtr<Graphics::Program>&& gfxProgram)
66 {
67   uint32_t programId{0u};
68
69   // Get program id and use it as hash for the cache
70   // in order to maintain current functionality as long as needed
71   gfxController.GetProgramParameter(*gfxProgram, 1, &programId);
72
73   size_t shaderHash = programId;
74
75   Program* program = cache.GetProgram(shaderHash);
76
77   if(nullptr == program)
78   {
79     // program not found so create it
80     program = new Program(cache, shaderData, gfxController, std::move(gfxProgram));
81     cache.AddProgram(shaderHash, program);
82   }
83
84   return program;
85 }
86
87 Program::Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& controller, Graphics::UniquePtr<Graphics::Program>&& gfxProgram)
88 : mCache(cache),
89   mProjectionMatrix(nullptr),
90   mViewMatrix(nullptr),
91   mGfxProgram(std::move(gfxProgram)),
92   mGfxController(controller),
93   mProgramData(shaderData)
94 {
95   BuildReflection(controller.GetProgramReflection(*mGfxProgram.get()));
96 }
97
98 Program::~Program() = default;
99
100 void Program::BuildReflection(const Graphics::Reflection& graphicsReflection)
101 {
102   mReflectionDefaultUniforms.clear();
103   mReflectionDefaultUniforms.resize(NUMBER_OF_DEFAULT_UNIFORMS);
104
105   auto uniformBlockCount = graphicsReflection.GetUniformBlockCount();
106
107   // add uniform block fields
108   for(auto i = 0u; i < uniformBlockCount; ++i)
109   {
110     Graphics::UniformBlockInfo uboInfo;
111     graphicsReflection.GetUniformBlock(i, uboInfo);
112
113     // for each member store data
114     for(const auto& item : uboInfo.members)
115     {
116       auto hashValue = CalculateHash(item.name);
117       mReflection.emplace_back(ReflectionUniformInfo{hashValue, false, item});
118
119       // update buffer index
120       mReflection.back().uniformInfo.bufferIndex = i;
121
122       // Update default uniforms
123       for(auto j = 0u; j < NUMBER_OF_DEFAULT_UNIFORMS; ++j)
124       {
125         if(hashValue == DEFAULT_UNIFORM_HASHTABLE[j])
126         {
127           mReflectionDefaultUniforms[j] = mReflection.back();
128           break;
129         }
130       }
131     }
132   }
133
134   // add samplers
135   auto samplers = graphicsReflection.GetSamplers();
136   for(const auto& sampler : samplers)
137   {
138     mReflection.emplace_back(ReflectionUniformInfo{CalculateHash(sampler.name), false, sampler});
139   }
140
141   // check for potential collisions
142   std::map<size_t, bool> hashTest;
143   bool                   hasCollisions(false);
144   for(auto&& item : mReflection)
145   {
146     if(hashTest.find(item.hashValue) == hashTest.end())
147     {
148       hashTest[item.hashValue] = false;
149     }
150     else
151     {
152       hashTest[item.hashValue] = true;
153       hasCollisions            = true;
154     }
155   }
156
157   // update collision flag for further use
158   if(hasCollisions)
159   {
160     for(auto&& item : mReflection)
161     {
162       item.hasCollision = hashTest[item.hashValue];
163     }
164   }
165 }
166
167 bool Program::GetUniform(const std::string& name, size_t hashedName, Graphics::UniformInfo& out) const
168 {
169   if(mReflection.empty())
170   {
171     return false;
172   }
173
174   hashedName = !hashedName ? CalculateHash(name, '[') : hashedName;
175
176   for(const ReflectionUniformInfo& item : mReflection)
177   {
178     if(item.hashValue == hashedName)
179     {
180       if(!item.hasCollision || item.uniformInfo.name == name)
181       {
182         out = item.uniformInfo;
183         return true;
184       }
185       else
186       {
187         return false;
188       }
189     }
190   }
191   return false;
192 }
193
194 const Graphics::UniformInfo* Program::GetDefaultUniform(DefaultUniformIndex defaultUniformIndex) const
195 {
196   if(mReflectionDefaultUniforms.empty())
197   {
198     return nullptr;
199   }
200
201   const auto value = &mReflectionDefaultUniforms[static_cast<uint32_t>(defaultUniformIndex)];
202   return &value->uniformInfo;
203 }
204
205 } // namespace Internal
206
207 } // namespace Dali