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