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