xref: /aosp_15_r20/external/deqp/modules/glshared/glsLongStressTestUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) Module
3  * -----------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Utilities for tests with gls::LongStressCase.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "glsLongStressTestUtil.hpp"
25 #include "tcuStringTemplate.hpp"
26 #include "deStringUtil.hpp"
27 
28 #include "glw.h"
29 
30 using de::toString;
31 using std::map;
32 using std::string;
33 using tcu::Mat2;
34 using tcu::Mat3;
35 using tcu::Mat4;
36 using tcu::Vec2;
37 using tcu::Vec3;
38 using tcu::Vec4;
39 
40 namespace deqp
41 {
42 namespace gls
43 {
44 namespace LongStressTestUtil
45 {
46 
47 template <int Size>
translationMat(const float v)48 static tcu::Matrix<float, Size, Size> translationMat(const float v)
49 {
50     tcu::Matrix<float, Size, Size> res(1.0f);
51     tcu::Vector<float, Size> col(v);
52     col[Size - 1] = 1.0f;
53     res.setColumn(Size - 1, col);
54     return res;
55 }
56 
57 // Specializes certain template patterns in templ for GLSL version m_glslVersion; params in additionalParams (optional) are also included in the substitution.
substitute(const string & templ,const map<string,string> & additionalParams) const58 string ProgramLibrary::substitute(const string &templ, const map<string, string> &additionalParams) const
59 {
60     const bool isGLSL3 = m_glslVersion == glu::GLSL_VERSION_300_ES;
61     map<string, string> params;
62 
63     params["FRAG_HEADER"] = isGLSL3 ? "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n" : "";
64     params["VTX_HEADER"]  = isGLSL3 ? "#version 300 es\n" : "";
65     params["VTX_IN"]      = isGLSL3 ? "in" : "attribute";
66     params["VTX_OUT"]     = isGLSL3 ? "out" : "varying";
67     params["FRAG_IN"]     = isGLSL3 ? "in" : "varying";
68     params["FRAG_COLOR"]  = isGLSL3 ? "dEQP_FragColor" : "gl_FragColor";
69     params["TEXTURE_2D_FUNC"] = isGLSL3 ? "texture" : "texture2D";
70     params["NS"]              = "${NS}"; // \note Keep these as-is, they're handled by StressCase.
71 
72     params.insert(additionalParams.begin(), additionalParams.end());
73 
74     return tcu::StringTemplate(templ.c_str()).specialize(params);
75 }
76 
substitute(const std::string & templ) const77 string ProgramLibrary::substitute(const std::string &templ) const
78 {
79     return substitute(templ, map<string, string>());
80 }
81 
ProgramLibrary(const glu::GLSLVersion glslVersion)82 ProgramLibrary::ProgramLibrary(const glu::GLSLVersion glslVersion) : m_glslVersion(glslVersion)
83 {
84     DE_ASSERT(glslVersion == glu::GLSL_VERSION_100_ES || glslVersion == glu::GLSL_VERSION_300_ES);
85 }
86 
generateBufferContext(const int numUnusedAttributes) const87 gls::ProgramContext ProgramLibrary::generateBufferContext(const int numUnusedAttributes) const
88 {
89     static const char *const vertexTemplate = "${VTX_HEADER}"
90                                               "${VTX_IN} highp vec3 a_position;\n"
91                                               "${VTX_UNUSED_INPUTS}"
92                                               "${VTX_OUT} mediump vec4 v_color;\n"
93                                               "\n"
94                                               "void main (void)\n"
95                                               "{\n"
96                                               "    gl_Position = vec4(a_position, 1.0);\n"
97                                               "    v_color = ${VTX_COLOR_EXPRESSION};\n"
98                                               "}\n";
99 
100     static const char *const fragmentTemplate = "${FRAG_HEADER}"
101                                                 "${FRAG_IN} mediump vec4 v_color;\n"
102                                                 "\n"
103                                                 "void main (void)\n"
104                                                 "{\n"
105                                                 "    ${FRAG_COLOR} = v_color;\n"
106                                                 "}\n";
107 
108     map<string, string> firstLevelParams;
109 
110     {
111         string vtxUnusedInputs;
112         string vtxColorExpr;
113         for (int i = 0; i < numUnusedAttributes; i++)
114         {
115             vtxUnusedInputs += "${VTX_IN} mediump vec4 a_in" + toString(i) + ";\n";
116             vtxColorExpr += string() + (i > 0 ? " + " : "") + "a_in" + toString(i);
117         }
118 
119         firstLevelParams["VTX_UNUSED_INPUTS"]    = substitute(vtxUnusedInputs);
120         firstLevelParams["VTX_COLOR_EXPRESSION"] = vtxColorExpr;
121     }
122 
123     gls::ProgramContext context(substitute(vertexTemplate, firstLevelParams).c_str(),
124                                 substitute(fragmentTemplate).c_str(), "a_position");
125 
126     context.attributes.push_back(gls::VarSpec("a_position", Vec3(-0.1f), Vec3(0.1f)));
127 
128     for (int i = 0; i < numUnusedAttributes; i++)
129         context.attributes.push_back(
130             gls::VarSpec("a_in" + de::toString(i), Vec4(0.0f), Vec4(1.0f / (float)numUnusedAttributes)));
131 
132     return context;
133 }
134 
generateTextureContext(const int numTextures,const int texWid,const int texHei,const float positionFactor) const135 gls::ProgramContext ProgramLibrary::generateTextureContext(const int numTextures, const int texWid, const int texHei,
136                                                            const float positionFactor) const
137 {
138     static const char *const vertexTemplate = "${VTX_HEADER}"
139                                               "${VTX_IN} highp vec3 a_position;\n"
140                                               "${VTX_IN} mediump vec2 a_texCoord;\n"
141                                               "${VTX_OUT} mediump vec2 v_texCoord;\n"
142                                               "uniform mediump mat4 u_posTrans;\n"
143                                               "\n"
144                                               "void main (void)\n"
145                                               "{\n"
146                                               "    gl_Position = u_posTrans * vec4(a_position, 1.0);\n"
147                                               "    v_texCoord = a_texCoord;\n"
148                                               "}\n";
149 
150     static const char *const fragmentTemplate = "${FRAG_HEADER}"
151                                                 "${FRAG_IN} mediump vec2 v_texCoord;\n"
152                                                 "uniform mediump sampler2D u_sampler;\n"
153                                                 "\n"
154                                                 "void main (void)\n"
155                                                 "{\n"
156                                                 "    ${FRAG_COLOR} = ${TEXTURE_2D_FUNC}(u_sampler, v_texCoord);\n"
157                                                 "}\n";
158 
159     gls::ProgramContext context(substitute(vertexTemplate).c_str(), substitute(fragmentTemplate).c_str(), "a_position");
160 
161     context.attributes.push_back(gls::VarSpec("a_position", Vec3(-positionFactor), Vec3(positionFactor)));
162     context.attributes.push_back(gls::VarSpec("a_texCoord", Vec2(0.0f), Vec2(1.0f)));
163 
164     context.uniforms.push_back(gls::VarSpec("u_sampler", 0));
165     context.uniforms.push_back(
166         gls::VarSpec("u_posTrans", translationMat<4>(positionFactor - 1.0f), translationMat<4>(1.0f - positionFactor)));
167 
168     for (int i = 0; i < numTextures; i++)
169         context.textureSpecs.push_back(gls::TextureSpec(
170             glu::TextureTestUtil::TEXTURETYPE_2D, 0, texWid, texHei, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA, true,
171             GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT, Vec4(0.0f), Vec4(1.0f)));
172 
173     return context;
174 }
175 
generateBufferAndTextureContext(const int numTextures,const int texWid,const int texHei) const176 gls::ProgramContext ProgramLibrary::generateBufferAndTextureContext(const int numTextures, const int texWid,
177                                                                     const int texHei) const
178 {
179     static const char *const vertexTemplate = "${VTX_HEADER}"
180                                               "${VTX_IN} highp vec3 a_position;\n"
181                                               "${VTX_TEX_COORD_INPUTS}"
182                                               "${VTX_TEX_COORD_OUTPUTS}"
183                                               "\n"
184                                               "void main (void)\n"
185                                               "{\n"
186                                               "    gl_Position = vec4(a_position, 1.0);\n"
187                                               "${VTX_TEX_COORD_WRITES}"
188                                               "}\n";
189 
190     static const char *const fragmentTemplate = "${FRAG_HEADER}"
191                                                 "${FRAG_TEX_COORD_INPUTS}"
192                                                 "${FRAG_SAMPLERS}"
193                                                 "\n"
194                                                 "void main (void)\n"
195                                                 "{\n"
196                                                 "    ${FRAG_COLOR} =${FRAG_COLOR_EXPRESSION};\n"
197                                                 "}\n";
198 
199     map<string, string> firstLevelParams;
200 
201     {
202         string vtxTexCoordInputs;
203         string vtxTexCoordOutputs;
204         string vtxTexCoordWrites;
205         string fragTexCoordInputs;
206         string fragSamplers;
207         string fragColorExpression;
208 
209         for (int i = 0; i < numTextures; i++)
210         {
211             vtxTexCoordInputs += "${VTX_IN} mediump vec2 a_texCoord" + toString(i) + ";\n";
212             vtxTexCoordOutputs += "${VTX_OUT} mediump vec2 v_texCoord" + toString(i) + ";\n";
213             vtxTexCoordWrites += "\tv_texCoord" + toString(i) + " = " + "a_texCoord" + toString(i) + ";\n";
214             fragTexCoordInputs += "${FRAG_IN} mediump vec2 v_texCoord" + toString(i) + ";\n";
215             fragSamplers += "uniform mediump sampler2D u_sampler" + toString(i) + ";\n";
216             fragColorExpression += string() + (i > 0 ? " +" : "") + "\n\t\t${TEXTURE_2D_FUNC}(u_sampler" + toString(i) +
217                                    ", v_texCoord" + toString(i) + ")";
218         }
219 
220         firstLevelParams["VTX_TEX_COORD_INPUTS"]  = substitute(vtxTexCoordInputs);
221         firstLevelParams["VTX_TEX_COORD_OUTPUTS"] = substitute(vtxTexCoordOutputs);
222         firstLevelParams["VTX_TEX_COORD_WRITES"]  = vtxTexCoordWrites;
223         firstLevelParams["FRAG_TEX_COORD_INPUTS"] = substitute(fragTexCoordInputs);
224         firstLevelParams["FRAG_SAMPLERS"]         = fragSamplers;
225         firstLevelParams["FRAG_COLOR_EXPRESSION"] = substitute(fragColorExpression);
226     }
227 
228     gls::ProgramContext context(substitute(vertexTemplate, firstLevelParams).c_str(),
229                                 substitute(fragmentTemplate, firstLevelParams).c_str(), "a_position");
230 
231     context.attributes.push_back(gls::VarSpec("a_position", Vec3(-0.1f), Vec3(0.1f)));
232 
233     for (int i = 0; i < numTextures; i++)
234     {
235         context.attributes.push_back(gls::VarSpec("a_texCoord" + de::toString(i), Vec2(0.0f), Vec2(1.0f)));
236         context.uniforms.push_back(gls::VarSpec("u_sampler" + de::toString(i), i));
237         context.textureSpecs.push_back(gls::TextureSpec(
238             glu::TextureTestUtil::TEXTURETYPE_2D, i, texWid, texHei, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA, true,
239             GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT, Vec4(0.0f), Vec4(1.0f / (float)numTextures)));
240     }
241 
242     return context;
243 }
244 
generateFragmentPointLightContext(const int texWid,const int texHei) const245 gls::ProgramContext ProgramLibrary::generateFragmentPointLightContext(const int texWid, const int texHei) const
246 {
247     static const char *const vertexTemplate =
248         "${VTX_HEADER}"
249         "struct Material\n"
250         "{\n"
251         "    mediump vec3    ambientColor;\n"
252         "    mediump vec4    diffuseColor;\n"
253         "    mediump vec3    emissiveColor;\n"
254         "    mediump vec3    specularColor;\n"
255         "    mediump float    shininess;\n"
256         "};\n"
257         "\n"
258         "struct Light\n"
259         "{\n"
260         "    mediump vec3    color;\n"
261         "    mediump vec4    position;\n"
262         "    mediump vec3    direction;\n"
263         "    mediump float    constantAttenuation;\n"
264         "    mediump float    linearAttenuation;\n"
265         "    mediump float    quadraticAttenuation;\n"
266         "};\n"
267         "\n"
268         "${VTX_IN} highp vec4    a_position${NS};\n"
269         "${VTX_IN} mediump vec3    a_normal${NS};\n"
270         "${VTX_IN} mediump vec3    a_color${NS};\n"
271         "${VTX_IN} mediump vec4    a_texCoord0${NS};\n"
272         "\n"
273         "uniform Material        u_material${NS};\n"
274         "uniform Light            u_light${NS}[1];\n"
275         "uniform highp mat4        u_mvpMatrix${NS};\n"
276         "uniform mediump mat4    u_modelViewMatrix${NS};\n"
277         "uniform mediump mat3    u_normalMatrix${NS};\n"
278         "uniform mediump mat4    u_texCoordMatrix0${NS};\n"
279         "\n"
280         "${VTX_OUT} mediump vec4    v_baseColor${NS};\n"
281         "${VTX_OUT} mediump vec2    v_texCoord0${NS};\n"
282         "\n"
283         "${VTX_OUT} mediump vec3    v_eyeNormal${NS};\n"
284         "${VTX_OUT} mediump vec3    v_directionToLight${NS}[1];\n"
285         "${VTX_OUT} mediump float    v_distanceToLight${NS}[1];\n"
286         "\n"
287         "vec3 direction (vec4 from, vec4 to)\n"
288         "{\n"
289         "    return vec3(to.xyz * from.w - from.xyz * to.w);\n"
290         "}\n"
291         "\n"
292         "void main (void)\n"
293         "{\n"
294         "    gl_Position = u_mvpMatrix${NS} * a_position${NS};\n"
295         "    v_texCoord0${NS} = (u_texCoordMatrix0${NS} * a_texCoord0${NS}).xy;\n"
296         "\n"
297         "    mediump vec4 eyePosition = u_modelViewMatrix${NS} * a_position${NS};\n"
298         "    mediump vec3 eyeNormal = normalize(u_normalMatrix${NS} * a_normal${NS});\n"
299         "\n"
300         "    vec4 color     = vec4(0.0, 0.0, 0.0, 1.0);\n"
301         "    color.rgb    += u_material${NS}.emissiveColor;\n"
302         "\n"
303         "    color.a        *= u_material${NS}.diffuseColor.a;\n"
304         "\n"
305         "    v_baseColor${NS} = color;\n"
306         "\n"
307         "    v_distanceToLight${NS}[0] = distance(eyePosition, u_light${NS}[0].position);\n"
308         "    v_directionToLight${NS}[0] = normalize(direction(eyePosition, u_light${NS}[0].position));\n"
309         "\n"
310         "    v_eyeNormal${NS} = eyeNormal;\n"
311         "}\n";
312 
313     static const char *const fragmentTemplate =
314         "${FRAG_HEADER}"
315         "struct Light\n"
316         "{\n"
317         "    mediump vec3    color;\n"
318         "    mediump vec4    position;\n"
319         "    mediump vec3    direction;\n"
320         "    mediump float    constantAttenuation;\n"
321         "    mediump float    linearAttenuation;\n"
322         "    mediump float    quadraticAttenuation;\n"
323         "};\n"
324         "\n"
325         "struct Material\n"
326         "{\n"
327         "    mediump vec3    ambientColor;\n"
328         "    mediump vec4    diffuseColor;\n"
329         "    mediump vec3    emissiveColor;\n"
330         "    mediump vec3    specularColor;\n"
331         "    mediump float    shininess;\n"
332         "};\n"
333         "\n"
334         "uniform sampler2D        u_sampler0${NS};\n"
335         "uniform Light            u_light${NS}[1];\n"
336         "uniform Material        u_material${NS};\n"
337         "\n"
338         "${FRAG_IN} mediump vec4    v_baseColor${NS};\n"
339         "${FRAG_IN} mediump vec2    v_texCoord0${NS};\n"
340         "\n"
341         "${FRAG_IN} mediump vec3    v_eyeNormal${NS};\n"
342         "${FRAG_IN} mediump vec3    v_directionToLight${NS}[1];\n"
343         "${FRAG_IN} mediump float    v_distanceToLight${NS}[1];\n"
344         "\n"
345         "mediump vec3 computeLighting (Light light, mediump vec3 directionToLight, mediump vec3 vertexEyeNormal)\n"
346         "{\n"
347         "    mediump float    normalDotDirection = max(dot(vertexEyeNormal, directionToLight), 0.0);\n"
348         "    mediump    vec3    color = normalDotDirection * u_material${NS}.diffuseColor.rgb * "
349         "light.color;\n"
350         "\n"
351         "    if (normalDotDirection != 0.0)\n"
352         "    {\n"
353         "        mediump vec3 h = normalize(directionToLight + vec3(0.0, 0.0, 1.0));\n"
354         "        color.rgb += pow(max(dot(vertexEyeNormal, h), 0.0), u_material${NS}.shininess) * "
355         "u_material${NS}.specularColor * light.color;\n"
356         "    }\n"
357         "\n"
358         "    return color;\n"
359         "}\n"
360         "\n"
361         "mediump float computePointLightAttenuation (Light light, mediump float distanceToLight)\n"
362         "{\n"
363         "    mediump float    constantAttenuation = light.constantAttenuation;\n"
364         "    mediump float    linearAttenuation = light.linearAttenuation * distanceToLight;\n"
365         "    mediump float    quadraticAttenuation = light.quadraticAttenuation * distanceToLight * distanceToLight;\n"
366         "\n"
367         "    return 1.0 / (constantAttenuation + linearAttenuation + quadraticAttenuation);\n"
368         "}\n"
369         "\n"
370         "void main (void)\n"
371         "{\n"
372         "    mediump vec3 eyeNormal = normalize(v_eyeNormal${NS});\n"
373         "    mediump vec4 color = v_baseColor${NS};\n"
374         "\n"
375         "    color.rgb += computePointLightAttenuation(u_light${NS}[0], v_distanceToLight${NS}[0]) * "
376         "computeLighting(u_light${NS}[0], normalize(v_directionToLight${NS}[0]), eyeNormal);\n"
377         "\n"
378         "    color *= ${TEXTURE_2D_FUNC}(u_sampler0${NS}, v_texCoord0${NS});\n"
379         "\n"
380         "    ${FRAG_COLOR} = color;\n"
381         "}\n";
382 
383     gls::ProgramContext context(substitute(vertexTemplate).c_str(), substitute(fragmentTemplate).c_str(),
384                                 "a_position${NS}");
385 
386     context.attributes.push_back(gls::VarSpec("a_position${NS}", Vec4(-1.0f), Vec4(1.0f)));
387     context.attributes.push_back(gls::VarSpec("a_normal${NS}", Vec3(-1.0f), Vec3(1.0f)));
388     context.attributes.push_back(gls::VarSpec("a_texCoord0${NS}", Vec4(-1.0f), Vec4(1.0f)));
389 
390     context.uniforms.push_back(gls::VarSpec("u_material${NS}.ambientColor", Vec3(0.0f), Vec3(1.0f)));
391     context.uniforms.push_back(gls::VarSpec("u_material${NS}.diffuseColor", Vec4(0.0f), Vec4(1.0f)));
392     context.uniforms.push_back(gls::VarSpec("u_material${NS}.emissiveColor", Vec3(0.0f), Vec3(1.0f)));
393     context.uniforms.push_back(gls::VarSpec("u_material${NS}.specularColor", Vec3(0.0f), Vec3(1.0f)));
394     context.uniforms.push_back(gls::VarSpec("u_material${NS}.shininess", 0.0f, 1.0f));
395 
396     context.uniforms.push_back(gls::VarSpec("u_light${NS}[0].color", Vec3(0.0f), Vec3(1.0f)));
397     context.uniforms.push_back(gls::VarSpec("u_light${NS}[0].position", Vec4(-1.0f), Vec4(1.0f)));
398     context.uniforms.push_back(gls::VarSpec("u_light${NS}[0].direction", Vec3(-1.0f), Vec3(1.0f)));
399     context.uniforms.push_back(gls::VarSpec("u_light${NS}[0].constantAttenuation", 0.1f, 1.0f));
400     context.uniforms.push_back(gls::VarSpec("u_light${NS}[0].linearAttenuation", 0.1f, 1.0f));
401     context.uniforms.push_back(gls::VarSpec("u_light${NS}[0].quadraticAttenuation", 0.1f, 1.0f));
402 
403     context.uniforms.push_back(gls::VarSpec("u_mvpMatrix${NS}", translationMat<4>(-0.2f), translationMat<4>(0.2f)));
404     context.uniforms.push_back(
405         gls::VarSpec("u_modelViewMatrix${NS}", translationMat<4>(-0.2f), translationMat<4>(0.2f)));
406     context.uniforms.push_back(gls::VarSpec("u_normalMatrix${NS}", translationMat<3>(-0.2f), translationMat<3>(0.2f)));
407     context.uniforms.push_back(
408         gls::VarSpec("u_texCoordMatrix0${NS}", translationMat<4>(-0.2f), translationMat<4>(0.2f)));
409 
410     context.uniforms.push_back(gls::VarSpec("u_sampler0${NS}", 0));
411 
412     context.textureSpecs.push_back(gls::TextureSpec(glu::TextureTestUtil::TEXTURETYPE_2D, 0, texWid, texHei, GL_RGBA,
413                                                     GL_UNSIGNED_BYTE, GL_RGBA, true, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,
414                                                     GL_REPEAT, GL_REPEAT, Vec4(0.0f), Vec4(1.0f)));
415 
416     return context;
417 }
418 
generateVertexUniformLoopLightContext(const int texWid,const int texHei) const419 gls::ProgramContext ProgramLibrary::generateVertexUniformLoopLightContext(const int texWid, const int texHei) const
420 {
421     static const char *const vertexTemplate =
422         "${VTX_HEADER}"
423         "struct Material {\n"
424         "    mediump vec3 ambientColor;\n"
425         "    mediump vec4 diffuseColor;\n"
426         "    mediump vec3 emissiveColor;\n"
427         "    mediump vec3 specularColor;\n"
428         "    mediump float shininess;\n"
429         "};\n"
430         "struct Light {\n"
431         "    mediump vec3 color;\n"
432         "    mediump vec4 position;\n"
433         "    mediump vec3 direction;\n"
434         "    mediump float constantAttenuation;\n"
435         "    mediump float linearAttenuation;\n"
436         "    mediump float quadraticAttenuation;\n"
437         "    mediump float spotExponent;\n"
438         "    mediump float spotCutoff;\n"
439         "};\n"
440         "${VTX_IN} highp vec4 a_position${NS};\n"
441         "${VTX_IN} mediump vec3 a_normal${NS};\n"
442         "${VTX_IN} mediump vec4 a_texCoord0${NS};\n"
443         "uniform Material u_material${NS};\n"
444         "uniform Light u_directionalLight${NS}[1];\n"
445         "uniform mediump int u_directionalLightCount${NS};\n"
446         "uniform Light u_spotLight${NS}[4];\n"
447         "uniform mediump int u_spotLightCount${NS};\n"
448         "uniform highp mat4 u_mvpMatrix${NS};\n"
449         "uniform highp mat4 u_modelViewMatrix${NS};\n"
450         "uniform mediump mat3 u_normalMatrix${NS};\n"
451         "uniform mediump mat4 u_texCoordMatrix0${NS};\n"
452         "${VTX_OUT} mediump vec4 v_color${NS};\n"
453         "${VTX_OUT} mediump vec2 v_texCoord0${NS};\n"
454         "mediump vec3 direction (mediump vec4 from, mediump vec4 to)\n"
455         "{\n"
456         "    return vec3(to.xyz * from.w - from.xyz * to.w);\n"
457         "}\n"
458         "\n"
459         "mediump vec3 computeLighting (\n"
460         "    mediump vec3 directionToLight,\n"
461         "    mediump vec3 halfVector,\n"
462         "    mediump vec3 normal,\n"
463         "    mediump vec3 lightColor,\n"
464         "    mediump vec3 diffuseColor,\n"
465         "    mediump vec3 specularColor,\n"
466         "    mediump float shininess)\n"
467         "{\n"
468         "    mediump float normalDotDirection  = max(dot(normal, directionToLight), 0.0);\n"
469         "    mediump vec3  color               = normalDotDirection * diffuseColor * lightColor;\n"
470         "\n"
471         "    if (normalDotDirection != 0.0)\n"
472         "        color += pow(max(dot(normal, halfVector), 0.0), shininess) * specularColor * lightColor;\n"
473         "\n"
474         "    return color;\n"
475         "}\n"
476         "\n"
477         "mediump float computeDistanceAttenuation (mediump float distToLight, mediump float constAtt, mediump float "
478         "linearAtt, mediump float quadraticAtt)\n"
479         "{\n"
480         "    return 1.0 / (constAtt + linearAtt * distToLight + quadraticAtt * distToLight * distToLight);\n"
481         "}\n"
482         "\n"
483         "mediump float computeSpotAttenuation (\n"
484         "    mediump vec3  directionToLight,\n"
485         "    mediump vec3  lightDir,\n"
486         "    mediump float spotExponent,\n"
487         "    mediump float spotCutoff)\n"
488         "{\n"
489         "    mediump float spotEffect = dot(lightDir, normalize(-directionToLight));\n"
490         "\n"
491         "    if (spotEffect < spotCutoff)\n"
492         "        spotEffect = 0.0;\n"
493         "\n"
494         "    spotEffect = pow(spotEffect, spotExponent);\n"
495         "    return spotEffect;\n"
496         "}\n"
497         "\n"
498         "void main (void)\n"
499         "{\n"
500         "    highp vec4 position = a_position${NS};\n"
501         "    highp vec3 normal = a_normal${NS};\n"
502         "    gl_Position = u_mvpMatrix${NS} * position;\n"
503         "    v_texCoord0${NS} = (u_texCoordMatrix0${NS} * a_texCoord0${NS}).xy;\n"
504         "    mediump vec4 color = vec4(u_material${NS}.emissiveColor, u_material${NS}.diffuseColor.a);\n"
505         "\n"
506         "    highp vec4 eyePosition = u_modelViewMatrix${NS} * position;\n"
507         "    mediump vec3 eyeNormal = normalize(u_normalMatrix${NS} * normal);\n"
508         "    for (int i = 0; i < u_directionalLightCount${NS}; i++)\n"
509         "    {\n"
510         "        mediump vec3 directionToLight = -u_directionalLight${NS}[i].direction;\n"
511         "        mediump vec3 halfVector = normalize(directionToLight + vec3(0.0, 0.0, 1.0));\n"
512         "        color.rgb += computeLighting(directionToLight, halfVector, eyeNormal, "
513         "u_directionalLight${NS}[i].color, u_material${NS}.diffuseColor.rgb, u_material${NS}.specularColor, "
514         "u_material${NS}.shininess);\n"
515         "    }\n"
516         "\n"
517         "    for (int i = 0; i < u_spotLightCount${NS}; i++)\n"
518         "    {\n"
519         "        mediump float distanceToLight = distance(eyePosition, u_spotLight${NS}[i].position);\n"
520         "        mediump vec3 directionToLight = normalize(direction(eyePosition, u_spotLight${NS}[i].position));\n"
521         "        mediump vec3 halfVector = normalize(directionToLight + vec3(0.0, 0.0, 1.0));\n"
522         "        color.rgb += computeLighting(directionToLight, halfVector, eyeNormal, u_spotLight${NS}[i].color, "
523         "u_material${NS}.diffuseColor.rgb, u_material${NS}.specularColor, u_material${NS}.shininess) * "
524         "computeDistanceAttenuation(distanceToLight, u_spotLight${NS}[i].constantAttenuation, "
525         "u_spotLight${NS}[i].linearAttenuation, u_spotLight${NS}[i].quadraticAttenuation) * "
526         "computeSpotAttenuation(directionToLight, u_spotLight${NS}[i].direction, u_spotLight${NS}[i].spotExponent, "
527         "u_spotLight${NS}[i].spotCutoff);\n"
528         "    }\n"
529         "\n"
530         "\n"
531         "    v_color${NS} = color;\n"
532         "}\n";
533 
534     static const char *const fragmentTemplate = "${FRAG_HEADER}"
535                                                 "uniform sampler2D u_sampler0${NS};\n"
536                                                 "${FRAG_IN} mediump vec4 v_color${NS};\n"
537                                                 "${FRAG_IN} mediump vec2 v_texCoord0${NS};\n"
538                                                 "void main (void)\n"
539                                                 "{\n"
540                                                 "    mediump vec2 texCoord0 = v_texCoord0${NS};\n"
541                                                 "    mediump vec4 color = v_color${NS};\n"
542                                                 "    color *= ${TEXTURE_2D_FUNC}(u_sampler0${NS}, texCoord0);\n"
543                                                 "    ${FRAG_COLOR} = color;\n"
544                                                 "}\n";
545 
546     gls::ProgramContext context(substitute(vertexTemplate).c_str(), substitute(fragmentTemplate).c_str(),
547                                 "a_position${NS}");
548 
549     context.attributes.push_back(gls::VarSpec("a_position${NS}", Vec4(-1.0f), Vec4(1.0f)));
550     context.attributes.push_back(gls::VarSpec("a_normal${NS}", Vec3(-1.0f), Vec3(1.0f)));
551     context.attributes.push_back(gls::VarSpec("a_texCoord0${NS}", Vec4(-1.0f), Vec4(1.0f)));
552 
553     context.uniforms.push_back(gls::VarSpec("u_material${NS}.ambientColor", Vec3(0.0f), Vec3(1.0f)));
554     context.uniforms.push_back(gls::VarSpec("u_material${NS}.diffuseColor", Vec4(0.0f), Vec4(1.0f)));
555     context.uniforms.push_back(gls::VarSpec("u_material${NS}.emissiveColor", Vec3(0.0f), Vec3(1.0f)));
556     context.uniforms.push_back(gls::VarSpec("u_material${NS}.specularColor", Vec3(0.0f), Vec3(1.0f)));
557     context.uniforms.push_back(gls::VarSpec("u_material${NS}.shininess", 0.0f, 1.0f));
558 
559     context.uniforms.push_back(gls::VarSpec("u_directionalLight${NS}[0].color", Vec3(0.0f), Vec3(1.0f)));
560     context.uniforms.push_back(gls::VarSpec("u_directionalLight${NS}[0].position", Vec4(-1.0f), Vec4(1.0f)));
561     context.uniforms.push_back(gls::VarSpec("u_directionalLight${NS}[0].direction", Vec3(-1.0f), Vec3(1.0f)));
562     context.uniforms.push_back(gls::VarSpec("u_directionalLight${NS}[0].constantAttenuation", 0.1f, 1.0f));
563     context.uniforms.push_back(gls::VarSpec("u_directionalLight${NS}[0].linearAttenuation", 0.1f, 1.0f));
564     context.uniforms.push_back(gls::VarSpec("u_directionalLight${NS}[0].quadraticAttenuation", 0.1f, 1.0f));
565     context.uniforms.push_back(gls::VarSpec("u_directionalLight${NS}[0].spotExponent", 0.1f, 1.0f));
566     context.uniforms.push_back(gls::VarSpec("u_directionalLight${NS}[0].spotCutoff", 0.1f, 1.0f));
567 
568     context.uniforms.push_back(gls::VarSpec("u_directionalLightCount${NS}", 1));
569 
570     for (int i = 0; i < 4; i++)
571     {
572         const std::string ndxStr = de::toString(i);
573 
574         context.uniforms.push_back(gls::VarSpec("u_spotLight${NS}[" + ndxStr + "].color", Vec3(0.0f), Vec3(1.0f)));
575         context.uniforms.push_back(gls::VarSpec("u_spotLight${NS}[" + ndxStr + "].position", Vec4(-1.0f), Vec4(1.0f)));
576         context.uniforms.push_back(gls::VarSpec("u_spotLight${NS}[" + ndxStr + "].direction", Vec3(-1.0f), Vec3(1.0f)));
577         context.uniforms.push_back(gls::VarSpec("u_spotLight${NS}[" + ndxStr + "].constantAttenuation", 0.1f, 1.0f));
578         context.uniforms.push_back(gls::VarSpec("u_spotLight${NS}[" + ndxStr + "].linearAttenuation", 0.1f, 1.0f));
579         context.uniforms.push_back(gls::VarSpec("u_spotLight${NS}[" + ndxStr + "].quadraticAttenuation", 0.1f, 1.0f));
580         context.uniforms.push_back(gls::VarSpec("u_spotLight${NS}[" + ndxStr + "].spotExponent", 0.1f, 1.0f));
581         context.uniforms.push_back(gls::VarSpec("u_spotLight${NS}[" + ndxStr + "].spotCutoff", 0.1f, 1.0f));
582     }
583 
584     context.uniforms.push_back(gls::VarSpec("u_spotLightCount${NS}", 4));
585 
586     context.uniforms.push_back(gls::VarSpec("u_mvpMatrix${NS}", translationMat<4>(-0.2f), translationMat<4>(0.2f)));
587     context.uniforms.push_back(
588         gls::VarSpec("u_modelViewMatrix${NS}", translationMat<4>(-0.2f), translationMat<4>(0.2f)));
589     context.uniforms.push_back(gls::VarSpec("u_normalMatrix${NS}", translationMat<3>(-0.2f), translationMat<3>(0.2f)));
590     context.uniforms.push_back(
591         gls::VarSpec("u_texCoordMatrix0${NS}", translationMat<4>(-0.2f), translationMat<4>(0.2f)));
592 
593     context.uniforms.push_back(gls::VarSpec("u_sampler0${NS}", 0));
594 
595     context.textureSpecs.push_back(gls::TextureSpec(glu::TextureTestUtil::TEXTURETYPE_2D, 0, texWid, texHei, GL_RGBA,
596                                                     GL_UNSIGNED_BYTE, GL_RGBA, true, GL_LINEAR, GL_LINEAR, GL_REPEAT,
597                                                     GL_REPEAT, Vec4(0.0f), Vec4(1.0f)));
598 
599     return context;
600 }
601 
602 } // namespace LongStressTestUtil
603 } // namespace gls
604 } // namespace deqp
605