[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-scene3d / utc-Dali-ShaderManager.cpp
1 /*
2  * Copyright (c) 2023 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-scene3d/public-api/loader/node-definition.h>
22 #include <dali-scene3d/public-api/loader/resource-bundle.h>
23 #include <dali-scene3d/public-api/loader/shader-manager.h>
24 #include <dali-test-suite-utils.h>
25 #include <set>
26 #include <string_view>
27
28 using namespace Dali;
29 using namespace Dali::Scene3D::Loader;
30
31 namespace
32 {
33 struct Context
34 {
35   ResourceBundle resources;
36 };
37
38 struct ShaderParameters
39 {
40   MeshDefinition&     meshDefinition;
41   MaterialDefinition& materialDefinition;
42   NodeDefinition&     nodeDefinition;
43 };
44
45 struct Permutation
46 {
47   using ConfigureFn = void (*)(ShaderParameters&);
48
49   ConfigureFn configureFn;
50
51   std::set<ShaderOption::Type> options;
52   RendererState::Type          rendererStateSet   = 0;
53   RendererState::Type          rendererStateClear = 0;
54 };
55
56 struct PermutationSet
57 {
58   std::vector<const Permutation*> permutations;
59 };
60
61 } // namespace
62
63 int UtcDaliShaderManagerProduceShader(void)
64 {
65   Context ctx;
66   ctx.resources.mMaterials.push_back({});
67   ctx.resources.mMeshes.push_back({});
68
69   Permutation permutations[]{
70     {
71       //0
72       [](ShaderParameters& p) {},
73       {},
74       RendererState::DEPTH_TEST | RendererState::CULL_BACK,
75     },
76     {
77       //1
78       [](ShaderParameters& p) {
79         p.materialDefinition.mFlags |= MaterialDefinition::TRANSPARENCY;
80       },
81       {ShaderOption::Type::THREE_TEXTURE},
82       RendererState::ALPHA_BLEND,
83     },
84     {//2
85      [](ShaderParameters& p) {
86        p.materialDefinition.mFlags |= MaterialDefinition::ALBEDO;
87        p.materialDefinition.mTextureStages.push_back({MaterialDefinition::ALBEDO, {}});
88      },
89      {ShaderOption::Type::THREE_TEXTURE, ShaderOption::Type::BASE_COLOR_TEXTURE}},
90     {//3
91      [](ShaderParameters& p) {
92        p.materialDefinition.mTextureStages.push_back({MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS, {}});
93      },
94      {ShaderOption::Type::THREE_TEXTURE, ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE}},
95     {//4
96      [](ShaderParameters& p) {
97        p.materialDefinition.mFlags |= MaterialDefinition::NORMAL;
98        p.materialDefinition.mTextureStages.push_back({MaterialDefinition::NORMAL, {}});
99      },
100      {ShaderOption::Type::THREE_TEXTURE, ShaderOption::Type::NORMAL_TEXTURE}},
101     {//5
102      [](ShaderParameters& p) {
103        p.materialDefinition.mFlags |= MaterialDefinition::SUBSURFACE;
104      },
105      {ShaderOption::Type::SUBSURFACE}},
106     {//6
107      [](ShaderParameters& p) {
108        p.materialDefinition.SetAlphaCutoff(.5f);
109      },
110      {ShaderOption::Type::ALPHA_TEST}},
111     {//7
112      [](ShaderParameters& p) {
113        p.materialDefinition.SetAlphaCutoff(1.f);
114      },
115      {ShaderOption::Type::ALPHA_TEST}},
116     {//8
117      [](ShaderParameters& p) {
118        p.materialDefinition.mFlags |= MaterialDefinition::GLTF_CHANNELS;
119      },
120      {ShaderOption::Type::GLTF_CHANNELS}},
121     {//9
122      [](ShaderParameters& p) {
123        p.meshDefinition.mJoints[0].mBlob.mOffset  = 0;
124        p.meshDefinition.mWeights[0].mBlob.mOffset = 0;
125      },
126      {ShaderOption::Type::SKINNING}},
127     {//10
128      [](ShaderParameters& p) {
129        p.meshDefinition.mFlags |= MeshDefinition::FLIP_UVS_VERTICAL;
130      },
131      {ShaderOption::Type::FLIP_UVS_VERTICAL}},
132     {
133       //11
134       [](ShaderParameters& p) {
135         p.meshDefinition.mBlendShapes.push_back({});
136       },
137     },
138     {//12
139      [](ShaderParameters& p) {
140        p.meshDefinition.mBlendShapes.back().deltas.mBlob.mOffset = 0;
141      },
142      {ShaderOption::Type::MORPH_POSITION}},
143     {//13
144      [](ShaderParameters& p) {
145        p.meshDefinition.mBlendShapes.back().normals.mBlob.mOffset = 0;
146      },
147      {ShaderOption::Type::MORPH_NORMAL}},
148     {//14
149      [](ShaderParameters& p) {
150        p.meshDefinition.mBlendShapes.back().tangents.mBlob.mOffset = 0;
151      },
152      {ShaderOption::Type::MORPH_TANGENT}},
153     {//15
154      [](ShaderParameters& p) {
155        auto& blendShapes = p.meshDefinition.mBlendShapes;
156        DALI_ASSERT_ALWAYS(!blendShapes.empty() &&
157                           (blendShapes.back().deltas.mBlob.mOffset != MeshDefinition::INVALID ||
158                            blendShapes.back().normals.mBlob.mOffset != MeshDefinition::INVALID ||
159                            blendShapes.back().tangents.mBlob.mOffset != MeshDefinition::INVALID));
160        p.meshDefinition.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
161      },
162      {ShaderOption::Type::MORPH_VERSION_2_0}},
163
164     {//16
165      [](ShaderParameters& p) {
166        p.materialDefinition.mFlags |= MaterialDefinition::OCCLUSION;
167      },
168      {ShaderOption::Type::OCCLUSION}},
169
170     {//17
171      [](ShaderParameters& p) {
172        p.meshDefinition.mColors[0].mBlob.mOffset = 0;
173      },
174      {ShaderOption::Type::COLOR_ATTRIBUTE}},
175     {//18
176      [](ShaderParameters& p) {
177        p.meshDefinition.mTangentType = Property::VECTOR4;
178      },
179      {ShaderOption::Type::VEC4_TANGENT}},
180   };
181
182   PermutationSet permutationSets[]{
183     // default
184     {{&permutations[0]}},
185
186     // alpha
187     {{&permutations[0], &permutations[1]}},
188
189     // three-texture setups
190     {{&permutations[0], &permutations[2]}},
191     {{&permutations[0], &permutations[3]}},
192     {{&permutations[0], &permutations[4]}},
193     {{&permutations[0], &permutations[2], &permutations[3]}},
194     {{&permutations[0], &permutations[3], &permutations[4]}},
195     {{&permutations[0], &permutations[4], &permutations[2]}},
196     {{&permutations[0], &permutations[2], &permutations[3], &permutations[4]}},
197
198     // subsurface scattering
199     {{&permutations[0], &permutations[5]}},
200
201     // alpha test
202     {{&permutations[0], &permutations[6]}},
203     {{&permutations[0], &permutations[7]}},
204
205     // glTF channels
206     {{&permutations[0], &permutations[8]}},
207
208     // skinning
209     {{&permutations[0], &permutations[9]}},
210
211     // flip uvs
212     {{&permutations[0], &permutations[10]}},
213
214     // morphing
215     {{&permutations[0], &permutations[11], &permutations[12]}},
216     {{&permutations[0], &permutations[11], &permutations[13]}},
217     {{&permutations[0], &permutations[11], &permutations[14]}},
218     {{&permutations[0], &permutations[11], &permutations[12], &permutations[13]}},
219     {{&permutations[0], &permutations[11], &permutations[13], &permutations[14]}},
220     {{&permutations[0], &permutations[11], &permutations[14], &permutations[12]}},
221     {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14]}},
222
223     {{&permutations[0], &permutations[11], &permutations[12], &permutations[15]}},
224     {{&permutations[0], &permutations[11], &permutations[13], &permutations[15]}},
225     {{&permutations[0], &permutations[11], &permutations[14], &permutations[15]}},
226     {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[15]}},
227     {{&permutations[0], &permutations[11], &permutations[13], &permutations[14], &permutations[15]}},
228     {{&permutations[0], &permutations[11], &permutations[14], &permutations[12], &permutations[15]}},
229     {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14], &permutations[15]}},
230
231     // etc.
232     {{&permutations[0], &permutations[1], &permutations[2]}},
233     {{&permutations[0], &permutations[1], &permutations[3]}},
234     {{&permutations[0], &permutations[1], &permutations[2], &permutations[3]}},
235
236     // occlusion
237     {{&permutations[0], &permutations[16]}},
238   };
239
240   TestApplication app;
241   ShaderManager   shaderManager;
242   for(auto& permutationSet : permutationSets)
243   {
244     static int tc = 0;
245     tet_printf("Test %d's tc\n", ++tc);
246     auto modelRenderable          = new ModelRenderable();
247     modelRenderable->mMeshIdx     = 0;
248     modelRenderable->mMaterialIdx = 0;
249
250     NodeDefinition                              nodeDefinition;
251     std::unique_ptr<NodeDefinition::Renderable> renderable;
252     renderable.reset(modelRenderable);
253     nodeDefinition.mRenderables.push_back(std::move(renderable));
254
255     MeshDefinition     meshDefinition;
256     MaterialDefinition materialDefinition;
257     ShaderParameters   shaderParameter{meshDefinition, materialDefinition, nodeDefinition};
258
259     // Only define skinning accessors for skinning test...
260     if(permutationSet.permutations.size() > 1)
261     {
262       auto& checkP = permutationSet.permutations[1];
263       if(auto search = checkP->options.find(ShaderOption::Type::SKINNING);
264          search != checkP->options.end())
265       {
266         meshDefinition.mJoints.push_back(MeshDefinition::Accessor{MeshDefinition::Blob{0, 0}, {}});
267         meshDefinition.mWeights.push_back(MeshDefinition::Accessor{MeshDefinition::Blob{0, 0}, {}});
268       }
269     }
270     std::set<std::string> defines;
271     ShaderOption          option1;
272     RendererState::Type   rendererState = 0;
273     for(auto permutation : permutationSet.permutations)
274     {
275       permutation->configureFn(shaderParameter);
276       if(materialDefinition.mFlags & MaterialDefinition::TRANSPARENCY)
277       {
278         option1.SetTransparency();
279       }
280       for(auto&& optionType : permutation->options)
281       {
282         option1.AddOption(optionType);
283       }
284       // No permutation uses extra joint weights.
285       option1.AddJointMacros(0);
286       rendererState = (rendererState | permutation->rendererStateSet) & ~permutation->rendererStateClear;
287     }
288     option1.AddOption(ShaderOption::Type::THREE_TEXTURE);
289
290     ShaderOption option2 = shaderManager.ProduceShaderOption(materialDefinition, meshDefinition);
291
292     Shader shaderFromOption1 = shaderManager.ProduceShader(option1);
293     Shader shaderFromOption2 = shaderManager.ProduceShader(option2);
294     DALI_TEST_EQUAL(option1.GetOptionHash(), option2.GetOptionHash());
295     DALI_TEST_EQUAL(shaderFromOption1, shaderFromOption2);
296
297     RendererState::Type rendererStateFromMaterialDefinition = shaderManager.GetRendererState(materialDefinition);
298     DALI_TEST_EQUAL(rendererStateFromMaterialDefinition, rendererState);
299   }
300
301   END_TEST;
302 }
303
304 int UtcDaliShaderManagerAddAndRemoveLights(void)
305 {
306   TestApplication app;
307   ShaderManager   shaderManager;
308
309   ShaderOption option1;
310   option1.AddOption(ShaderOption::Type::THREE_TEXTURE);
311   Dali::Shader shader1 = shaderManager.ProduceShader(option1);
312
313   ShaderOption option2;
314   option2.AddOption(ShaderOption::Type::BASE_COLOR_TEXTURE);
315   Dali::Shader shader2 = shaderManager.ProduceShader(option2);
316
317   DALI_TEST_NOT_EQUALS(shader1, shader2, 0.1f, TEST_LOCATION);
318   DALI_TEST_EQUALS(shader1.GetProperty<int>(shader1.GetPropertyIndex("uLightCount")), 0, TEST_LOCATION);
319   DALI_TEST_EQUALS(shader2.GetProperty<int>(shader2.GetPropertyIndex("uLightCount")), 0, TEST_LOCATION);
320
321   Scene3D::Light light = Scene3D::Light::New();
322   shaderManager.AddLight(light);
323
324   DALI_TEST_EQUALS(shader1.GetProperty<int>(shader1.GetPropertyIndex("uLightCount")), 1, TEST_LOCATION);
325   DALI_TEST_EQUALS(shader2.GetProperty<int>(shader2.GetPropertyIndex("uLightCount")), 1, TEST_LOCATION);
326
327   ShaderOption option3;
328   option3.AddOption(ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE);
329   Dali::Shader shader3 = shaderManager.ProduceShader(option3);
330
331   DALI_TEST_NOT_EQUALS(shader1, shader3, 0.1f, TEST_LOCATION);
332   DALI_TEST_NOT_EQUALS(shader2, shader3, 0.1f, TEST_LOCATION);
333
334   DALI_TEST_EQUALS(shader3.GetProperty<int>(shader3.GetPropertyIndex("uLightCount")), 1, TEST_LOCATION);
335
336   END_TEST;
337 }