DALi Version 2.2.11
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-scene3d / utc-Dali-ShaderDefinitionFactory.cpp
1 /*
2  * Copyright (c) 2022 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 // Enable debug log for test coverage
19 #define DEBUG_ENABLED 1
20
21 // Disable this UTC until shader definition factory refactorize
22 #define ENABLE_SHADER_DEFINITION_FACTORY_UTC 0
23
24 #include <dali-test-suite-utils.h>
25 #include <set>
26 #include <string_view>
27 #include "dali-scene3d/public-api/loader/gltf2-loader.h"
28 #include "dali-scene3d/public-api/loader/node-definition.h"
29 #include "dali-scene3d/public-api/loader/resource-bundle.h"
30 #include "dali-scene3d/public-api/loader/shader-definition-factory.h"
31
32 using namespace Dali;
33 using namespace Dali::Scene3D::Loader;
34
35 namespace
36 {
37 #if ENABLE_SHADER_DEFINITION_FACTORY_UTC
38 MaterialDefinition& NewMaterialDefinition(ResourceBundle& resources)
39 {
40   resources.mMaterials.push_back({});
41   return resources.mMaterials.back().first;
42 }
43
44 MeshDefinition& NewMeshDefinition(ResourceBundle& resources)
45 {
46   resources.mMeshes.push_back({});
47   return resources.mMeshes.back().first;
48 }
49
50 void ClearMeshesAndMaterials(ResourceBundle& resources)
51 {
52   resources.mMaterials.clear();
53   resources.mMeshes.clear();
54 }
55 #endif
56
57 struct Context
58 {
59   ResourceBundle          resources;
60   ShaderDefinitionFactory factory;
61
62   Context()
63   {
64     factory.SetResources(resources);
65   }
66 };
67
68 #if ENABLE_SHADER_DEFINITION_FACTORY_UTC
69 struct ShaderParameters
70 {
71   MeshDefinition&     meshDef;
72   MaterialDefinition& materialDef;
73   NodeDefinition&     nodeDef;
74 };
75
76 struct Permutation
77 {
78   using ConfigureFn = void (*)(ShaderParameters&);
79
80   ConfigureFn configureFn;
81
82   std::set<std::string> defines;
83   RendererState::Type   rendererStateSet   = 0;
84   RendererState::Type   rendererStateClear = 0;
85 };
86
87 struct PermutationSet
88 {
89   std::vector<const Permutation*> permutations;
90   Index                           shaderIdx;
91 };
92 #endif
93
94 } // namespace
95
96 int UtcDaliShaderDefinitionFactoryProduceShaderInvalid(void)
97 {
98   Context ctx;
99
100   NodeDefinition                              nodeDef;
101   std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(new NodeDefinition::Renderable());
102   nodeDef.mRenderables.push_back(std::move(renderable));
103
104   DALI_TEST_CHECK(ctx.resources.mShaders.empty());
105
106   END_TEST;
107 }
108
109 int UtcDaliShaderDefinitionFactoryProduceShader(void)
110 {
111 #if ENABLE_SHADER_DEFINITION_FACTORY_UTC
112   Context ctx;
113   ctx.resources.mMaterials.push_back({});
114   ctx.resources.mMeshes.push_back({});
115
116   Permutation permutations[]{
117     {
118       [](ShaderParameters& p) {},
119       {},
120       RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK,
121     },
122     {
123       [](ShaderParameters& p) {
124         p.materialDef.mFlags |= MaterialDefinition::TRANSPARENCY;
125       },
126       {"THREE_TEX"},
127       RendererState::ALPHA_BLEND,
128       RendererState::DEPTH_WRITE,
129     },
130     {[](ShaderParameters& p) {
131        p.materialDef.mFlags |= MaterialDefinition::ALBEDO;
132        p.materialDef.mTextureStages.push_back({MaterialDefinition::ALBEDO, {}});
133      },
134      {"THREE_TEX", "BASECOLOR_TEX"}},
135     {[](ShaderParameters& p) {
136        p.materialDef.mTextureStages.push_back({MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS, {}});
137      },
138      {"THREE_TEX", "METALLIC_ROUGHNESS_TEX"}},
139     {[](ShaderParameters& p) {
140        p.materialDef.mFlags |= MaterialDefinition::NORMAL;
141        p.materialDef.mTextureStages.push_back({MaterialDefinition::NORMAL, {}});
142      },
143      {"THREE_TEX", "NORMAL_TEX"}},
144     {[](ShaderParameters& p) {
145        p.materialDef.mFlags |= MaterialDefinition::SUBSURFACE;
146      },
147      {"SSS"}},
148     {[](ShaderParameters& p) {
149        p.materialDef.SetAlphaCutoff(.5f);
150      },
151      {"ALPHA_TEST"}},
152     {[](ShaderParameters& p) {
153        p.materialDef.SetAlphaCutoff(1.f);
154      },
155      {"ALPHA_TEST"}},
156     {[](ShaderParameters& p) {
157        p.materialDef.mFlags |= MaterialDefinition::GLTF_CHANNELS;
158      },
159      {"GLTF_CHANNELS"}},
160     {[](ShaderParameters& p) {
161        p.meshDef.mJoints0.mBlob.mOffset  = 0;
162        p.meshDef.mWeights0.mBlob.mOffset = 0;
163      },
164      {"SKINNING"}},
165     {[](ShaderParameters& p) {
166        p.meshDef.mFlags |= MeshDefinition::FLIP_UVS_VERTICAL;
167      },
168      {"FLIP_V"}},
169     {
170       [](ShaderParameters& p) {
171         p.meshDef.mBlendShapes.push_back({});
172       },
173     },
174     {[](ShaderParameters& p) {
175        p.meshDef.mBlendShapes.back().deltas.mBlob.mOffset = 0;
176      },
177      {"MORPH_POSITION", "MORPH"}},
178     {[](ShaderParameters& p) {
179        p.meshDef.mBlendShapes.back().normals.mBlob.mOffset = 0;
180      },
181      {"MORPH_NORMAL", "MORPH"}},
182     {[](ShaderParameters& p) {
183        p.meshDef.mBlendShapes.back().tangents.mBlob.mOffset = 0;
184      },
185      {"MORPH_TANGENT", "MORPH"}},
186     {[](ShaderParameters& p) {
187        auto& blendShapes = p.meshDef.mBlendShapes;
188        DALI_ASSERT_ALWAYS(!blendShapes.empty() &&
189                           (blendShapes.back().deltas.mBlob.mOffset != MeshDefinition::INVALID ||
190                            blendShapes.back().normals.mBlob.mOffset != MeshDefinition::INVALID ||
191                            blendShapes.back().tangents.mBlob.mOffset != MeshDefinition::INVALID));
192        p.meshDef.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
193      },
194      {"MORPH_VERSION_2_0"}},
195
196     {[](ShaderParameters& p) {
197        p.materialDef.mFlags |= MaterialDefinition::OCCLUSION;
198      },
199
200      {"OCCLUSION"}},
201
202     {[](ShaderParameters& p) {
203        p.meshDef.mColors.mBlob.mOffset = 0;
204      },
205      {"COLOR_ATTRIBUTE"}},
206     {[](ShaderParameters& p) {
207        p.meshDef.mTangentType = Property::VECTOR4;
208      },
209      {"VEC4_TANGENT"}},
210   };
211
212   PermutationSet permSets[]{
213     // default
214     {{&permutations[0]}, 0},
215
216     // alpha
217     {{&permutations[0], &permutations[1]}, 1},
218
219     // three-texture setups
220     {{&permutations[0], &permutations[2]}, 2},
221     {{&permutations[0], &permutations[3]}, 2},
222     {{&permutations[0], &permutations[4]}, 2},
223     {{&permutations[0], &permutations[2], &permutations[3]}, 2},
224     {{&permutations[0], &permutations[3], &permutations[4]}, 2},
225     {{&permutations[0], &permutations[4], &permutations[2]}, 2},
226     {{&permutations[0], &permutations[2], &permutations[3], &permutations[4]}, 2},
227
228     // subsurface scattering
229     {{&permutations[0], &permutations[5]}, 3},
230
231     // alpha test
232     {{&permutations[0], &permutations[6]}, 4},
233     {{&permutations[0], &permutations[7]}, 4},
234
235     // glTF channels
236     {{&permutations[0], &permutations[8]}, 5},
237
238     // skinning
239     {{&permutations[0], &permutations[9]}, 6},
240
241     // flip uvs
242     {{&permutations[0], &permutations[10]}, 7},
243
244     // morphing
245     {{&permutations[0], &permutations[11], &permutations[12]}, 8},
246     {{&permutations[0], &permutations[11], &permutations[13]}, 9},
247     {{&permutations[0], &permutations[11], &permutations[14]}, 10},
248     {{&permutations[0], &permutations[11], &permutations[12], &permutations[13]}, 11},
249     {{&permutations[0], &permutations[11], &permutations[13], &permutations[14]}, 12},
250     {{&permutations[0], &permutations[11], &permutations[14], &permutations[12]}, 13},
251     {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14]}, 14},
252
253     {{&permutations[0], &permutations[11], &permutations[12], &permutations[15]}, 15},
254     {{&permutations[0], &permutations[11], &permutations[13], &permutations[15]}, 16},
255     {{&permutations[0], &permutations[11], &permutations[14], &permutations[15]}, 17},
256     {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[15]}, 18},
257     {{&permutations[0], &permutations[11], &permutations[13], &permutations[14], &permutations[15]}, 19},
258     {{&permutations[0], &permutations[11], &permutations[14], &permutations[12], &permutations[15]}, 20},
259     {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14], &permutations[15]}, 21},
260
261     // etc.
262     {{&permutations[0], &permutations[1], &permutations[2]}, 1},
263     {{&permutations[0], &permutations[1], &permutations[3]}, 1},
264     {{&permutations[0], &permutations[1], &permutations[2], &permutations[3]}, 1},
265
266     // occlusion
267     {{&permutations[0], &permutations[16]}, 22},
268   };
269
270   for(auto& ps : permSets)
271   {
272     static int tc = 0;
273     tet_printf("Test %d's tc\n", ++tc);
274     auto modelRenderable          = new ModelRenderable();
275     modelRenderable->mMeshIdx     = 0;
276     modelRenderable->mMaterialIdx = 0;
277
278     NodeDefinition                              nodeDef;
279     std::unique_ptr<NodeDefinition::Renderable> renderable;
280     renderable.reset(modelRenderable);
281     nodeDef.mRenderables.push_back(std::move(renderable));
282
283     auto&            meshDef     = NewMeshDefinition(ctx.resources);
284     auto&            materialDef = NewMaterialDefinition(ctx.resources);
285     ShaderParameters sp{meshDef, materialDef, nodeDef};
286
287     std::set<std::string> defines;
288     RendererState::Type   rendererState = 0;
289     for(auto p : ps.permutations)
290     {
291       p->configureFn(sp);
292       defines.insert(p->defines.begin(), p->defines.end());
293       rendererState = (rendererState | p->rendererStateSet) & ~p->rendererStateClear;
294     }
295
296     for(auto& renderable : nodeDef.mRenderables)
297     {
298       auto shaderIdx = ctx.factory.ProduceShader(*renderable);
299       DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx);
300
301       auto& shaderDef = ctx.resources.mShaders[shaderIdx].first;
302       DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState);
303
304       uint32_t definesUnmatched = shaderDef.mDefines.size();
305       for(auto& define : shaderDef.mDefines)
306       {
307         auto iFind = defines.find(define);
308         if(iFind != defines.end())
309         {
310           defines.erase(iFind);
311           --definesUnmatched;
312         }
313         else
314         {
315           break;
316         }
317       }
318       if(!defines.empty())
319       {
320         std::ostringstream oss;
321         oss << "Need to check below defines :\n";
322         for(auto& it : defines)
323         {
324           oss << it << "\n";
325         }
326         tet_printf("%s\n", oss.str().c_str());
327       }
328
329       DALI_TEST_CHECK(defines.empty());
330       DALI_TEST_EQUAL(0, definesUnmatched);
331
332       auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"];
333       DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT);
334
335       auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"];
336       DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX);
337     }
338
339     ClearMeshesAndMaterials(ctx.resources);
340   }
341 #else
342   DALI_TEST_CHECK(true);
343 #endif
344
345   END_TEST;
346 }