Fix sparse cubemap array tests issues
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl4cSparseTextureClampTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23
24 /**
25  */ /*!
26  * \file  gl4cSparseTextureClampTests.cpp
27  * \brief Conformance tests for the GL_ARB_sparse_texture2 functionality.
28  */ /*-------------------------------------------------------------------*/
29
30 #include "gl4cSparseTextureClampTests.hpp"
31 #include "deStringUtil.hpp"
32 #include "gl4cSparseTexture2Tests.hpp"
33 #include "gl4cSparseTextureTests.hpp"
34 #include "gluContextInfo.hpp"
35 #include "gluDefs.hpp"
36 #include "glwEnums.hpp"
37 #include "glwFunctions.hpp"
38 #include "tcuImageIO.hpp"
39 #include "tcuTestLog.hpp"
40
41 #include <cmath>
42 #include <string.h>
43 #include <vector>
44
45 using namespace glw;
46 using namespace glu;
47
48 namespace gl4cts
49 {
50
51 const char* stc_compute_textureFill = "#version 430 core\n"
52                                                                           "\n"
53                                                                           "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
54                                                                           "\n"
55                                                                           "layout (location = 1) writeonly uniform highp <INPUT_TYPE> uni_image;\n"
56                                                                           "\n"
57                                                                           "void main()\n"
58                                                                           "{\n"
59                                                                           "    <POINT_TYPE> point = <POINT_TYPE>(<POINT_DEF>);\n"
60                                                                           "    memoryBarrier();\n"
61                                                                           "    <RETURN_TYPE> color = <RETURN_TYPE><RESULT_EXPECTED>;\n"
62                                                                           "    imageStore(uni_image, point<SAMPLE_DEF>, color);\n"
63                                                                           "}\n";
64
65 const char* stc_vertex_common = "#version 450\n"
66                                                                 "\n"
67                                                                 "in vec3 vertex;\n"
68                                                                 "in <COORD_TYPE> inCoord;\n"
69                                                                 "out <COORD_TYPE> texCoord;\n"
70                                                                 "\n"
71                                                                 "void main()\n"
72                                                                 "{\n"
73                                                                 "    texCoord = inCoord;\n"
74                                                                 "    gl_Position = vec4(vertex, 1);\n"
75                                                                 "}\n";
76
77 const char* stc_fragment_lookupResidency = "#version 450 core\n"
78                                                                                    "\n"
79                                                                                    "#extension GL_ARB_sparse_texture2 : enable\n"
80                                                                                    "#extension GL_ARB_sparse_texture_clamp : enable\n"
81                                                                                    "\n"
82                                                                                    "in <COORD_TYPE> texCoord;\n"
83                                                                                    "out vec4 fragColor;\n"
84                                                                                    "\n"
85                                                                                    "layout (location = 1<FORMAT_DEF>) uniform <INPUT_TYPE> uni_in;\n"
86                                                                                    "layout (location = 2) uniform int widthCommitted;\n"
87                                                                                    "\n"
88                                                                                    "void main()\n"
89                                                                                    "{\n"
90                                                                                    "    <COORD_TYPE> coord = texCoord;\n"
91                                                                                    "    <ICOORD_TYPE> texSize = <ICOORD_TYPE>(<SIZE_DEF>);\n"
92                                                                                    "    <POINT_TYPE> point = <POINT_TYPE>(coord * texSize);\n"
93                                                                                    "    <RETURN_TYPE> retValue,\n"
94                                                                                    "                  expValue,\n"
95                                                                                    "                  epsilon;\n"
96                                                                                    "    retValue = <RETURN_TYPE>(0);\n"
97                                                                                    "    expValue = <RETURN_TYPE><RESULT_EXPECTED>;\n"
98                                                                                    "    epsilon = <RETURN_TYPE>(<EPSILON>);\n"
99                                                                                    "\n"
100                                                                                    "<CUBE_MAP_COORD_DEF>\n"
101                                                                                    "<OFFSET_ARRAY_DEF>\n"
102                                                                                    "\n"
103                                                                                    "    ivec2 corner1 = ivec2(1, 1);\n"
104                                                                                    "    ivec2 corner2 = ivec2(texSize.x - 1, texSize.y - 1);\n"
105                                                                                    "\n"
106                                                                                    "    int code = <FUNCTION>(uni_in,\n"
107                                                                                    "                          <POINT_COORD><SAMPLE_DEF><ARGUMENTS>,\n"
108                                                                                    "                          retValue<COMPONENT_DEF>);\n"
109                                                                                    "\n"
110                                                                                    "    fragColor = vec4(1);\n"
111                                                                                    "\n"
112                                                                                    "    if (point.x > corner1.x && point.y > corner1.y &&\n"
113                                                                                    "        point.x < corner2.x && point.y < corner2.y &&\n"
114                                                                                    "        point.x < widthCommitted - 1)\n"
115                                                                                    "    {\n"
116                                                                                    "        if (!sparseTexelsResidentARB(code) ||\n"
117                                                                                    "            any(greaterThan(retValue, expValue + epsilon)) ||\n"
118                                                                                    "            any(lessThan(retValue, expValue - epsilon)))\n"
119                                                                                    "        {\n"
120                                                                                    "            fragColor = vec4(0);\n"
121                                                                                    "        }\n"
122                                                                                    "    }\n"
123                                                                                    "\n"
124                                                                                    "    if (point.x > corner1.x && point.y > corner1.y &&\n"
125                                                                                    "        point.x < corner2.x && point.y < corner2.y &&\n"
126                                                                                    "        point.x >= widthCommitted + 1)\n"
127                                                                                    "    {\n"
128                                                                                    "        if (sparseTexelsResidentARB(code))\n"
129                                                                                    "        {\n"
130                                                                                    "            fragColor = vec4(0);\n"
131                                                                                    "        }\n"
132                                                                                    "    }\n"
133                                                                                    "}\n";
134
135 const char* stc_fragment_lookupColor = "#version 450 core\n"
136                                                                            "\n"
137                                                                            "#extension GL_ARB_sparse_texture2 : enable\n"
138                                                                            "#extension GL_ARB_sparse_texture_clamp : enable\n"
139                                                                            "\n"
140                                                                            "in <COORD_TYPE> texCoord;\n"
141                                                                            "out vec4 fragColor;\n"
142                                                                            "\n"
143                                                                            "layout (location = 1<FORMAT_DEF>) uniform <INPUT_TYPE> uni_in;\n"
144                                                                            "\n"
145                                                                            "void main()\n"
146                                                                            "{\n"
147                                                                            "    <COORD_TYPE> coord = texCoord;\n"
148                                                                            "    <ICOORD_TYPE> texSize = <ICOORD_TYPE>(<SIZE_DEF>);\n"
149                                                                            "    <POINT_TYPE> point = <POINT_TYPE>(coord * texSize);\n"
150                                                                            "    <RETURN_TYPE> retValue,\n"
151                                                                            "                  expValue,\n"
152                                                                            "                  epsilon;\n"
153                                                                            "    retValue = <RETURN_TYPE>(0);\n"
154                                                                            "    expValue = <RETURN_TYPE><RESULT_EXPECTED>;\n"
155                                                                            "    epsilon = <RETURN_TYPE>(<EPSILON>);\n"
156                                                                            "\n"
157                                                                            "<CUBE_MAP_COORD_DEF>\n"
158                                                                            "<OFFSET_ARRAY_DEF>\n"
159                                                                            "\n"
160                                                                            "<FUNCTION_DEF>\n"
161                                                                            "\n"
162                                                                            "    fragColor = vec4(1);\n"
163                                                                            "\n"
164                                                                            "    if (any(greaterThan(retValue, expValue + epsilon)) ||\n"
165                                                                            "        any(lessThan(retValue, expValue - epsilon)))\n"
166                                                                            "    {\n"
167                                                                            "        fragColor = vec4(0);\n"
168                                                                            "    }\n"
169                                                                            "}\n";
170
171 /** Constructor.
172  *
173  *  @param context     Rendering context
174  */
175 SparseTextureClampLookupResidencyTestCase::SparseTextureClampLookupResidencyTestCase(deqp::Context& context)
176         : SparseTexture2LookupTestCase(
177                   context, "SparseTextureClampLookupResidency",
178                   "Verifies if sparse texture clamp lookup functions generates access residency information")
179 {
180         /* Left blank intentionally */
181 }
182
183 /** Constructor.
184  *
185  *  @param context     Rendering context
186  */
187 SparseTextureClampLookupResidencyTestCase::SparseTextureClampLookupResidencyTestCase(deqp::Context& context,
188                                                                                                                                                                          const char*    name,
189                                                                                                                                                                          const char*    description)
190         : SparseTexture2LookupTestCase(context, name, description)
191 {
192         /* Left blank intentionally */
193 }
194
195 /** Stub init method */
196 void SparseTextureClampLookupResidencyTestCase::init()
197 {
198         SparseTextureCommitmentTestCase::init();
199         mSupportedInternalFormats.push_back(GL_DEPTH_COMPONENT16);
200
201         FunctionToken f;
202         f = FunctionToken("sparseTextureClampARB", "<CUBE_REFZ_DEF>, <LOD>");
203         f.allowedTargets.insert(GL_TEXTURE_2D);
204         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
205         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
206         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
207         f.allowedTargets.insert(GL_TEXTURE_3D);
208         mFunctions.push_back(f);
209
210         f = FunctionToken("sparseTextureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
211         f.allowedTargets.insert(GL_TEXTURE_2D);
212         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
213         f.allowedTargets.insert(GL_TEXTURE_3D);
214         mFunctions.push_back(f);
215
216         f = FunctionToken("sparseTextureGradClampARB",
217                                           ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
218         f.allowedTargets.insert(GL_TEXTURE_2D);
219         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
220         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
221         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
222         f.allowedTargets.insert(GL_TEXTURE_3D);
223         mFunctions.push_back(f);
224
225         f = FunctionToken(
226                 "sparseTextureGradOffsetClampARB",
227                 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
228         f.allowedTargets.insert(GL_TEXTURE_2D);
229         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
230         f.allowedTargets.insert(GL_TEXTURE_3D);
231         mFunctions.push_back(f);
232 }
233
234 /** Executes test iteration.
235  *
236  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
237  */
238 tcu::TestNode::IterateResult SparseTextureClampLookupResidencyTestCase::iterate()
239 {
240         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture_clamp"))
241         {
242                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
243                 return STOP;
244         }
245
246         return SparseTexture2LookupTestCase::iterate();
247 }
248
249 /** Check if specific lookup function is allowed for specific target and format
250  *
251  * @param target       Target for which texture is binded
252  * @param format       Texture internal format
253  * @param funcToken    Texture lookup function structure
254  *
255  * @return Returns true if target/format combination is allowed, false otherwise.
256  */
257 bool SparseTextureClampLookupResidencyTestCase::funcAllowed(GLint target, GLint format, FunctionToken& funcToken)
258 {
259         if (funcToken.allowedTargets.find(target) == funcToken.allowedTargets.end())
260                 return false;
261
262         if (format == GL_DEPTH_COMPONENT16)
263         {
264                 if (target == GL_TEXTURE_CUBE_MAP_ARRAY &&
265                         (funcToken.name == "sparseTextureGradClampARB" || funcToken.name == "textureGradClampARB"))
266                         return false;
267         }
268
269         return true;
270 }
271
272 /** Verify if data stored in texture is as expected
273  *
274  * @param gl           GL API functions
275  * @param target       Target for which texture is binded
276  * @param format       Texture internal format
277  * @param texture      Texture object
278  * @param level        Texture mipmap level
279  * @param funcToken    Lookup function tokenize structure
280  *
281  * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
282  */
283 bool SparseTextureClampLookupResidencyTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format,
284                                                                                                                                                 GLuint& texture, GLint level,
285                                                                                                                                                 FunctionToken& funcToken)
286 {
287         mLog << "Verify Lookup Residency Texture Data [function: " << funcToken.name << ", level: " << level << "] - ";
288
289         if (level > mState.levels - 1)
290                 TCU_FAIL("Invalid level");
291
292         GLint width;
293         GLint height;
294         GLint depth;
295         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
296
297         //Committed region is limited to 1/2 of width
298         GLint widthCommitted = width / 2;
299
300         if (widthCommitted == 0 || height == 0 || depth < mState.minDepth)
301                 return true;
302
303         bool result = true;
304
305         if (target == GL_TEXTURE_CUBE_MAP)
306                 depth = depth * 6;
307
308         GLint texSize = width * height;
309
310         std::vector<GLubyte> vecExpData;
311         std::vector<GLubyte> vecOutData;
312         vecExpData.resize(texSize);
313         vecOutData.resize(texSize);
314         GLubyte* exp_data = vecExpData.data();
315         GLubyte* out_data = vecOutData.data();
316
317         // Expected data is 255 because
318         deMemset(exp_data, 255, texSize);
319
320         // Create verifying texture
321         GLint  verifyTarget = GL_TEXTURE_2D;
322         GLuint verifyTexture;
323         Texture::Generate(gl, verifyTexture);
324         Texture::Bind(gl, verifyTexture, verifyTarget);
325         Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth);
326         GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage");
327
328         GLuint fbo;
329         gl.genFramebuffers(1, &fbo);
330         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers");
331         gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
332         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
333         gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, verifyTarget, verifyTexture, 0);
334         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D");
335
336         gl.viewport(0, 0, width, height);
337
338         for (GLint z = 0; z < depth; ++z)
339         {
340                 for (int sample = 0; sample < mState.samples; ++sample)
341                 {
342                         deMemset(out_data, 0, texSize);
343
344                         Texture::Bind(gl, verifyTexture, verifyTarget);
345                         Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,
346                                                           (GLvoid*)out_data);
347                         GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage");
348
349                         std::string vertex   = stc_vertex_common;
350                         std::string fragment = stc_fragment_lookupResidency;
351
352                         // Make token copy to work on
353                         FunctionToken f = funcToken;
354
355                         // Adjust shader source to texture format
356                         TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f);
357
358                         replaceToken("<COORD_TYPE>", s.coordType.c_str(), vertex);
359
360                         replaceToken("<FUNCTION>", f.name.c_str(), fragment);
361                         replaceToken("<ARGUMENTS>", f.arguments.c_str(), fragment);
362
363                         replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), fragment);
364                         replaceToken("<INPUT_TYPE>", s.inputType.c_str(), fragment);
365                         replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), fragment);
366                         replaceToken("<LOD>", s.lod.c_str(), fragment);
367                         replaceToken("<LOD_DEF>", s.lodDef.c_str(), fragment);
368                         replaceToken("<COORD_TYPE>", s.coordType.c_str(), fragment);
369                         replaceToken("<ICOORD_TYPE>", s.iCoordType.c_str(), fragment);
370                         replaceToken("<COORD_DEF>", s.coordDef.c_str(), fragment);
371                         replaceToken("<POINT_TYPE>", s.pointType.c_str(), fragment);
372                         replaceToken("<POINT_DEF>", s.pointDef.c_str(), fragment);
373                         replaceToken("<RETURN_TYPE>", s.returnType.c_str(), fragment);
374                         replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), fragment);
375                         replaceToken("<EPSILON>", s.epsilon.c_str(), fragment);
376                         replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), fragment);
377                         replaceToken("<REFZ_DEF>", s.refZDef.c_str(), fragment);
378                         replaceToken("<CUBE_REFZ_DEF>", s.cubeMapArrayRefZDef.c_str(), fragment);
379                         replaceToken("<POINT_COORD>", s.pointCoord.c_str(), fragment);
380                         replaceToken("<COMPONENT_DEF>", s.componentDef.c_str(), fragment);
381                         replaceToken("<CUBE_MAP_COORD_DEF>", s.cubeMapCoordDef.c_str(), fragment);
382                         replaceToken("<OFFSET_ARRAY_DEF>", s.offsetArrayDef.c_str(), fragment);
383                         replaceToken("<FORMAT_DEF>", s.formatDef.c_str(), fragment);
384                         replaceToken("<OFFSET_TYPE>", s.offsetType.c_str(), fragment);
385                         replaceToken("<NOFFSET_TYPE>", s.nOffsetType.c_str(), fragment);
386                         replaceToken("<OFFSET_DIM>", s.offsetDim.c_str(), fragment);
387
388                         replaceToken("<TEX_WIDTH>", de::toString(width).c_str(), fragment);
389                         replaceToken("<TEX_HEIGHT>", de::toString(height).c_str(), fragment);
390                         replaceToken("<TEX_DEPTH>", de::toString(depth).c_str(), fragment);
391
392                         ProgramSources sources = makeVtxFragSources(vertex.c_str(), fragment.c_str());
393
394                         // Build and run shader
395                         ShaderProgram program(m_context.getRenderContext(), sources);
396                         if (program.isOk())
397                         {
398                                 gl.useProgram(program.getProgram());
399                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
400
401                                 // Pass input sampler/image to shader
402                                 gl.activeTexture(GL_TEXTURE0);
403                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
404                                 gl.uniform1i(1, 0 /* sampler_unit */);
405                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
406
407                                 // Pass committed region width to shader
408                                 gl.uniform1i(2, widthCommitted /* committed region width */);
409                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
410
411                                 gl.bindTexture(target, texture);
412                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
413
414                                 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
415                                 draw(target, z, program);
416
417                                 Texture::Bind(gl, verifyTexture, verifyTarget);
418                                 Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data);
419                                 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
420
421                                 //Verify only committed region
422                                 for (GLint y = 0; y < height; ++y)
423                                         for (GLint x = 0; x < width; ++x)
424                                         {
425                                                 GLubyte* dataRegion     = exp_data + x + y * width;
426                                                 GLubyte* outDataRegion = out_data + x + y * width;
427                                                 if (dataRegion[0] != outDataRegion[0])
428                                                         result = false;
429                                         }
430                         }
431                         else
432                         {
433                                 mLog << "Shader compilation failed (lookup residency) for target: " << target << ", format: " << format
434                                          << ", vertexInfoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog
435                                          << ", fragmentInfoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog
436                                          << ", programInfoLog: " << program.getProgramInfo().infoLog
437                                          << ", fragmentSource: " << fragment.c_str() << " - ";
438
439                                 result = false;
440                         }
441                 }
442         }
443
444         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
445         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
446
447         Texture::Delete(gl, verifyTexture);
448
449         return result;
450 }
451
452 void SparseTextureClampLookupResidencyTestCase::draw(GLint target, GLint layer, const ShaderProgram& program)
453 {
454         const GLfloat texCoord1D[] = { 0.0f, 1.0f, 0.0f, 1.0f };
455
456         const GLfloat texCoord2D[] = {
457                 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
458         };
459
460         const GLfloat texCoord3D[] = { 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f };
461
462         const GLfloat texCoordCubeMap[6][12] = {
463                 { 0.0f, 0.0f, 0.00f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f },
464                 { 0.0f, 0.0f, 0.17f, 1.0f, 0.0f, 0.17f, 0.0f, 1.0f, 0.17f, 1.0f, 1.0f, 0.17f },
465                 { 0.0f, 0.0f, 0.33f, 1.0f, 0.0f, 0.33f, 0.0f, 1.0f, 0.33f, 1.0f, 1.0f, 0.33f },
466                 { 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f },
467                 { 0.0f, 0.0f, 0.67f, 1.0f, 0.0f, 0.67f, 0.0f, 1.0f, 0.67f, 1.0f, 1.0f, 0.67f },
468                 { 0.0f, 0.0f, 0.83f, 1.0f, 0.0f, 0.83f, 0.0f, 1.0f, 0.83f, 1.0f, 1.0f, 0.83f }
469         };
470
471         const GLfloat vertices[] = {
472                 -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
473         };
474
475         const GLuint indices[] = { 0, 1, 2, 1, 2, 3 };
476
477         VertexArrayBinding floatCoord;
478
479         if (target == GL_TEXTURE_1D || target == GL_TEXTURE_1D_ARRAY)
480                 floatCoord = glu::va::Float("inCoord", 1, 4, 0, texCoord1D);
481         else if (target == GL_TEXTURE_3D)
482                 floatCoord = glu::va::Float("inCoord", 3, 4, 0, texCoord3D);
483         else if (target == GL_TEXTURE_CUBE_MAP)
484                 floatCoord = glu::va::Float("inCoord", 3, 4, 0, texCoordCubeMap[layer]);
485         else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
486         {
487                 GLfloat           layerCoord                       = GLfloat(layer) / 6.0f + 0.01f;
488                 const GLfloat texCoordCubeMapArray[16] = { 0.0f, 0.0f, layerCoord, GLfloat(layer),
489                                                                                                    1.0f, 0.0f, layerCoord, GLfloat(layer),
490                                                                                                    0.0f, 1.0f, layerCoord, GLfloat(layer),
491                                                                                                    1.0f, 1.0f, layerCoord, GLfloat(layer) };
492                 floatCoord = glu::va::Float("inCoord", 4, 4, 0, texCoordCubeMapArray);
493         }
494         else
495                 floatCoord = glu::va::Float("inCoord", 2, 4, 0, texCoord2D);
496
497         glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("vertex", 3, 4, 0, vertices), floatCoord };
498
499         glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
500                           glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(indices), indices));
501 }
502
503 /** Constructor.
504  *
505  *  @param context     Rendering context
506  */
507 SparseTextureClampLookupColorTestCase::SparseTextureClampLookupColorTestCase(deqp::Context& context)
508         : SparseTextureClampLookupResidencyTestCase(
509                   context, "SparseTextureClampLookupColor",
510                   "Verifies if sparse and non-sparse texture clamp lookup functions works as expected")
511 {
512         /* Left blank intentionally */
513 }
514
515 /** Stub init method */
516 void SparseTextureClampLookupColorTestCase::init()
517 {
518         SparseTextureCommitmentTestCase::init();
519         mSupportedTargets.push_back(GL_TEXTURE_1D);
520         mSupportedTargets.push_back(GL_TEXTURE_1D_ARRAY);
521         mSupportedInternalFormats.push_back(GL_DEPTH_COMPONENT16);
522
523         FunctionToken f;
524         f = FunctionToken("sparseTextureClampARB", "<CUBE_REFZ_DEF>, <LOD>");
525         f.allowedTargets.insert(GL_TEXTURE_2D);
526         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
527         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
528         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
529         f.allowedTargets.insert(GL_TEXTURE_3D);
530         mFunctions.push_back(f);
531
532         f = FunctionToken("textureClampARB", "<CUBE_REFZ_DEF>, <LOD>");
533         f.allowedTargets.insert(GL_TEXTURE_1D);
534         f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
535         f.allowedTargets.insert(GL_TEXTURE_2D);
536         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
537         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
538         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
539         f.allowedTargets.insert(GL_TEXTURE_3D);
540         mFunctions.push_back(f);
541
542         f = FunctionToken("sparseTextureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
543         f.allowedTargets.insert(GL_TEXTURE_2D);
544         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
545         f.allowedTargets.insert(GL_TEXTURE_3D);
546         mFunctions.push_back(f);
547
548         f = FunctionToken("textureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
549         f.allowedTargets.insert(GL_TEXTURE_1D);
550         f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
551         f.allowedTargets.insert(GL_TEXTURE_2D);
552         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
553         f.allowedTargets.insert(GL_TEXTURE_3D);
554         mFunctions.push_back(f);
555
556         f = FunctionToken("sparseTextureGradClampARB",
557                                           ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
558         f.allowedTargets.insert(GL_TEXTURE_2D);
559         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
560         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
561         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
562         f.allowedTargets.insert(GL_TEXTURE_3D);
563         mFunctions.push_back(f);
564
565         f = FunctionToken("textureGradClampARB", ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
566         f.allowedTargets.insert(GL_TEXTURE_1D);
567         f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
568         f.allowedTargets.insert(GL_TEXTURE_2D);
569         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
570         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
571         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
572         f.allowedTargets.insert(GL_TEXTURE_3D);
573         mFunctions.push_back(f);
574
575         f = FunctionToken(
576                 "sparseTextureGradOffsetClampARB",
577                 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
578         f.allowedTargets.insert(GL_TEXTURE_2D);
579         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
580         f.allowedTargets.insert(GL_TEXTURE_3D);
581         mFunctions.push_back(f);
582
583         f = FunctionToken(
584                 "textureGradOffsetClampARB",
585                 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
586         f.allowedTargets.insert(GL_TEXTURE_1D);
587         f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
588         f.allowedTargets.insert(GL_TEXTURE_2D);
589         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
590         f.allowedTargets.insert(GL_TEXTURE_3D);
591         mFunctions.push_back(f);
592 }
593
594 /** Executes test iteration.
595  *
596  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
597  */
598 tcu::TestNode::IterateResult SparseTextureClampLookupColorTestCase::iterate()
599 {
600         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture_clamp"))
601         {
602                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
603                 return STOP;
604         }
605
606         const Functions& gl = m_context.getRenderContext().getFunctions();
607
608         bool result = true;
609
610         GLuint texture;
611
612         for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
613                  ++iter)
614         {
615                 const GLint& target = *iter;
616
617                 for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
618                          formIter != mSupportedInternalFormats.end(); ++formIter)
619                 {
620                         const GLint& format = *formIter;
621
622                         if (!caseAllowed(target, format))
623                                 continue;
624
625                         for (std::vector<FunctionToken>::const_iterator tokIter = mFunctions.begin(); tokIter != mFunctions.end();
626                                  ++tokIter)
627                         {
628                                 // Check if target is allowed for current lookup function
629                                 FunctionToken funcToken = *tokIter;
630                                 if (!funcAllowed(target, format, funcToken))
631                                         continue;
632
633                                 bool isSparse = false;
634                                 if (funcToken.name.find("sparse", 0) != std::string::npos)
635                                         isSparse = true;
636
637                                 mLog.str("");
638                                 mLog << "Testing sparse texture lookup color functions for target: " << target << ", format: " << format
639                                          << " - ";
640
641                                 if (isSparse)
642                                         sparseAllocateTexture(gl, target, format, texture, 3);
643                                 else
644                                         allocateTexture(gl, target, format, texture, 3);
645
646                                 if (format == GL_DEPTH_COMPONENT16)
647                                         setupDepthMode(gl, target, texture);
648
649                                 int l;
650                                 int maxLevels = 0;
651                                 for (l = 0; l < mState.levels; ++l)
652                                 {
653                                         if (!isSparse || commitTexturePage(gl, target, format, texture, l))
654                                         {
655                                                 writeDataToTexture(gl, target, format, texture, l);
656                                                 maxLevels = l;
657                                         }
658                                 }
659
660                                 for (l = 0; l <= maxLevels; ++l)
661                                 {
662                                         result = result && verifyLookupTextureData(gl, target, format, texture, l, funcToken);
663
664                                         if (!result)
665                                                 break;
666                                 }
667
668                                 Texture::Delete(gl, texture);
669
670                                 if (!result)
671                                 {
672                                         m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
673                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
674                                         return STOP;
675                                 }
676                         }
677                 }
678         }
679
680         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
681         return STOP;
682 }
683
684 /** Writing data to generated texture using compute shader
685  *
686  * @param gl           GL API functions
687  * @param target       Target for which texture is binded
688  * @param format       Texture internal format
689  * @param texture      Texture object
690  *
691  * @return Returns true if no error occurred, otherwise throws an exception.
692  */
693 bool SparseTextureClampLookupColorTestCase::writeDataToTexture(const Functions& gl, GLint target, GLint format,
694                                                                                                                            GLuint& texture, GLint level)
695 {
696         mLog << "Fill Texture with shader [level: " << level << "] - ";
697
698         if (level > mState.levels - 1)
699                 TCU_FAIL("Invalid level");
700
701         GLint width;
702         GLint height;
703         GLint depth;
704         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
705
706         if (width > 0 && height > 0 && depth >= mState.minDepth)
707         {
708                 if (target == GL_TEXTURE_CUBE_MAP)
709                         depth = depth * 6;
710
711                 GLint texSize = width * height * depth * mState.format.getPixelSize();
712
713                 std::vector<GLubyte> vecData;
714                 vecData.resize(texSize);
715                 GLubyte* data = vecData.data();
716
717                 deMemset(data, 255, texSize);
718
719                 for (GLint sample = 0; sample < mState.samples; ++sample)
720                 {
721                         std::string shader = stc_compute_textureFill;
722
723                         // Adjust shader source to texture format
724                         TokenStrings s = createShaderTokens(target, format, sample);
725
726                         // Change expected result as it has to be adjusted to different levels
727                         s.resultExpected = generateExpectedResult(s.returnType, level);
728
729                         replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader);
730                         replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader);
731                         replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader);
732                         replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader);
733                         replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), shader);
734                         replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader);
735
736                         ProgramSources sources;
737                         sources << ComputeSource(shader);
738
739                         GLint convFormat = format;
740                         if (format == GL_DEPTH_COMPONENT16)
741                                 convFormat = GL_R16;
742
743                         // Build and run shader
744                         ShaderProgram program(m_context.getRenderContext(), sources);
745                         if (program.isOk())
746                         {
747                                 gl.useProgram(program.getProgram());
748                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
749                                 gl.bindImageTexture(0 /* unit */, texture, level /* level */, GL_FALSE /* layered */, 0 /* layer */,
750                                                                         GL_WRITE_ONLY, convFormat);
751                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture");
752                                 gl.uniform1i(1, 0 /* image_unit */);
753                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
754                                 gl.dispatchCompute(width, height, depth);
755                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute");
756                                 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
757                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier");
758                         }
759                         else
760                         {
761                                 mLog << "Compute shader compilation failed (writing) for target: " << target << ", format: " << format
762                                          << ", sample: " << sample << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog
763                                          << ", shaderSource: " << shader.c_str() << " - ";
764                         }
765                 }
766         }
767
768         return true;
769 }
770
771 /** Verify if data stored in texture is as expected
772  *
773  * @param gl           GL API functions
774  * @param target       Target for which texture is binded
775  * @param format       Texture internal format
776  * @param texture      Texture object
777  * @param level        Texture mipmap level
778  * @param funcToken    Lookup function tokenize structure
779  *
780  * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
781  */
782 bool SparseTextureClampLookupColorTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format,
783                                                                                                                                         GLuint& texture, GLint level,
784                                                                                                                                         FunctionToken& funcToken)
785 {
786         mLog << "Verify Lookup Color Texture Data [function: " << funcToken.name << ", level: " << level << "] - ";
787
788         if (level > mState.levels - 1)
789                 TCU_FAIL("Invalid level");
790
791         GLint width;
792         GLint height;
793         GLint depth;
794         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
795
796         if (width == 0 || height == 0 || depth < mState.minDepth)
797                 return true;
798
799         bool result = true;
800
801         if (target == GL_TEXTURE_CUBE_MAP)
802                 depth = depth * 6;
803
804         GLint texSize = width * height;
805
806         std::vector<GLubyte> vecExpData;
807         std::vector<GLubyte> vecOutData;
808         vecExpData.resize(texSize);
809         vecOutData.resize(texSize);
810         GLubyte* exp_data = vecExpData.data();
811         GLubyte* out_data = vecOutData.data();
812
813         // Expected data is 255 because
814         deMemset(exp_data, 255, texSize);
815
816         // Create verifying texture
817         GLint  verifyTarget = GL_TEXTURE_2D;
818         GLuint verifyTexture;
819         Texture::Generate(gl, verifyTexture);
820         Texture::Bind(gl, verifyTexture, verifyTarget);
821         Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth);
822         GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage");
823
824         GLuint fbo;
825         gl.genFramebuffers(1, &fbo);
826         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers");
827         gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
828         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
829         gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, verifyTarget, verifyTexture, 0);
830         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D");
831
832         gl.viewport(0, 0, width, height);
833
834         for (GLint z = 0; z < depth; ++z)
835         {
836                 for (int sample = 0; sample < mState.samples; ++sample)
837                 {
838                         deMemset(out_data, 0, texSize);
839
840                         Texture::Bind(gl, verifyTexture, verifyTarget);
841                         Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,
842                                                           (GLvoid*)out_data);
843                         GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage");
844
845                         std::string vertex   = stc_vertex_common;
846                         std::string fragment = stc_fragment_lookupColor;
847
848                         // Make token copy to work on
849                         FunctionToken f = funcToken;
850
851                         std::string functionDef = generateFunctionDef(f.name);
852
853                         // Adjust shader source to texture format
854                         TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f);
855
856                         // Change expected result as it has to be adjusted to different levels
857                         s.resultExpected = generateExpectedResult(s.returnType, level);
858
859                         replaceToken("<COORD_TYPE>", s.coordType.c_str(), vertex);
860
861                         replaceToken("<FUNCTION_DEF>", functionDef.c_str(), fragment);
862                         replaceToken("<FUNCTION>", f.name.c_str(), fragment);
863                         replaceToken("<ARGUMENTS>", f.arguments.c_str(), fragment);
864
865                         replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), fragment);
866                         replaceToken("<INPUT_TYPE>", s.inputType.c_str(), fragment);
867                         replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), fragment);
868                         replaceToken("<LOD>", s.lod.c_str(), fragment);
869                         replaceToken("<LOD_DEF>", s.lodDef.c_str(), fragment);
870                         replaceToken("<COORD_TYPE>", s.coordType.c_str(), fragment);
871                         replaceToken("<ICOORD_TYPE>", s.coordType.c_str(), fragment);
872                         replaceToken("<COORD_DEF>", s.coordDef.c_str(), fragment);
873                         replaceToken("<POINT_TYPE>", s.pointType.c_str(), fragment);
874                         replaceToken("<POINT_DEF>", s.pointDef.c_str(), fragment);
875                         replaceToken("<RETURN_TYPE>", s.returnType.c_str(), fragment);
876                         replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), fragment);
877                         replaceToken("<EPSILON>", s.epsilon.c_str(), fragment);
878                         replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), fragment);
879                         replaceToken("<REFZ_DEF>", s.refZDef.c_str(), fragment);
880                         replaceToken("<CUBE_REFZ_DEF>", s.cubeMapArrayRefZDef.c_str(), fragment);
881                         replaceToken("<POINT_COORD>", s.pointCoord.c_str(), fragment);
882                         replaceToken("<COMPONENT_DEF>", s.componentDef.c_str(), fragment);
883                         replaceToken("<CUBE_MAP_COORD_DEF>", s.cubeMapCoordDef.c_str(), fragment);
884                         replaceToken("<OFFSET_ARRAY_DEF>", s.offsetArrayDef.c_str(), fragment);
885                         replaceToken("<FORMAT_DEF>", s.formatDef.c_str(), fragment);
886                         replaceToken("<OFFSET_TYPE>", s.offsetType.c_str(), fragment);
887                         replaceToken("<NOFFSET_TYPE>", s.nOffsetType.c_str(), fragment);
888                         replaceToken("<OFFSET_DIM>", s.offsetDim.c_str(), fragment);
889
890                         replaceToken("<TEX_WIDTH>", de::toString(width).c_str(), fragment);
891                         replaceToken("<TEX_HEIGHT>", de::toString(height).c_str(), fragment);
892                         replaceToken("<TEX_DEPTH>", de::toString(depth).c_str(), fragment);
893
894                         ProgramSources sources = makeVtxFragSources(vertex.c_str(), fragment.c_str());
895
896                         // Build and run shader
897                         ShaderProgram program(m_context.getRenderContext(), sources);
898                         if (program.isOk())
899                         {
900                                 gl.useProgram(program.getProgram());
901                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
902
903                                 // Pass input sampler/image to shader
904                                 gl.activeTexture(GL_TEXTURE0);
905                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
906                                 gl.uniform1i(1, 0 /* sampler_unit */);
907                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
908
909                                 gl.bindTexture(target, texture);
910                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
911
912                                 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
913                                 draw(target, z, program);
914
915                                 Texture::Bind(gl, verifyTexture, verifyTarget);
916                                 Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data);
917                                 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
918
919                                 //Verify only committed region
920                                 for (GLint y = 0; y < height; ++y)
921                                         for (GLint x = 0; x < width; ++x)
922                                         {
923                                                 GLubyte* dataRegion     = exp_data + x + y * width;
924                                                 GLubyte* outDataRegion = out_data + x + y * width;
925                                                 if (dataRegion[0] != outDataRegion[0])
926                                                         result = false;
927                                         }
928                         }
929                         else
930                         {
931                                 mLog << "Shader compilation failed (lookup color) for target: " << target << ", format: " << format
932                                          << ", vertexInfoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog
933                                          << ", fragmentInfoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog
934                                          << ", programInfoLog: " << program.getProgramInfo().infoLog
935                                          << ", fragmentSource: " << fragment.c_str() << " - ";
936
937                                 result = false;
938                         }
939                 }
940         }
941
942         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
943         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
944
945         Texture::Delete(gl, verifyTexture);
946
947         return result;
948 }
949
950 /** Preparing texture. Function overridden to increase textures size.
951  *
952  * @param gl           GL API functions
953  * @param target       Target for which texture is binded
954  * @param format       Texture internal format
955  * @param texture      Texture object
956  *
957  * @return Returns true if no error occurred, otherwise throws an exception.
958  */
959 bool SparseTextureClampLookupColorTestCase::prepareTexture(const Functions& gl, GLint target, GLint format,
960                                                                                                                    GLuint& texture)
961 {
962         Texture::Generate(gl, texture);
963         Texture::Bind(gl, texture, target);
964
965         mState.minDepth = SparseTextureUtils::getTargetDepth(target);
966         SparseTextureUtils::getTexturePageSizes(gl, target, format, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ);
967
968         //The <width> and <height> has to be equal for cube map textures
969         if (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY)
970         {
971                 if (mState.pageSizeX > mState.pageSizeY)
972                         mState.pageSizeY = mState.pageSizeX;
973                 else if (mState.pageSizeX < mState.pageSizeY)
974                         mState.pageSizeX = mState.pageSizeY;
975         }
976
977         mState.width  = 4 * mState.pageSizeX;
978         mState.height = 4 * mState.pageSizeY;
979         mState.depth  = 4 * mState.pageSizeZ * mState.minDepth;
980
981         mState.format = glu::mapGLInternalFormat(format);
982
983         return true;
984 }
985
986 /** Commit texture page using texPageCommitment function. Function overridden to commit whole texture region.
987  *
988  * @param gl           GL API functions
989  * @param target       Target for which texture is binded
990  * @param format       Texture internal format
991  * @param texture      Texture object
992  * @param level        Texture mipmap level
993  *
994  * @return Returns true if commitment is done properly, false if commitment is not allowed or throws exception if error occurred.
995  */
996 bool SparseTextureClampLookupColorTestCase::commitTexturePage(const Functions& gl, GLint target, GLint format,
997                                                                                                                           GLuint& texture, GLint level)
998 {
999         mLog << "Commit Region [level: " << level << "] - ";
1000
1001         if (level > mState.levels - 1)
1002                 TCU_FAIL("Invalid level");
1003
1004         // Avoid not allowed commitments
1005         if (!isInPageSizesRange(target, level) || !isPageSizesMultiplication(target, level))
1006         {
1007                 mLog << "Skip commitment [level: " << level << "] - ";
1008                 return false;
1009         }
1010
1011         GLint width;
1012         GLint height;
1013         GLint depth;
1014         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1015
1016         if (target == GL_TEXTURE_CUBE_MAP)
1017                 depth = 6 * depth;
1018
1019         Texture::Bind(gl, texture, target);
1020         texPageCommitment(gl, target, format, texture, level, 0, 0, 0, width, height, depth, GL_TRUE);
1021         GLU_EXPECT_NO_ERROR(gl.getError(), "texPageCommitment");
1022
1023         return true;
1024 }
1025
1026 /** Check if current texture size for level is greater or equal page size in a corresponding direction
1027  *
1028  * @param target  Target for which texture is binded
1029  * @param level   Texture mipmap level
1030  *
1031  * @return Returns true if the texture size condition is fulfilled, false otherwise.
1032  */
1033 bool SparseTextureClampLookupColorTestCase::isInPageSizesRange(GLint target, GLint level)
1034 {
1035         GLint width;
1036         GLint height;
1037         GLint depth;
1038         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1039
1040         if (target == GL_TEXTURE_CUBE_MAP)
1041                 depth = 6 * depth;
1042
1043         if (width >= mState.pageSizeX && height >= mState.pageSizeY && (mState.minDepth == 0 || depth >= mState.pageSizeZ))
1044         {
1045                 return true;
1046         }
1047
1048         return false;
1049 }
1050
1051 /** Check if current texture size for level is page size multiplication in a corresponding direction
1052  *
1053  * @param target  Target for which texture is binded
1054  * @param level   Texture mipmap level
1055  *
1056  * @return Returns true if the texture size condition is fulfilled, false otherwise.
1057  */
1058 bool SparseTextureClampLookupColorTestCase::isPageSizesMultiplication(GLint target, GLint level)
1059 {
1060         GLint width;
1061         GLint height;
1062         GLint depth;
1063         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1064
1065         if (target == GL_TEXTURE_CUBE_MAP)
1066                 depth = 6 * depth;
1067
1068         if ((width % mState.pageSizeX) == 0 && (height % mState.pageSizeY) == 0 && (depth % mState.pageSizeZ) == 0)
1069         {
1070                 return true;
1071         }
1072
1073         return false;
1074 }
1075
1076 /** Constructor.
1077  *
1078  * @param funcName Tested function name.
1079  *
1080  * @return Returns shader source code part that uses lookup function to fetch texel from texture.
1081  */
1082 std::string SparseTextureClampLookupColorTestCase::generateFunctionDef(std::string funcName)
1083 {
1084         if (funcName.find("sparse", 0) != std::string::npos)
1085         {
1086                 return std::string("    <FUNCTION>(uni_in,\n"
1087                                                    "               <POINT_COORD><SAMPLE_DEF><ARGUMENTS>,\n"
1088                                                    "               retValue<COMPONENT_DEF>);\n");
1089         }
1090         else
1091         {
1092                 return std::string("    retValue<COMPONENT_DEF> = <FUNCTION>(uni_in,\n"
1093                                                    "                                         <POINT_COORD><SAMPLE_DEF><ARGUMENTS>);\n");
1094         }
1095 }
1096
1097 /** Constructor.
1098  *
1099  * @param returnType Expected result variable type.
1100  *
1101  * @return Returns shader source token that represent expected lookup result value.
1102  */
1103 std::string SparseTextureClampLookupColorTestCase::generateExpectedResult(std::string returnType, GLint level)
1104 {
1105         if (returnType == "vec4")
1106                 return std::string("(") + de::toString(0.5f + (float)level / 10) + std::string(", 0, 0, 1)");
1107         else
1108                 return std::string("(") + de::toString(level * 10) + std::string(", 0, 0, 1)");
1109 }
1110
1111 /** Constructor.
1112  *
1113  *  @param context Rendering context.
1114  */
1115 SparseTextureClampTests::SparseTextureClampTests(deqp::Context& context)
1116         : TestCaseGroup(context, "sparse_texture_clamp_tests",
1117                                         "Verify conformance of CTS_ARB_sparse_texture_clamp implementation")
1118 {
1119 }
1120
1121 /** Initializes the test group contents. */
1122 void SparseTextureClampTests::init()
1123 {
1124         addChild(new ShaderExtensionTestCase(m_context, "GL_ARB_sparse_texture_clamp"));
1125         addChild(new SparseTextureClampLookupResidencyTestCase(m_context));
1126         addChild(new SparseTextureClampLookupColorTestCase(m_context));
1127 }
1128
1129 } /* gl4cts namespace */