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