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