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