2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 // Enable debug log for test coverage
19 #define DEBUG_ENABLED 1
21 #include "dali-scene-loader/public-api/gltf2-loader.h"
22 #include "dali-scene-loader/public-api/shader-definition-factory.h"
23 #include "dali-scene-loader/public-api/node-definition.h"
24 #include "dali-scene-loader/public-api/resource-bundle.h"
25 #include <dali-test-suite-utils.h>
26 #include <string_view>
30 using namespace Dali::SceneLoader;
35 bool EndsWith(const std::string& str, const std::string& suffix) // ends_width() is C++20
37 return str.size() >= suffix.size() && str.substr(str.size() - suffix.size()).compare(suffix) == 0;
40 MaterialDefinition& NewMaterialDefinition(ResourceBundle& resources)
42 resources.mMaterials.push_back({});
43 return resources.mMaterials.back().first;
46 MeshDefinition& NewMeshDefinition(ResourceBundle& resources)
48 resources.mMeshes.push_back({});
49 return resources.mMeshes.back().first;
52 void ClearMeshesAndMaterials(ResourceBundle& resources)
54 resources.mMaterials.clear();
55 resources.mMeshes.clear();
60 ResourceBundle resources;
61 ShaderDefinitionFactory factory;
65 factory.SetResources(resources);
69 struct ShaderParameters
71 MeshDefinition& meshDef;
72 MaterialDefinition& materialDef;
73 NodeDefinition& nodeDef;
78 using ConfigureFn = void(*)(ShaderParameters&);
80 ConfigureFn configureFn;
82 std::set<std::string> defines;
83 RendererState::Type rendererStateSet = 0;
84 RendererState::Type rendererStateClear = 0;
89 std::vector<const Permutation*> permutations;
95 int UtcDaliShaderDefinitionFactoryProduceShaderInvalid(void)
99 NodeDefinition nodeDef;
100 nodeDef.mRenderable.reset(new NodeDefinition::Renderable());
102 DALI_TEST_EQUAL(INVALID_INDEX, ctx.factory.ProduceShader(nodeDef));
103 DALI_TEST_CHECK(ctx.resources.mShaders.empty());
108 int UtcDaliShaderDefinitionFactoryProduceShader(void)
111 ctx.resources.mMaterials.push_back({});
112 ctx.resources.mMeshes.push_back({});
114 Permutation permutations[]{
116 [](ShaderParameters& p) {},
118 RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK,
121 [](ShaderParameters& p) {
122 p.materialDef.mFlags |= MaterialDefinition::TRANSPARENCY;
125 RendererState::ALPHA_BLEND,
126 RendererState::DEPTH_WRITE,
129 [](ShaderParameters& p) {
130 p.materialDef.mTextureStages.push_back({ MaterialDefinition::ALBEDO, {} });
135 [](ShaderParameters& p) {
136 p.materialDef.mTextureStages.push_back({ MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS, {} });
141 [](ShaderParameters& p) {
142 p.materialDef.mTextureStages.push_back({ MaterialDefinition::NORMAL, {} });
147 [](ShaderParameters& p) {
148 p.materialDef.mFlags |= MaterialDefinition::SUBSURFACE;
153 [](ShaderParameters& p) {
154 p.materialDef.SetAlphaCutoff(.5f);
159 [](ShaderParameters& p) {
160 p.materialDef.SetAlphaCutoff(1.f);
165 [](ShaderParameters& p) {
166 p.materialDef.mFlags |= MaterialDefinition::GLTF_CHANNELS;
171 [](ShaderParameters& p) {
172 p.meshDef.mJoints0.mBlob.mOffset = 0;
173 p.meshDef.mWeights0.mBlob.mOffset = 0;
178 [](ShaderParameters& p) {
179 p.meshDef.mFlags |= MeshDefinition::FLIP_UVS_VERTICAL;
184 [](ShaderParameters& p) {
185 p.meshDef.mBlendShapes.push_back({});
189 [](ShaderParameters& p) {
190 p.meshDef.mBlendShapes.back().deltas.mBlob.mOffset = 0;
192 { "MORPH_POSITION", "MORPH" }
195 [](ShaderParameters& p) {
196 p.meshDef.mBlendShapes.back().normals.mBlob.mOffset = 0;
198 { "MORPH_NORMAL", "MORPH" }
201 [](ShaderParameters& p) {
202 p.meshDef.mBlendShapes.back().tangents.mBlob.mOffset = 0;
204 { "MORPH_TANGENT", "MORPH" }
207 [](ShaderParameters& p) {
208 auto& blendShapes = p.meshDef.mBlendShapes;
209 DALI_ASSERT_ALWAYS(!blendShapes.empty() &&
210 (blendShapes.back().deltas.mBlob.mOffset != MeshDefinition::INVALID ||
211 blendShapes.back().normals.mBlob.mOffset != MeshDefinition::INVALID ||
212 blendShapes.back().tangents.mBlob.mOffset != MeshDefinition::INVALID));
213 p.meshDef.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
215 { "MORPH_VERSION_2_0" }
219 PermutationSet permSets[] {
221 { { &permutations[0] }, 0 },
224 { { &permutations[0], &permutations[1] }, 1 },
226 // three-texture setups
227 { { &permutations[0], &permutations[2] }, 2 },
228 { { &permutations[0], &permutations[3] }, 2 },
229 { { &permutations[0], &permutations[4] }, 2 },
230 { { &permutations[0], &permutations[2], &permutations[3] }, 2 },
231 { { &permutations[0], &permutations[3], &permutations[4] }, 2 },
232 { { &permutations[0], &permutations[4], &permutations[2] }, 2 },
233 { { &permutations[0], &permutations[2], &permutations[3], &permutations[4] }, 2 },
235 // subsurface scattering
236 { { &permutations[0], &permutations[5] }, 3 },
239 { { &permutations[0], &permutations[6] }, 4 },
240 { { &permutations[0], &permutations[7] }, 4 },
243 { { &permutations[0], &permutations[8] }, 5 },
246 { { &permutations[0], &permutations[9] }, 6 },
249 { { &permutations[0], &permutations[10] }, 7 },
252 { { &permutations[0], &permutations[11], &permutations[12] }, 8 },
253 { { &permutations[0], &permutations[11], &permutations[13] }, 9 },
254 { { &permutations[0], &permutations[11], &permutations[14] }, 10 },
255 { { &permutations[0], &permutations[11], &permutations[12], &permutations[13] }, 11 },
256 { { &permutations[0], &permutations[11], &permutations[13], &permutations[14] }, 12 },
257 { { &permutations[0], &permutations[11], &permutations[14], &permutations[12] }, 13 },
258 { { &permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14] }, 14 },
260 { { &permutations[0], &permutations[11], &permutations[12], &permutations[15] }, 15 },
261 { { &permutations[0], &permutations[11], &permutations[13], &permutations[15] }, 16 },
262 { { &permutations[0], &permutations[11], &permutations[14], &permutations[15] }, 17 },
263 { { &permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[15] }, 18 },
264 { { &permutations[0], &permutations[11], &permutations[13], &permutations[14], &permutations[15] }, 19 },
265 { { &permutations[0], &permutations[11], &permutations[14], &permutations[12], &permutations[15] }, 20 },
266 { { &permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14], &permutations[15] }, 21 },
269 { { &permutations[0], &permutations[1], &permutations[2] }, 1 },
270 { { &permutations[0], &permutations[1], &permutations[3] }, 1 },
271 { { &permutations[0], &permutations[1], &permutations[2], &permutations[3] }, 1 },
273 for(auto& ps: permSets)
275 printf("%ld\n", &ps - permSets);
277 auto modelNode = new ModelNode();
278 modelNode->mMeshIdx = 0;
279 modelNode->mMaterialIdx = 0;
281 NodeDefinition nodeDef;
282 nodeDef.mRenderable.reset(modelNode);
284 auto& meshDef = NewMeshDefinition(ctx.resources);
285 auto& materialDef = NewMaterialDefinition(ctx.resources);
286 ShaderParameters sp{ meshDef, materialDef, nodeDef };
288 std::set<std::string> defines;
289 RendererState::Type rendererState = 0;
290 for (auto p : ps.permutations)
293 defines.insert(p->defines.begin(), p->defines.end());
294 rendererState = (rendererState | p->rendererStateSet) & ~p->rendererStateClear;
297 auto shaderIdx = ctx.factory.ProduceShader(nodeDef);
298 DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx);
300 auto& shaderDef = ctx.resources.mShaders[shaderIdx].first;
301 DALI_TEST_CHECK(EndsWith(shaderDef.mVertexShaderPath, ".vsh"));
302 DALI_TEST_CHECK(EndsWith(shaderDef.mFragmentShaderPath, ".fsh"));
303 DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState);
305 uint32_t definesUnmatched = shaderDef.mDefines.size();
306 for (auto& d: shaderDef.mDefines)
308 auto iFind = defines.find(d);
309 if (iFind != defines.end())
311 defines.erase(iFind);
316 printf("mismatched: %s\n", d.c_str());
321 DALI_TEST_CHECK(defines.empty());
322 DALI_TEST_EQUAL(0, definesUnmatched);
324 printf("defines OK\n");
326 auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"];
327 DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT);
329 auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"];
330 DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX);
332 ClearMeshesAndMaterials(ctx.resources);