1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 */ /*-------------------------------------------------------------------*/
26 * \file gl4cSparseTextureClampTests.cpp
27 * \brief Conformance tests for the GL_ARB_sparse_texture2 functionality.
28 */ /*-------------------------------------------------------------------*/
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"
51 const char* stc_compute_textureFill = "#version 430 core\n"
53 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
55 "layout (location = 1) writeonly uniform highp <INPUT_TYPE> uni_image;\n"
59 " <POINT_TYPE> point = <POINT_TYPE>(<POINT_DEF>);\n"
61 " <RETURN_TYPE> color = <RETURN_TYPE><RESULT_EXPECTED>;\n"
62 " imageStore(uni_image, point<SAMPLE_DEF>, color);\n"
65 const char* stc_vertex_common = "#version 450\n"
68 "in <COORD_TYPE> inCoord;\n"
69 "out <COORD_TYPE> texCoord;\n"
73 " texCoord = inCoord;\n"
74 " gl_Position = vec4(vertex, 1);\n"
77 const char* stc_fragment_lookupResidency = "#version 450 core\n"
79 "#extension GL_ARB_sparse_texture2 : enable\n"
80 "#extension GL_ARB_sparse_texture_clamp : enable\n"
82 "in <COORD_TYPE> texCoord;\n"
83 "out vec4 fragColor;\n"
85 "layout (location = 1<FORMAT_DEF>) uniform <INPUT_TYPE> uni_in;\n"
86 "layout (location = 2) uniform int widthCommitted;\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"
96 " retValue = <RETURN_TYPE>(0);\n"
97 " expValue = <RETURN_TYPE><RESULT_EXPECTED>;\n"
98 " epsilon = <RETURN_TYPE>(<EPSILON>);\n"
100 "<CUBE_MAP_COORD_DEF>\n"
101 "<OFFSET_ARRAY_DEF>\n"
103 " ivec2 corner1 = ivec2(1, 1);\n"
104 " ivec2 corner2 = ivec2(texSize.x - 1, texSize.y - 1);\n"
106 " int code = <FUNCTION>(uni_in,\n"
107 " <POINT_COORD><SAMPLE_DEF><ARGUMENTS>,\n"
108 " retValue<COMPONENT_DEF>);\n"
110 " fragColor = vec4(1);\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"
116 " if (!sparseTexelsResidentARB(code) ||\n"
117 " any(greaterThan(retValue, expValue + epsilon)) ||\n"
118 " any(lessThan(retValue, expValue - epsilon)))\n"
120 " fragColor = vec4(0);\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"
128 " if (sparseTexelsResidentARB(code))\n"
130 " fragColor = vec4(0);\n"
135 const char* stc_fragment_lookupColor = "#version 450 core\n"
137 "#extension GL_ARB_sparse_texture2 : enable\n"
138 "#extension GL_ARB_sparse_texture_clamp : enable\n"
140 "in <COORD_TYPE> texCoord;\n"
141 "out vec4 fragColor;\n"
143 "layout (location = 1<FORMAT_DEF>) uniform <INPUT_TYPE> uni_in;\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"
153 " retValue = <RETURN_TYPE>(0);\n"
154 " expValue = <RETURN_TYPE><RESULT_EXPECTED>;\n"
155 " epsilon = <RETURN_TYPE>(<EPSILON>);\n"
157 "<CUBE_MAP_COORD_DEF>\n"
158 "<OFFSET_ARRAY_DEF>\n"
162 " fragColor = vec4(1);\n"
164 " if (any(greaterThan(retValue, expValue + epsilon)) ||\n"
165 " any(lessThan(retValue, expValue - epsilon)))\n"
167 " fragColor = vec4(0);\n"
173 * @param context Rendering context
175 SparseTextureClampLookupResidencyTestCase::SparseTextureClampLookupResidencyTestCase(deqp::Context& context)
176 : SparseTexture2LookupTestCase(
177 context, "SparseTextureClampLookupResidency",
178 "Verifies if sparse texture clamp lookup functions generates access residency information")
180 /* Left blank intentionally */
185 * @param context Rendering context
187 SparseTextureClampLookupResidencyTestCase::SparseTextureClampLookupResidencyTestCase(deqp::Context& context,
189 const char* description)
190 : SparseTexture2LookupTestCase(context, name, description)
192 /* Left blank intentionally */
195 /** Stub init method */
196 void SparseTextureClampLookupResidencyTestCase::init()
198 SparseTextureCommitmentTestCase::init();
199 mSupportedInternalFormats.push_back(GL_DEPTH_COMPONENT16);
202 f = FunctionToken("sparseTextureClampARB", ", <LOD>");
203 f.allowedTargets.insert(GL_TEXTURE_2D);
204 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
205 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
206 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
207 f.allowedTargets.insert(GL_TEXTURE_3D);
208 mFunctions.push_back(f);
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);
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);
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);
234 /** Executes test iteration.
236 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
238 tcu::TestNode::IterateResult SparseTextureClampLookupResidencyTestCase::iterate()
240 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture_clamp"))
242 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
246 return SparseTexture2LookupTestCase::iterate();
249 /** Check if specific lookup function is allowed for specific target and format
251 * @param target Target for which texture is binded
252 * @param format Texture internal format
253 * @param funcToken Texture lookup function structure
255 * @return Returns true if target/format combination is allowed, false otherwise.
257 bool SparseTextureClampLookupResidencyTestCase::funcAllowed(GLint target, GLint format, FunctionToken& funcToken)
259 if (funcToken.allowedTargets.find(target) == funcToken.allowedTargets.end())
262 if (format == GL_DEPTH_COMPONENT16)
264 if (target == GL_TEXTURE_CUBE_MAP_ARRAY && funcToken.name == "sparseTextureGradClampARB")
271 /** Verify if data stored in texture is as expected
273 * @param gl GL API functions
274 * @param target Target for which texture is binded
275 * @param format Texture internal format
276 * @param texture Texture object
277 * @param level Texture mipmap level
278 * @param funcToken Lookup function tokenize structure
280 * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
282 bool SparseTextureClampLookupResidencyTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format,
283 GLuint& texture, GLint level,
284 FunctionToken& funcToken)
286 mLog << "Verify Lookup Residency Texture Data [function: " << funcToken.name << ", level: " << level << "] - ";
288 if (level > mState.levels - 1)
289 TCU_FAIL("Invalid level");
294 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
296 //Committed region is limited to 1/2 of width
297 GLint widthCommitted = width / 2;
299 if (widthCommitted == 0 || height == 0 || depth < mState.minDepth)
304 if (target == GL_TEXTURE_CUBE_MAP)
307 GLint texSize = width * height;
309 std::vector<GLubyte> vecExpData;
310 std::vector<GLubyte> vecOutData;
311 vecExpData.resize(texSize);
312 vecOutData.resize(texSize);
313 GLubyte* exp_data = vecExpData.data();
314 GLubyte* out_data = vecOutData.data();
316 // Expected data is 255 because
317 deMemset(exp_data, 255, texSize);
319 // Create verifying texture
320 GLint verifyTarget = GL_TEXTURE_2D;
321 GLuint verifyTexture;
322 Texture::Generate(gl, verifyTexture);
323 Texture::Bind(gl, verifyTexture, verifyTarget);
324 Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth);
325 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage");
328 gl.genFramebuffers(1, &fbo);
329 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers");
330 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
331 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
332 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, verifyTarget, verifyTexture, 0);
333 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D");
335 gl.viewport(0, 0, width, height);
337 for (GLint z = 0; z < depth; ++z)
339 for (int sample = 0; sample < mState.samples; ++sample)
341 deMemset(out_data, 0, texSize);
343 Texture::Bind(gl, verifyTexture, verifyTarget);
344 Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,
346 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage");
348 std::string vertex = stc_vertex_common;
349 std::string fragment = stc_fragment_lookupResidency;
351 // Make token copy to work on
352 FunctionToken f = funcToken;
354 // Adjust shader source to texture format
355 TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f);
357 replaceToken("<COORD_TYPE>", s.coordType.c_str(), vertex);
359 replaceToken("<FUNCTION>", f.name.c_str(), fragment);
360 replaceToken("<ARGUMENTS>", f.arguments.c_str(), fragment);
362 replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), fragment);
363 replaceToken("<INPUT_TYPE>", s.inputType.c_str(), fragment);
364 replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), fragment);
365 replaceToken("<LOD>", s.lod.c_str(), fragment);
366 replaceToken("<LOD_DEF>", s.lodDef.c_str(), fragment);
367 replaceToken("<COORD_TYPE>", s.coordType.c_str(), fragment);
368 replaceToken("<ICOORD_TYPE>", s.iCoordType.c_str(), fragment);
369 replaceToken("<COORD_DEF>", s.coordDef.c_str(), fragment);
370 replaceToken("<POINT_TYPE>", s.pointType.c_str(), fragment);
371 replaceToken("<POINT_DEF>", s.pointDef.c_str(), fragment);
372 replaceToken("<RETURN_TYPE>", s.returnType.c_str(), fragment);
373 replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), fragment);
374 replaceToken("<EPSILON>", s.epsilon.c_str(), fragment);
375 replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), fragment);
376 replaceToken("<REFZ_DEF>", s.refZDef.c_str(), fragment);
377 replaceToken("<POINT_COORD>", s.pointCoord.c_str(), fragment);
378 replaceToken("<COMPONENT_DEF>", s.componentDef.c_str(), fragment);
379 replaceToken("<CUBE_MAP_COORD_DEF>", s.cubeMapCoordDef.c_str(), fragment);
380 replaceToken("<OFFSET_ARRAY_DEF>", s.offsetArrayDef.c_str(), fragment);
381 replaceToken("<FORMAT_DEF>", s.formatDef.c_str(), fragment);
382 replaceToken("<OFFSET_TYPE>", s.offsetType.c_str(), fragment);
383 replaceToken("<NOFFSET_TYPE>", s.nOffsetType.c_str(), fragment);
384 replaceToken("<OFFSET_DIM>", s.offsetDim.c_str(), fragment);
386 replaceToken("<TEX_WIDTH>", de::toString(width).c_str(), fragment);
387 replaceToken("<TEX_HEIGHT>", de::toString(height).c_str(), fragment);
388 replaceToken("<TEX_DEPTH>", de::toString(depth).c_str(), fragment);
390 ProgramSources sources = makeVtxFragSources(vertex.c_str(), fragment.c_str());
392 // Build and run shader
393 ShaderProgram program(m_context.getRenderContext(), sources);
396 gl.useProgram(program.getProgram());
397 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
399 // Pass input sampler/image to shader
400 gl.activeTexture(GL_TEXTURE0);
401 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
402 gl.uniform1i(1, 0 /* sampler_unit */);
403 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
405 // Pass committed region width to shader
406 gl.uniform1i(2, widthCommitted /* committed region width */);
407 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
409 gl.bindTexture(target, texture);
410 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
412 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
413 draw(target, z, program);
415 Texture::Bind(gl, verifyTexture, verifyTarget);
416 Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data);
417 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
419 //Verify only committed region
420 for (GLint y = 0; y < height; ++y)
421 for (GLint x = 0; x < width; ++x)
423 GLubyte* dataRegion = exp_data + x + y * width;
424 GLubyte* outDataRegion = out_data + x + y * width;
425 if (dataRegion[0] != outDataRegion[0])
431 mLog << "Shader compilation failed (lookup residency) for target: " << target << ", format: " << format
432 << ", vertexInfoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog
433 << ", fragmentInfoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog
434 << ", programInfoLog: " << program.getProgramInfo().infoLog
435 << ", fragmentSource: " << fragment.c_str() << " - ";
442 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
443 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
445 Texture::Delete(gl, verifyTexture);
450 void SparseTextureClampLookupResidencyTestCase::draw(GLint target, GLint layer, const ShaderProgram& program)
452 const GLfloat texCoord1D[] = { 0.0f, 1.0f, 0.0f, 1.0f };
454 const GLfloat texCoord2D[] = {
455 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
458 const GLfloat texCoord3D[] = { 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f };
460 const GLfloat texCoordCubeMap[6][12] = {
461 { 0.0f, 0.0f, 0.00f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f },
462 { 0.0f, 0.0f, 0.17f, 1.0f, 0.0f, 0.17f, 0.0f, 1.0f, 0.17f, 1.0f, 1.0f, 0.17f },
463 { 0.0f, 0.0f, 0.33f, 1.0f, 0.0f, 0.33f, 0.0f, 1.0f, 0.33f, 1.0f, 1.0f, 0.33f },
464 { 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f },
465 { 0.0f, 0.0f, 0.67f, 1.0f, 0.0f, 0.67f, 0.0f, 1.0f, 0.67f, 1.0f, 1.0f, 0.67f },
466 { 0.0f, 0.0f, 0.83f, 1.0f, 0.0f, 0.83f, 0.0f, 1.0f, 0.83f, 1.0f, 1.0f, 0.83f }
469 const GLfloat vertices[] = {
470 -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
473 const GLuint indices[] = { 0, 1, 2, 1, 2, 3 };
475 VertexArrayBinding floatCoord;
477 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_1D_ARRAY)
478 floatCoord = glu::va::Float("inCoord", 1, 4, 0, texCoord1D);
479 else if (target == GL_TEXTURE_3D)
480 floatCoord = glu::va::Float("inCoord", 3, 4, 0, texCoord3D);
481 else if (target == GL_TEXTURE_CUBE_MAP)
482 floatCoord = glu::va::Float("inCoord", 3, 4, 0, texCoordCubeMap[layer]);
484 floatCoord = glu::va::Float("inCoord", 2, 4, 0, texCoord2D);
486 glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("vertex", 3, 4, 0, vertices), floatCoord };
488 glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
489 glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(indices), indices));
494 * @param context Rendering context
496 SparseTextureClampLookupColorTestCase::SparseTextureClampLookupColorTestCase(deqp::Context& context)
497 : SparseTextureClampLookupResidencyTestCase(
498 context, "SparseTextureClampLookupColor",
499 "Verifies if sparse and non-sparse texture clamp lookup functions works as expected")
501 /* Left blank intentionally */
504 /** Stub init method */
505 void SparseTextureClampLookupColorTestCase::init()
507 SparseTextureCommitmentTestCase::init();
508 mSupportedTargets.push_back(GL_TEXTURE_1D);
509 mSupportedTargets.push_back(GL_TEXTURE_1D_ARRAY);
510 mSupportedInternalFormats.push_back(GL_DEPTH_COMPONENT16);
513 f = FunctionToken("sparseTextureClampARB", ", <LOD>");
514 f.allowedTargets.insert(GL_TEXTURE_2D);
515 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
516 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
517 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
518 f.allowedTargets.insert(GL_TEXTURE_3D);
519 mFunctions.push_back(f);
521 f = FunctionToken("textureClampARB", ", <LOD>");
522 f.allowedTargets.insert(GL_TEXTURE_1D);
523 f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
524 f.allowedTargets.insert(GL_TEXTURE_2D);
525 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
526 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
527 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
528 f.allowedTargets.insert(GL_TEXTURE_3D);
529 mFunctions.push_back(f);
531 f = FunctionToken("sparseTextureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
532 f.allowedTargets.insert(GL_TEXTURE_2D);
533 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
534 f.allowedTargets.insert(GL_TEXTURE_3D);
535 mFunctions.push_back(f);
537 f = FunctionToken("textureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
538 f.allowedTargets.insert(GL_TEXTURE_1D);
539 f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
540 f.allowedTargets.insert(GL_TEXTURE_2D);
541 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
542 f.allowedTargets.insert(GL_TEXTURE_3D);
543 mFunctions.push_back(f);
545 f = FunctionToken("sparseTextureGradClampARB",
546 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
547 f.allowedTargets.insert(GL_TEXTURE_2D);
548 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
549 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
550 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
551 f.allowedTargets.insert(GL_TEXTURE_3D);
552 mFunctions.push_back(f);
554 f = FunctionToken("textureGradClampARB", ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
555 f.allowedTargets.insert(GL_TEXTURE_1D);
556 f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
557 f.allowedTargets.insert(GL_TEXTURE_2D);
558 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
559 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
560 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
561 f.allowedTargets.insert(GL_TEXTURE_3D);
562 mFunctions.push_back(f);
565 "sparseTextureGradOffsetClampARB",
566 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
567 f.allowedTargets.insert(GL_TEXTURE_2D);
568 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
569 f.allowedTargets.insert(GL_TEXTURE_3D);
570 mFunctions.push_back(f);
573 "textureGradOffsetClampARB",
574 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
575 f.allowedTargets.insert(GL_TEXTURE_1D);
576 f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
577 f.allowedTargets.insert(GL_TEXTURE_2D);
578 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
579 f.allowedTargets.insert(GL_TEXTURE_3D);
580 mFunctions.push_back(f);
583 /** Executes test iteration.
585 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
587 tcu::TestNode::IterateResult SparseTextureClampLookupColorTestCase::iterate()
589 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture_clamp"))
591 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
595 const Functions& gl = m_context.getRenderContext().getFunctions();
601 for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
604 const GLint& target = *iter;
606 for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
607 formIter != mSupportedInternalFormats.end(); ++formIter)
609 const GLint& format = *formIter;
611 if (!caseAllowed(target, format))
614 for (std::vector<FunctionToken>::const_iterator tokIter = mFunctions.begin(); tokIter != mFunctions.end();
617 // Check if target is allowed for current lookup function
618 FunctionToken funcToken = *tokIter;
619 if (!funcAllowed(target, format, funcToken))
622 bool isSparse = false;
623 if (funcToken.name.find("sparse", 0) != std::string::npos)
627 mLog << "Testing sparse texture lookup color functions for target: " << target << ", format: " << format
631 sparseAllocateTexture(gl, target, format, texture, 3);
633 allocateTexture(gl, target, format, texture, 3);
635 if (format == GL_DEPTH_COMPONENT16)
636 setupDepthMode(gl, target, texture);
640 for (l = 0; l < mState.levels; ++l)
642 if (!isSparse || commitTexturePage(gl, target, format, texture, l))
644 writeDataToTexture(gl, target, format, texture, l);
649 for (l = 0; l <= maxLevels; ++l)
651 result = result && verifyLookupTextureData(gl, target, format, texture, l, funcToken);
657 Texture::Delete(gl, texture);
661 m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
662 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
669 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
673 /** Writing data to generated texture using compute shader
675 * @param gl GL API functions
676 * @param target Target for which texture is binded
677 * @param format Texture internal format
678 * @param texture Texture object
680 * @return Returns true if no error occurred, otherwise throws an exception.
682 bool SparseTextureClampLookupColorTestCase::writeDataToTexture(const Functions& gl, GLint target, GLint format,
683 GLuint& texture, GLint level)
685 mLog << "Fill Texture with shader [level: " << level << "] - ";
687 if (level > mState.levels - 1)
688 TCU_FAIL("Invalid level");
693 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
695 if (width > 0 && height > 0 && depth >= mState.minDepth)
697 if (target == GL_TEXTURE_CUBE_MAP)
700 GLint texSize = width * height * depth * mState.format.getPixelSize();
702 std::vector<GLubyte> vecData;
703 vecData.resize(texSize);
704 GLubyte* data = vecData.data();
706 deMemset(data, 255, texSize);
708 for (GLint sample = 0; sample < mState.samples; ++sample)
710 std::string shader = stc_compute_textureFill;
712 // Adjust shader source to texture format
713 TokenStrings s = createShaderTokens(target, format, sample);
715 // Change expected result as it has to be adjusted to different levels
716 s.resultExpected = generateExpectedResult(s.returnType, level);
718 replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader);
719 replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader);
720 replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader);
721 replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader);
722 replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), shader);
723 replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader);
725 ProgramSources sources;
726 sources << ComputeSource(shader);
728 GLint convFormat = format;
729 if (format == GL_DEPTH_COMPONENT16)
732 // Build and run shader
733 ShaderProgram program(m_context.getRenderContext(), sources);
736 gl.useProgram(program.getProgram());
737 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
738 gl.bindImageTexture(0 /* unit */, texture, level /* level */, GL_FALSE /* layered */, 0 /* layer */,
739 GL_WRITE_ONLY, convFormat);
740 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture");
741 gl.uniform1i(1, 0 /* image_unit */);
742 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
743 gl.dispatchCompute(width, height, depth);
744 GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute");
745 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
746 GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier");
750 mLog << "Compute shader compilation failed (writing) for target: " << target << ", format: " << format
751 << ", sample: " << sample << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog
752 << ", shaderSource: " << shader.c_str() << " - ";
760 /** Verify if data stored in texture is as expected
762 * @param gl GL API functions
763 * @param target Target for which texture is binded
764 * @param format Texture internal format
765 * @param texture Texture object
766 * @param level Texture mipmap level
767 * @param funcToken Lookup function tokenize structure
769 * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
771 bool SparseTextureClampLookupColorTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format,
772 GLuint& texture, GLint level,
773 FunctionToken& funcToken)
775 mLog << "Verify Lookup Color Texture Data [function: " << funcToken.name << ", level: " << level << "] - ";
777 if (level > mState.levels - 1)
778 TCU_FAIL("Invalid level");
783 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
785 if (width == 0 || height == 0 || depth < mState.minDepth)
790 if (target == GL_TEXTURE_CUBE_MAP)
793 GLint texSize = width * height;
795 std::vector<GLubyte> vecExpData;
796 std::vector<GLubyte> vecOutData;
797 vecExpData.resize(texSize);
798 vecOutData.resize(texSize);
799 GLubyte* exp_data = vecExpData.data();
800 GLubyte* out_data = vecOutData.data();
802 // Expected data is 255 because
803 deMemset(exp_data, 255, texSize);
805 // Create verifying texture
806 GLint verifyTarget = GL_TEXTURE_2D;
807 GLuint verifyTexture;
808 Texture::Generate(gl, verifyTexture);
809 Texture::Bind(gl, verifyTexture, verifyTarget);
810 Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth);
811 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage");
814 gl.genFramebuffers(1, &fbo);
815 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers");
816 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
817 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
818 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, verifyTarget, verifyTexture, 0);
819 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D");
821 gl.viewport(0, 0, width, height);
823 for (GLint z = 0; z < depth; ++z)
825 for (int sample = 0; sample < mState.samples; ++sample)
827 deMemset(out_data, 0, texSize);
829 Texture::Bind(gl, verifyTexture, verifyTarget);
830 Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,
832 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage");
834 std::string vertex = stc_vertex_common;
835 std::string fragment = stc_fragment_lookupColor;
837 // Make token copy to work on
838 FunctionToken f = funcToken;
840 std::string functionDef = generateFunctionDef(f.name);
842 // Adjust shader source to texture format
843 TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f);
845 // Change expected result as it has to be adjusted to different levels
846 s.resultExpected = generateExpectedResult(s.returnType, level);
848 replaceToken("<COORD_TYPE>", s.coordType.c_str(), vertex);
850 replaceToken("<FUNCTION_DEF>", functionDef.c_str(), fragment);
851 replaceToken("<FUNCTION>", f.name.c_str(), fragment);
852 replaceToken("<ARGUMENTS>", f.arguments.c_str(), fragment);
854 replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), fragment);
855 replaceToken("<INPUT_TYPE>", s.inputType.c_str(), fragment);
856 replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), fragment);
857 replaceToken("<LOD>", s.lod.c_str(), fragment);
858 replaceToken("<LOD_DEF>", s.lodDef.c_str(), fragment);
859 replaceToken("<COORD_TYPE>", s.coordType.c_str(), fragment);
860 replaceToken("<ICOORD_TYPE>", s.coordType.c_str(), fragment);
861 replaceToken("<COORD_DEF>", s.coordDef.c_str(), fragment);
862 replaceToken("<POINT_TYPE>", s.pointType.c_str(), fragment);
863 replaceToken("<POINT_DEF>", s.pointDef.c_str(), fragment);
864 replaceToken("<RETURN_TYPE>", s.returnType.c_str(), fragment);
865 replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), fragment);
866 replaceToken("<EPSILON>", s.epsilon.c_str(), fragment);
867 replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), fragment);
868 replaceToken("<REFZ_DEF>", s.refZDef.c_str(), fragment);
869 replaceToken("<POINT_COORD>", s.pointCoord.c_str(), fragment);
870 replaceToken("<COMPONENT_DEF>", s.componentDef.c_str(), fragment);
871 replaceToken("<CUBE_MAP_COORD_DEF>", s.cubeMapCoordDef.c_str(), fragment);
872 replaceToken("<OFFSET_ARRAY_DEF>", s.offsetArrayDef.c_str(), fragment);
873 replaceToken("<FORMAT_DEF>", s.formatDef.c_str(), fragment);
874 replaceToken("<OFFSET_TYPE>", s.offsetType.c_str(), fragment);
875 replaceToken("<NOFFSET_TYPE>", s.nOffsetType.c_str(), fragment);
876 replaceToken("<OFFSET_DIM>", s.offsetDim.c_str(), fragment);
878 replaceToken("<TEX_WIDTH>", de::toString(width).c_str(), fragment);
879 replaceToken("<TEX_HEIGHT>", de::toString(height).c_str(), fragment);
880 replaceToken("<TEX_DEPTH>", de::toString(depth).c_str(), fragment);
882 ProgramSources sources = makeVtxFragSources(vertex.c_str(), fragment.c_str());
884 // Build and run shader
885 ShaderProgram program(m_context.getRenderContext(), sources);
888 gl.useProgram(program.getProgram());
889 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
891 // Pass input sampler/image to shader
892 gl.activeTexture(GL_TEXTURE0);
893 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
894 gl.uniform1i(1, 0 /* sampler_unit */);
895 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
897 gl.bindTexture(target, texture);
898 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
900 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
901 draw(target, z, program);
903 Texture::Bind(gl, verifyTexture, verifyTarget);
904 Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data);
905 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
907 //Verify only committed region
908 for (GLint y = 0; y < height; ++y)
909 for (GLint x = 0; x < width; ++x)
911 GLubyte* dataRegion = exp_data + x + y * width;
912 GLubyte* outDataRegion = out_data + x + y * width;
913 if (dataRegion[0] != outDataRegion[0])
919 mLog << "Shader compilation failed (lookup color) for target: " << target << ", format: " << format
920 << ", vertexInfoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog
921 << ", fragmentInfoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog
922 << ", programInfoLog: " << program.getProgramInfo().infoLog
923 << ", fragmentSource: " << fragment.c_str() << " - ";
930 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
931 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
933 Texture::Delete(gl, verifyTexture);
938 /** Preparing texture. Function overridden to increase textures size.
940 * @param gl GL API functions
941 * @param target Target for which texture is binded
942 * @param format Texture internal format
943 * @param texture Texture object
945 * @return Returns true if no error occurred, otherwise throws an exception.
947 bool SparseTextureClampLookupColorTestCase::prepareTexture(const Functions& gl, GLint target, GLint format,
950 Texture::Generate(gl, texture);
951 Texture::Bind(gl, texture, target);
953 mState.minDepth = SparseTextureUtils::getTargetDepth(target);
954 SparseTextureUtils::getTexturePageSizes(gl, target, format, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ);
956 //The <width> and <height> has to be equal for cube map textures
957 if (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY)
959 if (mState.pageSizeX > mState.pageSizeY)
960 mState.pageSizeY = mState.pageSizeX;
961 else if (mState.pageSizeX < mState.pageSizeY)
962 mState.pageSizeX = mState.pageSizeY;
965 mState.width = 4 * mState.pageSizeX;
966 mState.height = 4 * mState.pageSizeY;
967 mState.depth = 4 * mState.pageSizeZ * mState.minDepth;
969 mState.format = glu::mapGLInternalFormat(format);
974 /** Commit texture page using texPageCommitment function. Function overridden to commit whole texture region.
976 * @param gl GL API functions
977 * @param target Target for which texture is binded
978 * @param format Texture internal format
979 * @param texture Texture object
980 * @param level Texture mipmap level
982 * @return Returns true if commitment is done properly, false if commitment is not allowed or throws exception if error occurred.
984 bool SparseTextureClampLookupColorTestCase::commitTexturePage(const Functions& gl, GLint target, GLint format,
985 GLuint& texture, GLint level)
987 mLog << "Commit Region [level: " << level << "] - ";
989 if (level > mState.levels - 1)
990 TCU_FAIL("Invalid level");
992 // Avoid not allowed commitments
993 if (!isInPageSizesRange(target, level) || !isPageSizesMultiplication(target, level))
995 mLog << "Skip commitment [level: " << level << "] - ";
1002 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1004 if (target == GL_TEXTURE_CUBE_MAP)
1007 Texture::Bind(gl, texture, target);
1008 texPageCommitment(gl, target, format, texture, level, 0, 0, 0, width, height, depth, GL_TRUE);
1009 GLU_EXPECT_NO_ERROR(gl.getError(), "texPageCommitment");
1014 /** Check if current texture size for level is greater or equal page size in a corresponding direction
1016 * @param target Target for which texture is binded
1017 * @param level Texture mipmap level
1019 * @return Returns true if the texture size condition is fulfilled, false otherwise.
1021 bool SparseTextureClampLookupColorTestCase::isInPageSizesRange(GLint target, GLint level)
1026 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1028 if (target == GL_TEXTURE_CUBE_MAP)
1031 if (width >= mState.pageSizeX && height >= mState.pageSizeY && (mState.minDepth == 0 || depth >= mState.pageSizeZ))
1039 /** Check if current texture size for level is page size multiplication in a corresponding direction
1041 * @param target Target for which texture is binded
1042 * @param level Texture mipmap level
1044 * @return Returns true if the texture size condition is fulfilled, false otherwise.
1046 bool SparseTextureClampLookupColorTestCase::isPageSizesMultiplication(GLint target, GLint level)
1051 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1053 if (target == GL_TEXTURE_CUBE_MAP)
1056 if ((width % mState.pageSizeX) == 0 && (height % mState.pageSizeY) == 0 && (depth % mState.pageSizeZ) == 0)
1066 * @param funcName Tested function name.
1068 * @return Returns shader source code part that uses lookup function to fetch texel from texture.
1070 std::string SparseTextureClampLookupColorTestCase::generateFunctionDef(std::string funcName)
1072 if (funcName.find("sparse", 0) != std::string::npos)
1074 return std::string(" <FUNCTION>(uni_in,\n"
1075 " <POINT_COORD><SAMPLE_DEF><ARGUMENTS>,\n"
1076 " retValue<COMPONENT_DEF>);\n");
1080 return std::string(" retValue<COMPONENT_DEF> = <FUNCTION>(uni_in,\n"
1081 " <POINT_COORD><SAMPLE_DEF><ARGUMENTS>);\n");
1087 * @param returnType Expected result variable type.
1089 * @return Returns shader source token that represent expected lookup result value.
1091 std::string SparseTextureClampLookupColorTestCase::generateExpectedResult(std::string returnType, GLint level)
1093 if (returnType == "vec4")
1094 return std::string("(") + de::toString(0.5f + (float)level / 10) + std::string(", 0, 0, 1)");
1096 return std::string("(") + de::toString(level * 10) + std::string(", 0, 0, 1)");
1101 * @param context Rendering context.
1103 SparseTextureClampTests::SparseTextureClampTests(deqp::Context& context)
1104 : TestCaseGroup(context, "sparse_texture_clamp_tests",
1105 "Verify conformance of CTS_ARB_sparse_texture_clamp implementation")
1109 /** Initializes the test group contents. */
1110 void SparseTextureClampTests::init()
1112 addChild(new ShaderExtensionTestCase(m_context, "GL_ARB_sparse_texture_clamp"));
1113 addChild(new SparseTextureClampLookupResidencyTestCase(m_context));
1114 addChild(new SparseTextureClampLookupColorTestCase(m_context));
1117 } /* gl4cts namespace */