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-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"
30 using namespace Dali::Scene3D::Loader;
34 MaterialDefinition& NewMaterialDefinition(ResourceBundle& resources)
36 resources.mMaterials.push_back({});
37 return resources.mMaterials.back().first;
40 MeshDefinition& NewMeshDefinition(ResourceBundle& resources)
42 resources.mMeshes.push_back({});
43 return resources.mMeshes.back().first;
46 void ClearMeshesAndMaterials(ResourceBundle& resources)
48 resources.mMaterials.clear();
49 resources.mMeshes.clear();
54 ResourceBundle resources;
55 ShaderDefinitionFactory factory;
59 factory.SetResources(resources);
63 struct ShaderParameters
65 MeshDefinition& meshDef;
66 MaterialDefinition& materialDef;
67 NodeDefinition& nodeDef;
72 using ConfigureFn = void (*)(ShaderParameters&);
74 ConfigureFn configureFn;
76 std::set<std::string> defines;
77 RendererState::Type rendererStateSet = 0;
78 RendererState::Type rendererStateClear = 0;
83 std::vector<const Permutation*> permutations;
89 int UtcDaliShaderDefinitionFactoryProduceShaderInvalid(void)
93 NodeDefinition nodeDef;
94 nodeDef.mRenderable.reset(new NodeDefinition::Renderable());
96 DALI_TEST_EQUAL(INVALID_INDEX, ctx.factory.ProduceShader(nodeDef));
97 DALI_TEST_CHECK(ctx.resources.mShaders.empty());
102 int UtcDaliShaderDefinitionFactoryProduceShader(void)
105 ctx.resources.mMaterials.push_back({});
106 ctx.resources.mMeshes.push_back({});
108 Permutation permutations[]{
110 [](ShaderParameters& p) {},
112 RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK,
115 [](ShaderParameters& p) {
116 p.materialDef.mFlags |= MaterialDefinition::TRANSPARENCY;
119 RendererState::ALPHA_BLEND,
120 RendererState::DEPTH_WRITE,
122 {[](ShaderParameters& p) {
123 p.materialDef.mTextureStages.push_back({MaterialDefinition::ALBEDO, {}});
126 {[](ShaderParameters& p) {
127 p.materialDef.mTextureStages.push_back({MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS, {}});
130 {[](ShaderParameters& p) {
131 p.materialDef.mTextureStages.push_back({MaterialDefinition::NORMAL, {}});
134 {[](ShaderParameters& p) {
135 p.materialDef.mFlags |= MaterialDefinition::SUBSURFACE;
138 {[](ShaderParameters& p) {
139 p.materialDef.SetAlphaCutoff(.5f);
142 {[](ShaderParameters& p) {
143 p.materialDef.SetAlphaCutoff(1.f);
146 {[](ShaderParameters& p) {
147 p.materialDef.mFlags |= MaterialDefinition::GLTF_CHANNELS;
150 {[](ShaderParameters& p) {
151 p.meshDef.mJoints0.mBlob.mOffset = 0;
152 p.meshDef.mWeights0.mBlob.mOffset = 0;
155 {[](ShaderParameters& p) {
156 p.meshDef.mFlags |= MeshDefinition::FLIP_UVS_VERTICAL;
160 [](ShaderParameters& p) {
161 p.meshDef.mBlendShapes.push_back({});
164 {[](ShaderParameters& p) {
165 p.meshDef.mBlendShapes.back().deltas.mBlob.mOffset = 0;
167 {"MORPH_POSITION", "MORPH"}},
168 {[](ShaderParameters& p) {
169 p.meshDef.mBlendShapes.back().normals.mBlob.mOffset = 0;
171 {"MORPH_NORMAL", "MORPH"}},
172 {[](ShaderParameters& p) {
173 p.meshDef.mBlendShapes.back().tangents.mBlob.mOffset = 0;
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;
184 {"MORPH_VERSION_2_0"}},
186 {[](ShaderParameters& p) {
187 p.materialDef.mFlags |= MaterialDefinition::OCCLUSION;
193 PermutationSet permSets[]{
195 {{&permutations[0]}, 0},
198 {{&permutations[0], &permutations[1]}, 1},
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},
209 // subsurface scattering
210 {{&permutations[0], &permutations[5]}, 3},
213 {{&permutations[0], &permutations[6]}, 4},
214 {{&permutations[0], &permutations[7]}, 4},
217 {{&permutations[0], &permutations[8]}, 5},
220 {{&permutations[0], &permutations[9]}, 6},
223 {{&permutations[0], &permutations[10]}, 7},
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},
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},
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},
248 {{&permutations[0], &permutations[16]}, 22},
251 for(auto& ps : permSets)
253 auto modelNode = new ModelNode();
254 modelNode->mMeshIdx = 0;
255 modelNode->mMaterialIdx = 0;
257 NodeDefinition nodeDef;
258 nodeDef.mRenderable.reset(modelNode);
260 auto& meshDef = NewMeshDefinition(ctx.resources);
261 auto& materialDef = NewMaterialDefinition(ctx.resources);
262 ShaderParameters sp{meshDef, materialDef, nodeDef};
264 std::set<std::string> defines;
265 RendererState::Type rendererState = 0;
266 for(auto p : ps.permutations)
269 defines.insert(p->defines.begin(), p->defines.end());
270 rendererState = (rendererState | p->rendererStateSet) & ~p->rendererStateClear;
273 auto shaderIdx = ctx.factory.ProduceShader(nodeDef);
274 DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx);
276 auto& shaderDef = ctx.resources.mShaders[shaderIdx].first;
277 DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState);
279 uint32_t definesUnmatched = shaderDef.mDefines.size();
280 for(auto& define : shaderDef.mDefines)
282 auto iFind = defines.find(define);
283 if(iFind != defines.end())
285 defines.erase(iFind);
294 DALI_TEST_CHECK(defines.empty());
295 DALI_TEST_EQUAL(0, definesUnmatched);
297 auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"];
298 DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT);
300 auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"];
301 DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX);
303 ClearMeshesAndMaterials(ctx.resources);