2 * Copyright (c) 2022 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-test-suite-utils.h>
23 #include <string_view>
24 #include "dali-scene-loader/public-api/gltf2-loader.h"
25 #include "dali-scene-loader/public-api/node-definition.h"
26 #include "dali-scene-loader/public-api/resource-bundle.h"
27 #include "dali-scene-loader/public-api/shader-definition-factory.h"
30 using namespace Dali::SceneLoader;
34 bool EndsWith(const std::string& str, const std::string& suffix) // ends_width() is C++20
36 return str.size() >= suffix.size() && str.substr(str.size() - suffix.size()).compare(suffix) == 0;
39 MaterialDefinition& NewMaterialDefinition(ResourceBundle& resources)
41 resources.mMaterials.push_back({});
42 return resources.mMaterials.back().first;
45 MeshDefinition& NewMeshDefinition(ResourceBundle& resources)
47 resources.mMeshes.push_back({});
48 return resources.mMeshes.back().first;
51 void ClearMeshesAndMaterials(ResourceBundle& resources)
53 resources.mMaterials.clear();
54 resources.mMeshes.clear();
59 ResourceBundle resources;
60 ShaderDefinitionFactory factory;
64 factory.SetResources(resources);
68 struct ShaderParameters
70 MeshDefinition& meshDef;
71 MaterialDefinition& materialDef;
72 NodeDefinition& nodeDef;
77 using ConfigureFn = void (*)(ShaderParameters&);
79 ConfigureFn configureFn;
81 std::set<std::string> defines;
82 RendererState::Type rendererStateSet = 0;
83 RendererState::Type rendererStateClear = 0;
88 std::vector<const Permutation*> permutations;
94 int UtcDaliShaderDefinitionFactoryProduceShaderInvalid(void)
98 NodeDefinition nodeDef;
99 nodeDef.mRenderable.reset(new NodeDefinition::Renderable());
101 DALI_TEST_EQUAL(INVALID_INDEX, ctx.factory.ProduceShader(nodeDef));
102 DALI_TEST_CHECK(ctx.resources.mShaders.empty());
107 int UtcDaliShaderDefinitionFactoryProduceShader(void)
110 ctx.resources.mMaterials.push_back({});
111 ctx.resources.mMeshes.push_back({});
113 Permutation permutations[]{
115 [](ShaderParameters& p) {},
117 RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK,
120 [](ShaderParameters& p) {
121 p.materialDef.mFlags |= MaterialDefinition::TRANSPARENCY;
124 RendererState::ALPHA_BLEND,
125 RendererState::DEPTH_WRITE,
127 {[](ShaderParameters& p) {
128 p.materialDef.mTextureStages.push_back({MaterialDefinition::ALBEDO, {}});
131 {[](ShaderParameters& p) {
132 p.materialDef.mTextureStages.push_back({MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS, {}});
135 {[](ShaderParameters& p) {
136 p.materialDef.mTextureStages.push_back({MaterialDefinition::NORMAL, {}});
139 {[](ShaderParameters& p) {
140 p.materialDef.mFlags |= MaterialDefinition::SUBSURFACE;
143 {[](ShaderParameters& p) {
144 p.materialDef.SetAlphaCutoff(.5f);
147 {[](ShaderParameters& p) {
148 p.materialDef.SetAlphaCutoff(1.f);
151 {[](ShaderParameters& p) {
152 p.materialDef.mFlags |= MaterialDefinition::GLTF_CHANNELS;
155 {[](ShaderParameters& p) {
156 p.meshDef.mJoints0.mBlob.mOffset = 0;
157 p.meshDef.mWeights0.mBlob.mOffset = 0;
160 {[](ShaderParameters& p) {
161 p.meshDef.mFlags |= MeshDefinition::FLIP_UVS_VERTICAL;
165 [](ShaderParameters& p) {
166 p.meshDef.mBlendShapes.push_back({});
169 {[](ShaderParameters& p) {
170 p.meshDef.mBlendShapes.back().deltas.mBlob.mOffset = 0;
172 {"MORPH_POSITION", "MORPH"}},
173 {[](ShaderParameters& p) {
174 p.meshDef.mBlendShapes.back().normals.mBlob.mOffset = 0;
176 {"MORPH_NORMAL", "MORPH"}},
177 {[](ShaderParameters& p) {
178 p.meshDef.mBlendShapes.back().tangents.mBlob.mOffset = 0;
180 {"MORPH_TANGENT", "MORPH"}},
181 {[](ShaderParameters& p) {
182 auto& blendShapes = p.meshDef.mBlendShapes;
183 DALI_ASSERT_ALWAYS(!blendShapes.empty() &&
184 (blendShapes.back().deltas.mBlob.mOffset != MeshDefinition::INVALID ||
185 blendShapes.back().normals.mBlob.mOffset != MeshDefinition::INVALID ||
186 blendShapes.back().tangents.mBlob.mOffset != MeshDefinition::INVALID));
187 p.meshDef.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
189 {"MORPH_VERSION_2_0"}},
191 {[](ShaderParameters& p) {
192 p.materialDef.mFlags |= MaterialDefinition::OCCLUSION;
198 PermutationSet permSets[]{
200 {{&permutations[0]}, 0},
203 {{&permutations[0], &permutations[1]}, 1},
205 // three-texture setups
206 {{&permutations[0], &permutations[2]}, 2},
207 {{&permutations[0], &permutations[3]}, 2},
208 {{&permutations[0], &permutations[4]}, 2},
209 {{&permutations[0], &permutations[2], &permutations[3]}, 2},
210 {{&permutations[0], &permutations[3], &permutations[4]}, 2},
211 {{&permutations[0], &permutations[4], &permutations[2]}, 2},
212 {{&permutations[0], &permutations[2], &permutations[3], &permutations[4]}, 2},
214 // subsurface scattering
215 {{&permutations[0], &permutations[5]}, 3},
218 {{&permutations[0], &permutations[6]}, 4},
219 {{&permutations[0], &permutations[7]}, 4},
222 {{&permutations[0], &permutations[8]}, 5},
225 {{&permutations[0], &permutations[9]}, 6},
228 {{&permutations[0], &permutations[10]}, 7},
231 {{&permutations[0], &permutations[11], &permutations[12]}, 8},
232 {{&permutations[0], &permutations[11], &permutations[13]}, 9},
233 {{&permutations[0], &permutations[11], &permutations[14]}, 10},
234 {{&permutations[0], &permutations[11], &permutations[12], &permutations[13]}, 11},
235 {{&permutations[0], &permutations[11], &permutations[13], &permutations[14]}, 12},
236 {{&permutations[0], &permutations[11], &permutations[14], &permutations[12]}, 13},
237 {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14]}, 14},
239 {{&permutations[0], &permutations[11], &permutations[12], &permutations[15]}, 15},
240 {{&permutations[0], &permutations[11], &permutations[13], &permutations[15]}, 16},
241 {{&permutations[0], &permutations[11], &permutations[14], &permutations[15]}, 17},
242 {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[15]}, 18},
243 {{&permutations[0], &permutations[11], &permutations[13], &permutations[14], &permutations[15]}, 19},
244 {{&permutations[0], &permutations[11], &permutations[14], &permutations[12], &permutations[15]}, 20},
245 {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14], &permutations[15]}, 21},
248 {{&permutations[0], &permutations[1], &permutations[2]}, 1},
249 {{&permutations[0], &permutations[1], &permutations[3]}, 1},
250 {{&permutations[0], &permutations[1], &permutations[2], &permutations[3]}, 1},
253 {{&permutations[0], &permutations[16]}, 22},
256 for(auto& ps : permSets)
258 printf("%ld\n", &ps - permSets);
260 auto modelNode = new ModelNode();
261 modelNode->mMeshIdx = 0;
262 modelNode->mMaterialIdx = 0;
264 NodeDefinition nodeDef;
265 nodeDef.mRenderable.reset(modelNode);
267 auto& meshDef = NewMeshDefinition(ctx.resources);
268 auto& materialDef = NewMaterialDefinition(ctx.resources);
269 ShaderParameters sp{meshDef, materialDef, nodeDef};
271 std::set<std::string> defines;
272 RendererState::Type rendererState = 0;
273 for(auto p : ps.permutations)
276 defines.insert(p->defines.begin(), p->defines.end());
277 rendererState = (rendererState | p->rendererStateSet) & ~p->rendererStateClear;
280 auto shaderIdx = ctx.factory.ProduceShader(nodeDef);
281 DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx);
283 auto& shaderDef = ctx.resources.mShaders[shaderIdx].first;
284 DALI_TEST_CHECK(EndsWith(shaderDef.mVertexShaderPath, ".vsh"));
285 DALI_TEST_CHECK(EndsWith(shaderDef.mFragmentShaderPath, ".fsh"));
286 DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState);
288 uint32_t definesUnmatched = shaderDef.mDefines.size();
289 for(auto& d : shaderDef.mDefines)
291 auto iFind = defines.find(d);
292 if(iFind != defines.end())
294 defines.erase(iFind);
299 printf("mismatched: %s\n", d.c_str());
304 DALI_TEST_CHECK(defines.empty());
305 DALI_TEST_EQUAL(0, definesUnmatched);
307 printf("defines OK\n");
309 auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"];
310 DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT);
312 auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"];
313 DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX);
315 ClearMeshesAndMaterials(ctx.resources);