accf914a6cf30f0d21dff5272e3bccfd68c8dd90
[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", ", <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 && funcToken.name == "sparseTextureGradClampARB")
265                         return false;
266         }
267
268         return true;
269 }
270
271 /** Verify if data stored in texture is as expected
272  *
273  * @param gl           GL API functions
274  * @param target       Target for which texture is binded
275  * @param format       Texture internal format
276  * @param texture      Texture object
277  * @param level        Texture mipmap level
278  * @param funcToken    Lookup function tokenize structure
279  *
280  * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
281  */
282 bool SparseTextureClampLookupResidencyTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format,
283                                                                                                                                                 GLuint& texture, GLint level,
284                                                                                                                                                 FunctionToken& funcToken)
285 {
286         mLog << "Verify Lookup Residency Texture Data [function: " << funcToken.name << ", level: " << level << "] - ";
287
288         if (level > mState.levels - 1)
289                 TCU_FAIL("Invalid level");
290
291         GLint width;
292         GLint height;
293         GLint depth;
294         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
295
296         //Committed region is limited to 1/2 of width
297         GLint widthCommitted = width / 2;
298
299         if (widthCommitted == 0 || height == 0 || depth < mState.minDepth)
300                 return true;
301
302         bool result = true;
303
304         if (target == GL_TEXTURE_CUBE_MAP)
305                 depth = depth * 6;
306
307         GLint texSize = width * height;
308
309         std::vector<GLubyte> vecExpData;
310         std::vector<GLubyte> vecOutData;
311         vecExpData.resize(texSize);
312         vecOutData.resize(texSize);
313         GLubyte* exp_data = vecExpData.data();
314         GLubyte* out_data = vecOutData.data();
315
316         // Expected data is 255 because
317         deMemset(exp_data, 255, texSize);
318
319         // Create verifying texture
320         GLint  verifyTarget = GL_TEXTURE_2D;
321         GLuint verifyTexture;
322         Texture::Generate(gl, verifyTexture);
323         Texture::Bind(gl, verifyTexture, verifyTarget);
324         Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth);
325         GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage");
326
327         GLuint fbo;
328         gl.genFramebuffers(1, &fbo);
329         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers");
330         gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
331         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
332         gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, verifyTarget, verifyTexture, 0);
333         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D");
334
335         gl.viewport(0, 0, width, height);
336
337         for (GLint z = 0; z < depth; ++z)
338         {
339                 for (int sample = 0; sample < mState.samples; ++sample)
340                 {
341                         deMemset(out_data, 0, texSize);
342
343                         Texture::Bind(gl, verifyTexture, verifyTarget);
344                         Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,
345                                                           (GLvoid*)out_data);
346                         GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage");
347
348                         std::string vertex   = stc_vertex_common;
349                         std::string fragment = stc_fragment_lookupResidency;
350
351                         // Make token copy to work on
352                         FunctionToken f = funcToken;
353
354                         // Adjust shader source to texture format
355                         TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f);
356
357                         replaceToken("<COORD_TYPE>", s.coordType.c_str(), vertex);
358
359                         replaceToken("<FUNCTION>", f.name.c_str(), fragment);
360                         replaceToken("<ARGUMENTS>", f.arguments.c_str(), fragment);
361
362                         replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), fragment);
363                         replaceToken("<INPUT_TYPE>", s.inputType.c_str(), fragment);
364                         replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), fragment);
365                         replaceToken("<LOD>", s.lod.c_str(), fragment);
366                         replaceToken("<LOD_DEF>", s.lodDef.c_str(), fragment);
367                         replaceToken("<COORD_TYPE>", s.coordType.c_str(), fragment);
368                         replaceToken("<ICOORD_TYPE>", s.iCoordType.c_str(), fragment);
369                         replaceToken("<COORD_DEF>", s.coordDef.c_str(), fragment);
370                         replaceToken("<POINT_TYPE>", s.pointType.c_str(), fragment);
371                         replaceToken("<POINT_DEF>", s.pointDef.c_str(), fragment);
372                         replaceToken("<RETURN_TYPE>", s.returnType.c_str(), fragment);
373                         replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), fragment);
374                         replaceToken("<EPSILON>", s.epsilon.c_str(), fragment);
375                         replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), fragment);
376                         replaceToken("<REFZ_DEF>", s.refZDef.c_str(), fragment);
377                         replaceToken("<POINT_COORD>", s.pointCoord.c_str(), fragment);
378                         replaceToken("<COMPONENT_DEF>", s.componentDef.c_str(), fragment);
379                         replaceToken("<CUBE_MAP_COORD_DEF>", s.cubeMapCoordDef.c_str(), fragment);
380                         replaceToken("<OFFSET_ARRAY_DEF>", s.offsetArrayDef.c_str(), fragment);
381                         replaceToken("<FORMAT_DEF>", s.formatDef.c_str(), fragment);
382                         replaceToken("<OFFSET_TYPE>", s.offsetType.c_str(), fragment);
383                         replaceToken("<NOFFSET_TYPE>", s.nOffsetType.c_str(), fragment);
384                         replaceToken("<OFFSET_DIM>", s.offsetDim.c_str(), fragment);
385
386                         replaceToken("<TEX_WIDTH>", de::toString(width).c_str(), fragment);
387                         replaceToken("<TEX_HEIGHT>", de::toString(height).c_str(), fragment);
388                         replaceToken("<TEX_DEPTH>", de::toString(depth).c_str(), fragment);
389
390                         ProgramSources sources = makeVtxFragSources(vertex.c_str(), fragment.c_str());
391
392                         // Build and run shader
393                         ShaderProgram program(m_context.getRenderContext(), sources);
394                         if (program.isOk())
395                         {
396                                 gl.useProgram(program.getProgram());
397                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
398
399                                 // Pass input sampler/image to shader
400                                 gl.activeTexture(GL_TEXTURE0);
401                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
402                                 gl.uniform1i(1, 0 /* sampler_unit */);
403                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
404
405                                 // Pass committed region width to shader
406                                 gl.uniform1i(2, widthCommitted /* committed region width */);
407                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
408
409                                 gl.bindTexture(target, texture);
410                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
411
412                                 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
413                                 draw(target, z, program);
414
415                                 Texture::Bind(gl, verifyTexture, verifyTarget);
416                                 Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data);
417                                 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
418
419                                 //Verify only committed region
420                                 for (GLint y = 0; y < height; ++y)
421                                         for (GLint x = 0; x < width; ++x)
422                                         {
423                                                 GLubyte* dataRegion     = exp_data + x + y * width;
424                                                 GLubyte* outDataRegion = out_data + x + y * width;
425                                                 if (dataRegion[0] != outDataRegion[0])
426                                                         result = false;
427                                         }
428                         }
429                         else
430                         {
431                                 mLog << "Shader compilation failed (lookup residency) for target: " << target << ", format: " << format
432                                          << ", vertexInfoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog
433                                          << ", fragmentInfoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog
434                                          << ", programInfoLog: " << program.getProgramInfo().infoLog
435                                          << ", fragmentSource: " << fragment.c_str() << " - ";
436
437                                 result = false;
438                         }
439                 }
440         }
441
442         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
443         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
444
445         Texture::Delete(gl, verifyTexture);
446
447         return result;
448 }
449
450 void SparseTextureClampLookupResidencyTestCase::draw(GLint target, GLint layer, const ShaderProgram& program)
451 {
452         const GLfloat texCoord1D[] = { 0.0f, 1.0f, 0.0f, 1.0f };
453
454         const GLfloat texCoord2D[] = {
455                 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
456         };
457
458         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 };
459
460         const GLfloat texCoordCubeMap[6][12] = {
461                 { 0.0f, 0.0f, 0.00f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f },
462                 { 0.0f, 0.0f, 0.17f, 1.0f, 0.0f, 0.17f, 0.0f, 1.0f, 0.17f, 1.0f, 1.0f, 0.17f },
463                 { 0.0f, 0.0f, 0.33f, 1.0f, 0.0f, 0.33f, 0.0f, 1.0f, 0.33f, 1.0f, 1.0f, 0.33f },
464                 { 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f },
465                 { 0.0f, 0.0f, 0.67f, 1.0f, 0.0f, 0.67f, 0.0f, 1.0f, 0.67f, 1.0f, 1.0f, 0.67f },
466                 { 0.0f, 0.0f, 0.83f, 1.0f, 0.0f, 0.83f, 0.0f, 1.0f, 0.83f, 1.0f, 1.0f, 0.83f }
467         };
468
469         const GLfloat vertices[] = {
470                 -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
471         };
472
473         const GLuint indices[] = { 0, 1, 2, 1, 2, 3 };
474
475         VertexArrayBinding floatCoord;
476
477         if (target == GL_TEXTURE_1D || target == GL_TEXTURE_1D_ARRAY)
478                 floatCoord = glu::va::Float("inCoord", 1, 4, 0, texCoord1D);
479         else if (target == GL_TEXTURE_3D)
480                 floatCoord = glu::va::Float("inCoord", 3, 4, 0, texCoord3D);
481         else if (target == GL_TEXTURE_CUBE_MAP)
482                 floatCoord = glu::va::Float("inCoord", 3, 4, 0, texCoordCubeMap[layer]);
483         else
484                 floatCoord = glu::va::Float("inCoord", 2, 4, 0, texCoord2D);
485
486         glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("vertex", 3, 4, 0, vertices), floatCoord };
487
488         glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
489                           glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(indices), indices));
490 }
491
492 /** Constructor.
493  *
494  *  @param context     Rendering context
495  */
496 SparseTextureClampLookupColorTestCase::SparseTextureClampLookupColorTestCase(deqp::Context& context)
497         : SparseTextureClampLookupResidencyTestCase(
498                   context, "SparseTextureClampLookupColor",
499                   "Verifies if sparse and non-sparse texture clamp lookup functions works as expected")
500 {
501         /* Left blank intentionally */
502 }
503
504 /** Stub init method */
505 void SparseTextureClampLookupColorTestCase::init()
506 {
507         SparseTextureCommitmentTestCase::init();
508         mSupportedTargets.push_back(GL_TEXTURE_1D);
509         mSupportedTargets.push_back(GL_TEXTURE_1D_ARRAY);
510         mSupportedInternalFormats.push_back(GL_DEPTH_COMPONENT16);
511
512         FunctionToken f;
513         f = FunctionToken("sparseTextureClampARB", ", <LOD>");
514         f.allowedTargets.insert(GL_TEXTURE_2D);
515         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
516         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
517         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
518         f.allowedTargets.insert(GL_TEXTURE_3D);
519         mFunctions.push_back(f);
520
521         f = FunctionToken("textureClampARB", ", <LOD>");
522         f.allowedTargets.insert(GL_TEXTURE_1D);
523         f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
524         f.allowedTargets.insert(GL_TEXTURE_2D);
525         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
526         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
527         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
528         f.allowedTargets.insert(GL_TEXTURE_3D);
529         mFunctions.push_back(f);
530
531         f = FunctionToken("sparseTextureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
532         f.allowedTargets.insert(GL_TEXTURE_2D);
533         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
534         f.allowedTargets.insert(GL_TEXTURE_3D);
535         mFunctions.push_back(f);
536
537         f = FunctionToken("textureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
538         f.allowedTargets.insert(GL_TEXTURE_1D);
539         f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
540         f.allowedTargets.insert(GL_TEXTURE_2D);
541         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
542         f.allowedTargets.insert(GL_TEXTURE_3D);
543         mFunctions.push_back(f);
544
545         f = FunctionToken("sparseTextureGradClampARB",
546                                           ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
547         f.allowedTargets.insert(GL_TEXTURE_2D);
548         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
549         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
550         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
551         f.allowedTargets.insert(GL_TEXTURE_3D);
552         mFunctions.push_back(f);
553
554         f = FunctionToken("textureGradClampARB", ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
555         f.allowedTargets.insert(GL_TEXTURE_1D);
556         f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
557         f.allowedTargets.insert(GL_TEXTURE_2D);
558         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
559         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
560         f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
561         f.allowedTargets.insert(GL_TEXTURE_3D);
562         mFunctions.push_back(f);
563
564         f = FunctionToken(
565                 "sparseTextureGradOffsetClampARB",
566                 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
567         f.allowedTargets.insert(GL_TEXTURE_2D);
568         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
569         f.allowedTargets.insert(GL_TEXTURE_3D);
570         mFunctions.push_back(f);
571
572         f = FunctionToken(
573                 "textureGradOffsetClampARB",
574                 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
575         f.allowedTargets.insert(GL_TEXTURE_1D);
576         f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
577         f.allowedTargets.insert(GL_TEXTURE_2D);
578         f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
579         f.allowedTargets.insert(GL_TEXTURE_3D);
580         mFunctions.push_back(f);
581 }
582
583 /** Executes test iteration.
584  *
585  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
586  */
587 tcu::TestNode::IterateResult SparseTextureClampLookupColorTestCase::iterate()
588 {
589         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture_clamp"))
590         {
591                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
592                 return STOP;
593         }
594
595         const Functions& gl = m_context.getRenderContext().getFunctions();
596
597         bool result = true;
598
599         GLuint texture;
600
601         for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
602                  ++iter)
603         {
604                 const GLint& target = *iter;
605
606                 for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
607                          formIter != mSupportedInternalFormats.end(); ++formIter)
608                 {
609                         const GLint& format = *formIter;
610
611                         if (!caseAllowed(target, format))
612                                 continue;
613
614                         for (std::vector<FunctionToken>::const_iterator tokIter = mFunctions.begin(); tokIter != mFunctions.end();
615                                  ++tokIter)
616                         {
617                                 // Check if target is allowed for current lookup function
618                                 FunctionToken funcToken = *tokIter;
619                                 if (!funcAllowed(target, format, funcToken))
620                                         continue;
621
622                                 bool isSparse = false;
623                                 if (funcToken.name.find("sparse", 0) != std::string::npos)
624                                         isSparse = true;
625
626                                 mLog.str("");
627                                 mLog << "Testing sparse texture lookup color functions for target: " << target << ", format: " << format
628                                          << " - ";
629
630                                 if (isSparse)
631                                         sparseAllocateTexture(gl, target, format, texture, 3);
632                                 else
633                                         allocateTexture(gl, target, format, texture, 3);
634
635                                 if (format == GL_DEPTH_COMPONENT16)
636                                         setupDepthMode(gl, target, texture);
637
638                                 int l;
639                                 int maxLevels = 0;
640                                 for (l = 0; l < mState.levels; ++l)
641                                 {
642                                         if (!isSparse || commitTexturePage(gl, target, format, texture, l))
643                                         {
644                                                 writeDataToTexture(gl, target, format, texture, l);
645                                                 maxLevels = l;
646                                         }
647                                 }
648
649                                 for (l = 0; l <= maxLevels; ++l)
650                                 {
651                                         result = result && verifyLookupTextureData(gl, target, format, texture, l, funcToken);
652
653                                         if (!result)
654                                                 break;
655                                 }
656
657                                 Texture::Delete(gl, texture);
658
659                                 if (!result)
660                                 {
661                                         m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
662                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
663                                         return STOP;
664                                 }
665                         }
666                 }
667         }
668
669         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
670         return STOP;
671 }
672
673 /** Writing data to generated texture using compute shader
674  *
675  * @param gl           GL API functions
676  * @param target       Target for which texture is binded
677  * @param format       Texture internal format
678  * @param texture      Texture object
679  *
680  * @return Returns true if no error occurred, otherwise throws an exception.
681  */
682 bool SparseTextureClampLookupColorTestCase::writeDataToTexture(const Functions& gl, GLint target, GLint format,
683                                                                                                                            GLuint& texture, GLint level)
684 {
685         mLog << "Fill Texture with shader [level: " << level << "] - ";
686
687         if (level > mState.levels - 1)
688                 TCU_FAIL("Invalid level");
689
690         GLint width;
691         GLint height;
692         GLint depth;
693         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
694
695         if (width > 0 && height > 0 && depth >= mState.minDepth)
696         {
697                 if (target == GL_TEXTURE_CUBE_MAP)
698                         depth = depth * 6;
699
700                 GLint texSize = width * height * depth * mState.format.getPixelSize();
701
702                 std::vector<GLubyte> vecData;
703                 vecData.resize(texSize);
704                 GLubyte* data = vecData.data();
705
706                 deMemset(data, 255, texSize);
707
708                 for (GLint sample = 0; sample < mState.samples; ++sample)
709                 {
710                         std::string shader = stc_compute_textureFill;
711
712                         // Adjust shader source to texture format
713                         TokenStrings s = createShaderTokens(target, format, sample);
714
715                         // Change expected result as it has to be adjusted to different levels
716                         s.resultExpected = generateExpectedResult(s.returnType, level);
717
718                         replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader);
719                         replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader);
720                         replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader);
721                         replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader);
722                         replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), shader);
723                         replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader);
724
725                         ProgramSources sources;
726                         sources << ComputeSource(shader);
727
728                         GLint convFormat = format;
729                         if (format == GL_DEPTH_COMPONENT16)
730                                 convFormat = GL_R16;
731
732                         // Build and run shader
733                         ShaderProgram program(m_context.getRenderContext(), sources);
734                         if (program.isOk())
735                         {
736                                 gl.useProgram(program.getProgram());
737                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
738                                 gl.bindImageTexture(0 /* unit */, texture, level /* level */, GL_FALSE /* layered */, 0 /* layer */,
739                                                                         GL_WRITE_ONLY, convFormat);
740                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture");
741                                 gl.uniform1i(1, 0 /* image_unit */);
742                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
743                                 gl.dispatchCompute(width, height, depth);
744                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute");
745                                 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
746                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier");
747                         }
748                         else
749                         {
750                                 mLog << "Compute shader compilation failed (writing) for target: " << target << ", format: " << format
751                                          << ", sample: " << sample << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog
752                                          << ", shaderSource: " << shader.c_str() << " - ";
753                         }
754                 }
755         }
756
757         return true;
758 }
759
760 /** Verify if data stored in texture is as expected
761  *
762  * @param gl           GL API functions
763  * @param target       Target for which texture is binded
764  * @param format       Texture internal format
765  * @param texture      Texture object
766  * @param level        Texture mipmap level
767  * @param funcToken    Lookup function tokenize structure
768  *
769  * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
770  */
771 bool SparseTextureClampLookupColorTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format,
772                                                                                                                                         GLuint& texture, GLint level,
773                                                                                                                                         FunctionToken& funcToken)
774 {
775         mLog << "Verify Lookup Color Texture Data [function: " << funcToken.name << ", level: " << level << "] - ";
776
777         if (level > mState.levels - 1)
778                 TCU_FAIL("Invalid level");
779
780         GLint width;
781         GLint height;
782         GLint depth;
783         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
784
785         if (width == 0 || height == 0 || depth < mState.minDepth)
786                 return true;
787
788         bool result = true;
789
790         if (target == GL_TEXTURE_CUBE_MAP)
791                 depth = depth * 6;
792
793         GLint texSize = width * height;
794
795         std::vector<GLubyte> vecExpData;
796         std::vector<GLubyte> vecOutData;
797         vecExpData.resize(texSize);
798         vecOutData.resize(texSize);
799         GLubyte* exp_data = vecExpData.data();
800         GLubyte* out_data = vecOutData.data();
801
802         // Expected data is 255 because
803         deMemset(exp_data, 255, texSize);
804
805         // Create verifying texture
806         GLint  verifyTarget = GL_TEXTURE_2D;
807         GLuint verifyTexture;
808         Texture::Generate(gl, verifyTexture);
809         Texture::Bind(gl, verifyTexture, verifyTarget);
810         Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth);
811         GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage");
812
813         GLuint fbo;
814         gl.genFramebuffers(1, &fbo);
815         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers");
816         gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
817         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
818         gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, verifyTarget, verifyTexture, 0);
819         GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D");
820
821         gl.viewport(0, 0, width, height);
822
823         for (GLint z = 0; z < depth; ++z)
824         {
825                 for (int sample = 0; sample < mState.samples; ++sample)
826                 {
827                         deMemset(out_data, 0, texSize);
828
829                         Texture::Bind(gl, verifyTexture, verifyTarget);
830                         Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,
831                                                           (GLvoid*)out_data);
832                         GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage");
833
834                         std::string vertex   = stc_vertex_common;
835                         std::string fragment = stc_fragment_lookupColor;
836
837                         // Make token copy to work on
838                         FunctionToken f = funcToken;
839
840                         std::string functionDef = generateFunctionDef(f.name);
841
842                         // Adjust shader source to texture format
843                         TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f);
844
845                         // Change expected result as it has to be adjusted to different levels
846                         s.resultExpected = generateExpectedResult(s.returnType, level);
847
848                         replaceToken("<COORD_TYPE>", s.coordType.c_str(), vertex);
849
850                         replaceToken("<FUNCTION_DEF>", functionDef.c_str(), fragment);
851                         replaceToken("<FUNCTION>", f.name.c_str(), fragment);
852                         replaceToken("<ARGUMENTS>", f.arguments.c_str(), fragment);
853
854                         replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), fragment);
855                         replaceToken("<INPUT_TYPE>", s.inputType.c_str(), fragment);
856                         replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), fragment);
857                         replaceToken("<LOD>", s.lod.c_str(), fragment);
858                         replaceToken("<LOD_DEF>", s.lodDef.c_str(), fragment);
859                         replaceToken("<COORD_TYPE>", s.coordType.c_str(), fragment);
860                         replaceToken("<ICOORD_TYPE>", s.coordType.c_str(), fragment);
861                         replaceToken("<COORD_DEF>", s.coordDef.c_str(), fragment);
862                         replaceToken("<POINT_TYPE>", s.pointType.c_str(), fragment);
863                         replaceToken("<POINT_DEF>", s.pointDef.c_str(), fragment);
864                         replaceToken("<RETURN_TYPE>", s.returnType.c_str(), fragment);
865                         replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), fragment);
866                         replaceToken("<EPSILON>", s.epsilon.c_str(), fragment);
867                         replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), fragment);
868                         replaceToken("<REFZ_DEF>", s.refZDef.c_str(), fragment);
869                         replaceToken("<POINT_COORD>", s.pointCoord.c_str(), fragment);
870                         replaceToken("<COMPONENT_DEF>", s.componentDef.c_str(), fragment);
871                         replaceToken("<CUBE_MAP_COORD_DEF>", s.cubeMapCoordDef.c_str(), fragment);
872                         replaceToken("<OFFSET_ARRAY_DEF>", s.offsetArrayDef.c_str(), fragment);
873                         replaceToken("<FORMAT_DEF>", s.formatDef.c_str(), fragment);
874                         replaceToken("<OFFSET_TYPE>", s.offsetType.c_str(), fragment);
875                         replaceToken("<NOFFSET_TYPE>", s.nOffsetType.c_str(), fragment);
876                         replaceToken("<OFFSET_DIM>", s.offsetDim.c_str(), fragment);
877
878                         replaceToken("<TEX_WIDTH>", de::toString(width).c_str(), fragment);
879                         replaceToken("<TEX_HEIGHT>", de::toString(height).c_str(), fragment);
880                         replaceToken("<TEX_DEPTH>", de::toString(depth).c_str(), fragment);
881
882                         ProgramSources sources = makeVtxFragSources(vertex.c_str(), fragment.c_str());
883
884                         // Build and run shader
885                         ShaderProgram program(m_context.getRenderContext(), sources);
886                         if (program.isOk())
887                         {
888                                 gl.useProgram(program.getProgram());
889                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
890
891                                 // Pass input sampler/image to shader
892                                 gl.activeTexture(GL_TEXTURE0);
893                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
894                                 gl.uniform1i(1, 0 /* sampler_unit */);
895                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
896
897                                 gl.bindTexture(target, texture);
898                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
899
900                                 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
901                                 draw(target, z, program);
902
903                                 Texture::Bind(gl, verifyTexture, verifyTarget);
904                                 Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data);
905                                 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
906
907                                 //Verify only committed region
908                                 for (GLint y = 0; y < height; ++y)
909                                         for (GLint x = 0; x < width; ++x)
910                                         {
911                                                 GLubyte* dataRegion     = exp_data + x + y * width;
912                                                 GLubyte* outDataRegion = out_data + x + y * width;
913                                                 if (dataRegion[0] != outDataRegion[0])
914                                                         result = false;
915                                         }
916                         }
917                         else
918                         {
919                                 mLog << "Shader compilation failed (lookup color) for target: " << target << ", format: " << format
920                                          << ", vertexInfoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog
921                                          << ", fragmentInfoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog
922                                          << ", programInfoLog: " << program.getProgramInfo().infoLog
923                                          << ", fragmentSource: " << fragment.c_str() << " - ";
924
925                                 result = false;
926                         }
927                 }
928         }
929
930         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
931         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
932
933         Texture::Delete(gl, verifyTexture);
934
935         return result;
936 }
937
938 /** Preparing texture. Function overridden to increase textures size.
939  *
940  * @param gl           GL API functions
941  * @param target       Target for which texture is binded
942  * @param format       Texture internal format
943  * @param texture      Texture object
944  *
945  * @return Returns true if no error occurred, otherwise throws an exception.
946  */
947 bool SparseTextureClampLookupColorTestCase::prepareTexture(const Functions& gl, GLint target, GLint format,
948                                                                                                                    GLuint& texture)
949 {
950         Texture::Generate(gl, texture);
951         Texture::Bind(gl, texture, target);
952
953         mState.minDepth = SparseTextureUtils::getTargetDepth(target);
954         SparseTextureUtils::getTexturePageSizes(gl, target, format, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ);
955
956         //The <width> and <height> has to be equal for cube map textures
957         if (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY)
958         {
959                 if (mState.pageSizeX > mState.pageSizeY)
960                         mState.pageSizeY = mState.pageSizeX;
961                 else if (mState.pageSizeX < mState.pageSizeY)
962                         mState.pageSizeX = mState.pageSizeY;
963         }
964
965         mState.width  = 4 * mState.pageSizeX;
966         mState.height = 4 * mState.pageSizeY;
967         mState.depth  = 4 * mState.pageSizeZ * mState.minDepth;
968
969         mState.format = glu::mapGLInternalFormat(format);
970
971         return true;
972 }
973
974 /** Commit texture page using texPageCommitment function. Function overridden to commit whole texture region.
975  *
976  * @param gl           GL API functions
977  * @param target       Target for which texture is binded
978  * @param format       Texture internal format
979  * @param texture      Texture object
980  * @param level        Texture mipmap level
981  *
982  * @return Returns true if commitment is done properly, false if commitment is not allowed or throws exception if error occurred.
983  */
984 bool SparseTextureClampLookupColorTestCase::commitTexturePage(const Functions& gl, GLint target, GLint format,
985                                                                                                                           GLuint& texture, GLint level)
986 {
987         mLog << "Commit Region [level: " << level << "] - ";
988
989         if (level > mState.levels - 1)
990                 TCU_FAIL("Invalid level");
991
992         // Avoid not allowed commitments
993         if (!isInPageSizesRange(target, level) || !isPageSizesMultiplication(target, level))
994         {
995                 mLog << "Skip commitment [level: " << level << "] - ";
996                 return false;
997         }
998
999         GLint width;
1000         GLint height;
1001         GLint depth;
1002         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1003
1004         if (target == GL_TEXTURE_CUBE_MAP)
1005                 depth = 6 * depth;
1006
1007         Texture::Bind(gl, texture, target);
1008         texPageCommitment(gl, target, format, texture, level, 0, 0, 0, width, height, depth, GL_TRUE);
1009         GLU_EXPECT_NO_ERROR(gl.getError(), "texPageCommitment");
1010
1011         return true;
1012 }
1013
1014 /** Check if current texture size for level is greater or equal page size in a corresponding direction
1015  *
1016  * @param target  Target for which texture is binded
1017  * @param level   Texture mipmap level
1018  *
1019  * @return Returns true if the texture size condition is fulfilled, false otherwise.
1020  */
1021 bool SparseTextureClampLookupColorTestCase::isInPageSizesRange(GLint target, GLint level)
1022 {
1023         GLint width;
1024         GLint height;
1025         GLint depth;
1026         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1027
1028         if (target == GL_TEXTURE_CUBE_MAP)
1029                 depth = 6 * depth;
1030
1031         if (width >= mState.pageSizeX && height >= mState.pageSizeY && (mState.minDepth == 0 || depth >= mState.pageSizeZ))
1032         {
1033                 return true;
1034         }
1035
1036         return false;
1037 }
1038
1039 /** Check if current texture size for level is page size multiplication in a corresponding direction
1040  *
1041  * @param target  Target for which texture is binded
1042  * @param level   Texture mipmap level
1043  *
1044  * @return Returns true if the texture size condition is fulfilled, false otherwise.
1045  */
1046 bool SparseTextureClampLookupColorTestCase::isPageSizesMultiplication(GLint target, GLint level)
1047 {
1048         GLint width;
1049         GLint height;
1050         GLint depth;
1051         SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1052
1053         if (target == GL_TEXTURE_CUBE_MAP)
1054                 depth = 6 * depth;
1055
1056         if ((width % mState.pageSizeX) == 0 && (height % mState.pageSizeY) == 0 && (depth % mState.pageSizeZ) == 0)
1057         {
1058                 return true;
1059         }
1060
1061         return false;
1062 }
1063
1064 /** Constructor.
1065  *
1066  * @param funcName Tested function name.
1067  *
1068  * @return Returns shader source code part that uses lookup function to fetch texel from texture.
1069  */
1070 std::string SparseTextureClampLookupColorTestCase::generateFunctionDef(std::string funcName)
1071 {
1072         if (funcName.find("sparse", 0) != std::string::npos)
1073         {
1074                 return std::string("    <FUNCTION>(uni_in,\n"
1075                                                    "               <POINT_COORD><SAMPLE_DEF><ARGUMENTS>,\n"
1076                                                    "               retValue<COMPONENT_DEF>);\n");
1077         }
1078         else
1079         {
1080                 return std::string("    retValue<COMPONENT_DEF> = <FUNCTION>(uni_in,\n"
1081                                                    "                                         <POINT_COORD><SAMPLE_DEF><ARGUMENTS>);\n");
1082         }
1083 }
1084
1085 /** Constructor.
1086  *
1087  * @param returnType Expected result variable type.
1088  *
1089  * @return Returns shader source token that represent expected lookup result value.
1090  */
1091 std::string SparseTextureClampLookupColorTestCase::generateExpectedResult(std::string returnType, GLint level)
1092 {
1093         if (returnType == "vec4")
1094                 return std::string("(") + de::toString(0.5f + (float)level / 10) + std::string(", 0, 0, 1)");
1095         else
1096                 return std::string("(") + de::toString(level * 10) + std::string(", 0, 0, 1)");
1097 }
1098
1099 /** Constructor.
1100  *
1101  *  @param context Rendering context.
1102  */
1103 SparseTextureClampTests::SparseTextureClampTests(deqp::Context& context)
1104         : TestCaseGroup(context, "sparse_texture_clamp_tests",
1105                                         "Verify conformance of CTS_ARB_sparse_texture_clamp implementation")
1106 {
1107 }
1108
1109 /** Initializes the test group contents. */
1110 void SparseTextureClampTests::init()
1111 {
1112         addChild(new ShaderExtensionTestCase(m_context, "GL_ARB_sparse_texture_clamp"));
1113         addChild(new SparseTextureClampLookupResidencyTestCase(m_context));
1114         addChild(new SparseTextureClampLookupColorTestCase(m_context));
1115 }
1116
1117 } /* gl4cts namespace */