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", "<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);
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 &&
265 (funcToken.name == "sparseTextureGradClampARB" || funcToken.name == "textureGradClampARB"))
272 /** Verify if data stored in texture is as expected
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
281 * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
283 bool SparseTextureClampLookupResidencyTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format,
284 GLuint& texture, GLint level,
285 FunctionToken& funcToken)
287 mLog << "Verify Lookup Residency Texture Data [function: " << funcToken.name << ", level: " << level << "] - ";
289 if (level > mState.levels - 1)
290 TCU_FAIL("Invalid level");
295 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
297 //Committed region is limited to 1/2 of width
298 GLint widthCommitted = width / 2;
300 if (widthCommitted == 0 || height == 0 || depth < mState.minDepth)
305 if (target == GL_TEXTURE_CUBE_MAP)
308 GLint texSize = width * height;
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();
317 // Expected data is 255 because
318 deMemset(exp_data, 255, texSize);
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");
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");
336 gl.viewport(0, 0, width, height);
338 for (GLint z = 0; z < depth; ++z)
340 for (int sample = 0; sample < mState.samples; ++sample)
342 deMemset(out_data, 0, texSize);
344 Texture::Bind(gl, verifyTexture, verifyTarget);
345 Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,
347 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage");
349 std::string vertex = stc_vertex_common;
350 std::string fragment = stc_fragment_lookupResidency;
352 // Make token copy to work on
353 FunctionToken f = funcToken;
355 // Adjust shader source to texture format
356 TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f);
358 replaceToken("<COORD_TYPE>", s.coordType.c_str(), vertex);
360 replaceToken("<FUNCTION>", f.name.c_str(), fragment);
361 replaceToken("<ARGUMENTS>", f.arguments.c_str(), fragment);
363 replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), fragment);
364 replaceToken("<INPUT_TYPE>", s.inputType.c_str(), fragment);
365 replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), fragment);
366 replaceToken("<LOD>", s.lod.c_str(), fragment);
367 replaceToken("<LOD_DEF>", s.lodDef.c_str(), fragment);
368 replaceToken("<COORD_TYPE>", s.coordType.c_str(), fragment);
369 replaceToken("<ICOORD_TYPE>", s.iCoordType.c_str(), fragment);
370 replaceToken("<COORD_DEF>", s.coordDef.c_str(), fragment);
371 replaceToken("<POINT_TYPE>", s.pointType.c_str(), fragment);
372 replaceToken("<POINT_DEF>", s.pointDef.c_str(), fragment);
373 replaceToken("<RETURN_TYPE>", s.returnType.c_str(), fragment);
374 replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), fragment);
375 replaceToken("<EPSILON>", s.epsilon.c_str(), fragment);
376 replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), fragment);
377 replaceToken("<REFZ_DEF>", s.refZDef.c_str(), fragment);
378 replaceToken("<CUBE_REFZ_DEF>", s.cubeMapArrayRefZDef.c_str(), fragment);
379 replaceToken("<POINT_COORD>", s.pointCoord.c_str(), fragment);
380 replaceToken("<COMPONENT_DEF>", s.componentDef.c_str(), fragment);
381 replaceToken("<CUBE_MAP_COORD_DEF>", s.cubeMapCoordDef.c_str(), fragment);
382 replaceToken("<OFFSET_ARRAY_DEF>", s.offsetArrayDef.c_str(), fragment);
383 replaceToken("<FORMAT_DEF>", s.formatDef.c_str(), fragment);
384 replaceToken("<OFFSET_TYPE>", s.offsetType.c_str(), fragment);
385 replaceToken("<NOFFSET_TYPE>", s.nOffsetType.c_str(), fragment);
386 replaceToken("<OFFSET_DIM>", s.offsetDim.c_str(), fragment);
388 replaceToken("<TEX_WIDTH>", de::toString(width).c_str(), fragment);
389 replaceToken("<TEX_HEIGHT>", de::toString(height).c_str(), fragment);
390 replaceToken("<TEX_DEPTH>", de::toString(depth).c_str(), fragment);
392 ProgramSources sources = makeVtxFragSources(vertex.c_str(), fragment.c_str());
394 // Build and run shader
395 ShaderProgram program(m_context.getRenderContext(), sources);
398 gl.useProgram(program.getProgram());
399 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
401 // Pass input sampler/image to shader
402 gl.activeTexture(GL_TEXTURE0);
403 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
404 gl.uniform1i(1, 0 /* sampler_unit */);
405 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
407 // Pass committed region width to shader
408 gl.uniform1i(2, widthCommitted /* committed region width */);
409 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
411 gl.bindTexture(target, texture);
412 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
414 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
415 draw(target, z, program);
417 Texture::Bind(gl, verifyTexture, verifyTarget);
418 Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data);
419 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
421 //Verify only committed region
422 for (GLint y = 0; y < height; ++y)
423 for (GLint x = 0; x < width; ++x)
425 GLubyte* dataRegion = exp_data + x + y * width;
426 GLubyte* outDataRegion = out_data + x + y * width;
427 if (dataRegion[0] != outDataRegion[0])
433 mLog << "Shader compilation failed (lookup residency) for target: " << target << ", format: " << format
434 << ", vertexInfoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog
435 << ", fragmentInfoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog
436 << ", programInfoLog: " << program.getProgramInfo().infoLog
437 << ", fragmentSource: " << fragment.c_str() << " - ";
444 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
445 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
447 Texture::Delete(gl, verifyTexture);
452 void SparseTextureClampLookupResidencyTestCase::draw(GLint target, GLint layer, const ShaderProgram& program)
454 const GLfloat texCoord1D[] = { 0.0f, 1.0f, 0.0f, 1.0f };
456 const GLfloat texCoord2D[] = {
457 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
460 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 };
462 const GLfloat texCoordCubeMap[6][12] = {
463 { 0.0f, 0.0f, 0.00f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f },
464 { 0.0f, 0.0f, 0.17f, 1.0f, 0.0f, 0.17f, 0.0f, 1.0f, 0.17f, 1.0f, 1.0f, 0.17f },
465 { 0.0f, 0.0f, 0.33f, 1.0f, 0.0f, 0.33f, 0.0f, 1.0f, 0.33f, 1.0f, 1.0f, 0.33f },
466 { 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f },
467 { 0.0f, 0.0f, 0.67f, 1.0f, 0.0f, 0.67f, 0.0f, 1.0f, 0.67f, 1.0f, 1.0f, 0.67f },
468 { 0.0f, 0.0f, 0.83f, 1.0f, 0.0f, 0.83f, 0.0f, 1.0f, 0.83f, 1.0f, 1.0f, 0.83f }
471 const GLfloat vertices[] = {
472 -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
475 const GLuint indices[] = { 0, 1, 2, 1, 2, 3 };
477 VertexArrayBinding floatCoord;
479 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_1D_ARRAY)
480 floatCoord = glu::va::Float("inCoord", 1, 4, 0, texCoord1D);
481 else if (target == GL_TEXTURE_3D)
482 floatCoord = glu::va::Float("inCoord", 3, 4, 0, texCoord3D);
483 else if (target == GL_TEXTURE_CUBE_MAP)
484 floatCoord = glu::va::Float("inCoord", 3, 4, 0, texCoordCubeMap[layer]);
485 else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
487 GLfloat layerCoord = GLfloat(layer) / 6.0f + 0.01f;
488 const GLfloat texCoordCubeMapArray[16] = { 0.0f, 0.0f, layerCoord, GLfloat(layer),
489 1.0f, 0.0f, layerCoord, GLfloat(layer),
490 0.0f, 1.0f, layerCoord, GLfloat(layer),
491 1.0f, 1.0f, layerCoord, GLfloat(layer) };
492 floatCoord = glu::va::Float("inCoord", 4, 4, 0, texCoordCubeMapArray);
495 floatCoord = glu::va::Float("inCoord", 2, 4, 0, texCoord2D);
497 glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("vertex", 3, 4, 0, vertices), floatCoord };
499 glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
500 glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(indices), indices));
505 * @param context Rendering context
507 SparseTextureClampLookupColorTestCase::SparseTextureClampLookupColorTestCase(deqp::Context& context)
508 : SparseTextureClampLookupResidencyTestCase(
509 context, "SparseTextureClampLookupColor",
510 "Verifies if sparse and non-sparse texture clamp lookup functions works as expected")
512 /* Left blank intentionally */
515 /** Stub init method */
516 void SparseTextureClampLookupColorTestCase::init()
518 SparseTextureCommitmentTestCase::init();
519 mSupportedTargets.push_back(GL_TEXTURE_1D);
520 mSupportedTargets.push_back(GL_TEXTURE_1D_ARRAY);
521 mSupportedInternalFormats.push_back(GL_DEPTH_COMPONENT16);
524 f = FunctionToken("sparseTextureClampARB", "<CUBE_REFZ_DEF>, <LOD>");
525 f.allowedTargets.insert(GL_TEXTURE_2D);
526 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
527 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
528 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
529 f.allowedTargets.insert(GL_TEXTURE_3D);
530 mFunctions.push_back(f);
532 f = FunctionToken("textureClampARB", "<CUBE_REFZ_DEF>, <LOD>");
533 f.allowedTargets.insert(GL_TEXTURE_1D);
534 f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
535 f.allowedTargets.insert(GL_TEXTURE_2D);
536 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
537 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
538 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
539 f.allowedTargets.insert(GL_TEXTURE_3D);
540 mFunctions.push_back(f);
542 f = FunctionToken("sparseTextureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
543 f.allowedTargets.insert(GL_TEXTURE_2D);
544 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
545 f.allowedTargets.insert(GL_TEXTURE_3D);
546 mFunctions.push_back(f);
548 f = FunctionToken("textureOffsetClampARB", ", <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
549 f.allowedTargets.insert(GL_TEXTURE_1D);
550 f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
551 f.allowedTargets.insert(GL_TEXTURE_2D);
552 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
553 f.allowedTargets.insert(GL_TEXTURE_3D);
554 mFunctions.push_back(f);
556 f = FunctionToken("sparseTextureGradClampARB",
557 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
558 f.allowedTargets.insert(GL_TEXTURE_2D);
559 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
560 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
561 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
562 f.allowedTargets.insert(GL_TEXTURE_3D);
563 mFunctions.push_back(f);
565 f = FunctionToken("textureGradClampARB", ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
566 f.allowedTargets.insert(GL_TEXTURE_1D);
567 f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
568 f.allowedTargets.insert(GL_TEXTURE_2D);
569 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
570 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP);
571 f.allowedTargets.insert(GL_TEXTURE_CUBE_MAP_ARRAY);
572 f.allowedTargets.insert(GL_TEXTURE_3D);
573 mFunctions.push_back(f);
576 "sparseTextureGradOffsetClampARB",
577 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
578 f.allowedTargets.insert(GL_TEXTURE_2D);
579 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
580 f.allowedTargets.insert(GL_TEXTURE_3D);
581 mFunctions.push_back(f);
584 "textureGradOffsetClampARB",
585 ", <NOFFSET_TYPE><OFFSET_DIM>(0), <NOFFSET_TYPE><OFFSET_DIM>(0), <OFFSET_TYPE><OFFSET_DIM>(0), <LOD>");
586 f.allowedTargets.insert(GL_TEXTURE_1D);
587 f.allowedTargets.insert(GL_TEXTURE_1D_ARRAY);
588 f.allowedTargets.insert(GL_TEXTURE_2D);
589 f.allowedTargets.insert(GL_TEXTURE_2D_ARRAY);
590 f.allowedTargets.insert(GL_TEXTURE_3D);
591 mFunctions.push_back(f);
594 /** Executes test iteration.
596 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
598 tcu::TestNode::IterateResult SparseTextureClampLookupColorTestCase::iterate()
600 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture_clamp"))
602 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
606 const Functions& gl = m_context.getRenderContext().getFunctions();
612 for (std::vector<glw::GLint>::const_iterator iter = mSupportedTargets.begin(); iter != mSupportedTargets.end();
615 const GLint& target = *iter;
617 for (std::vector<glw::GLint>::const_iterator formIter = mSupportedInternalFormats.begin();
618 formIter != mSupportedInternalFormats.end(); ++formIter)
620 const GLint& format = *formIter;
622 if (!caseAllowed(target, format))
625 for (std::vector<FunctionToken>::const_iterator tokIter = mFunctions.begin(); tokIter != mFunctions.end();
628 // Check if target is allowed for current lookup function
629 FunctionToken funcToken = *tokIter;
630 if (!funcAllowed(target, format, funcToken))
633 bool isSparse = false;
634 if (funcToken.name.find("sparse", 0) != std::string::npos)
638 mLog << "Testing sparse texture lookup color functions for target: " << target << ", format: " << format
642 sparseAllocateTexture(gl, target, format, texture, 3);
644 allocateTexture(gl, target, format, texture, 3);
646 if (format == GL_DEPTH_COMPONENT16)
647 setupDepthMode(gl, target, texture);
651 for (l = 0; l < mState.levels; ++l)
653 if (!isSparse || commitTexturePage(gl, target, format, texture, l))
655 writeDataToTexture(gl, target, format, texture, l);
660 for (l = 0; l <= maxLevels; ++l)
662 result = result && verifyLookupTextureData(gl, target, format, texture, l, funcToken);
668 Texture::Delete(gl, texture);
672 m_testCtx.getLog() << tcu::TestLog::Message << mLog.str() << "Fail" << tcu::TestLog::EndMessage;
673 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
680 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
684 /** Writing data to generated texture using compute shader
686 * @param gl GL API functions
687 * @param target Target for which texture is binded
688 * @param format Texture internal format
689 * @param texture Texture object
691 * @return Returns true if no error occurred, otherwise throws an exception.
693 bool SparseTextureClampLookupColorTestCase::writeDataToTexture(const Functions& gl, GLint target, GLint format,
694 GLuint& texture, GLint level)
696 mLog << "Fill Texture with shader [level: " << level << "] - ";
698 if (level > mState.levels - 1)
699 TCU_FAIL("Invalid level");
704 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
706 if (width > 0 && height > 0 && depth >= mState.minDepth)
708 if (target == GL_TEXTURE_CUBE_MAP)
711 GLint texSize = width * height * depth * mState.format.getPixelSize();
713 std::vector<GLubyte> vecData;
714 vecData.resize(texSize);
715 GLubyte* data = vecData.data();
717 deMemset(data, 255, texSize);
719 for (GLint sample = 0; sample < mState.samples; ++sample)
721 std::string shader = stc_compute_textureFill;
723 // Adjust shader source to texture format
724 TokenStrings s = createShaderTokens(target, format, sample);
726 // Change expected result as it has to be adjusted to different levels
727 s.resultExpected = generateExpectedResult(s.returnType, level);
729 replaceToken("<INPUT_TYPE>", s.inputType.c_str(), shader);
730 replaceToken("<POINT_TYPE>", s.pointType.c_str(), shader);
731 replaceToken("<POINT_DEF>", s.pointDef.c_str(), shader);
732 replaceToken("<RETURN_TYPE>", s.returnType.c_str(), shader);
733 replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), shader);
734 replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), shader);
736 ProgramSources sources;
737 sources << ComputeSource(shader);
739 GLint convFormat = format;
740 if (format == GL_DEPTH_COMPONENT16)
743 // Build and run shader
744 ShaderProgram program(m_context.getRenderContext(), sources);
747 gl.useProgram(program.getProgram());
748 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
749 gl.bindImageTexture(0 /* unit */, texture, level /* level */, GL_FALSE /* layered */, 0 /* layer */,
750 GL_WRITE_ONLY, convFormat);
751 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture");
752 gl.uniform1i(1, 0 /* image_unit */);
753 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
754 gl.dispatchCompute(width, height, depth);
755 GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute");
756 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
757 GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier");
761 mLog << "Compute shader compilation failed (writing) for target: " << target << ", format: " << format
762 << ", sample: " << sample << ", infoLog: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog
763 << ", shaderSource: " << shader.c_str() << " - ";
771 /** Verify if data stored in texture is as expected
773 * @param gl GL API functions
774 * @param target Target for which texture is binded
775 * @param format Texture internal format
776 * @param texture Texture object
777 * @param level Texture mipmap level
778 * @param funcToken Lookup function tokenize structure
780 * @return Returns true if data is as expected, false if not, throws an exception if error occurred.
782 bool SparseTextureClampLookupColorTestCase::verifyLookupTextureData(const Functions& gl, GLint target, GLint format,
783 GLuint& texture, GLint level,
784 FunctionToken& funcToken)
786 mLog << "Verify Lookup Color Texture Data [function: " << funcToken.name << ", level: " << level << "] - ";
788 if (level > mState.levels - 1)
789 TCU_FAIL("Invalid level");
794 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
796 if (width == 0 || height == 0 || depth < mState.minDepth)
801 if (target == GL_TEXTURE_CUBE_MAP)
804 GLint texSize = width * height;
806 std::vector<GLubyte> vecExpData;
807 std::vector<GLubyte> vecOutData;
808 vecExpData.resize(texSize);
809 vecOutData.resize(texSize);
810 GLubyte* exp_data = vecExpData.data();
811 GLubyte* out_data = vecOutData.data();
813 // Expected data is 255 because
814 deMemset(exp_data, 255, texSize);
816 // Create verifying texture
817 GLint verifyTarget = GL_TEXTURE_2D;
818 GLuint verifyTexture;
819 Texture::Generate(gl, verifyTexture);
820 Texture::Bind(gl, verifyTexture, verifyTarget);
821 Texture::Storage(gl, verifyTarget, 1, GL_R8, width, height, depth);
822 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::Storage");
825 gl.genFramebuffers(1, &fbo);
826 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers");
827 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
828 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
829 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, verifyTarget, verifyTexture, 0);
830 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D");
832 gl.viewport(0, 0, width, height);
834 for (GLint z = 0; z < depth; ++z)
836 for (int sample = 0; sample < mState.samples; ++sample)
838 deMemset(out_data, 0, texSize);
840 Texture::Bind(gl, verifyTexture, verifyTarget);
841 Texture::SubImage(gl, verifyTarget, 0, 0, 0, 0, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,
843 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::SubImage");
845 std::string vertex = stc_vertex_common;
846 std::string fragment = stc_fragment_lookupColor;
848 // Make token copy to work on
849 FunctionToken f = funcToken;
851 std::string functionDef = generateFunctionDef(f.name);
853 // Adjust shader source to texture format
854 TokenStringsExt s = createLookupShaderTokens(target, format, level, sample, f);
856 // Change expected result as it has to be adjusted to different levels
857 s.resultExpected = generateExpectedResult(s.returnType, level);
859 replaceToken("<COORD_TYPE>", s.coordType.c_str(), vertex);
861 replaceToken("<FUNCTION_DEF>", functionDef.c_str(), fragment);
862 replaceToken("<FUNCTION>", f.name.c_str(), fragment);
863 replaceToken("<ARGUMENTS>", f.arguments.c_str(), fragment);
865 replaceToken("<OUTPUT_TYPE>", s.outputType.c_str(), fragment);
866 replaceToken("<INPUT_TYPE>", s.inputType.c_str(), fragment);
867 replaceToken("<SIZE_DEF>", s.sizeDef.c_str(), fragment);
868 replaceToken("<LOD>", s.lod.c_str(), fragment);
869 replaceToken("<LOD_DEF>", s.lodDef.c_str(), fragment);
870 replaceToken("<COORD_TYPE>", s.coordType.c_str(), fragment);
871 replaceToken("<ICOORD_TYPE>", s.coordType.c_str(), fragment);
872 replaceToken("<COORD_DEF>", s.coordDef.c_str(), fragment);
873 replaceToken("<POINT_TYPE>", s.pointType.c_str(), fragment);
874 replaceToken("<POINT_DEF>", s.pointDef.c_str(), fragment);
875 replaceToken("<RETURN_TYPE>", s.returnType.c_str(), fragment);
876 replaceToken("<RESULT_EXPECTED>", s.resultExpected.c_str(), fragment);
877 replaceToken("<EPSILON>", s.epsilon.c_str(), fragment);
878 replaceToken("<SAMPLE_DEF>", s.sampleDef.c_str(), fragment);
879 replaceToken("<REFZ_DEF>", s.refZDef.c_str(), fragment);
880 replaceToken("<CUBE_REFZ_DEF>", s.cubeMapArrayRefZDef.c_str(), fragment);
881 replaceToken("<POINT_COORD>", s.pointCoord.c_str(), fragment);
882 replaceToken("<COMPONENT_DEF>", s.componentDef.c_str(), fragment);
883 replaceToken("<CUBE_MAP_COORD_DEF>", s.cubeMapCoordDef.c_str(), fragment);
884 replaceToken("<OFFSET_ARRAY_DEF>", s.offsetArrayDef.c_str(), fragment);
885 replaceToken("<FORMAT_DEF>", s.formatDef.c_str(), fragment);
886 replaceToken("<OFFSET_TYPE>", s.offsetType.c_str(), fragment);
887 replaceToken("<NOFFSET_TYPE>", s.nOffsetType.c_str(), fragment);
888 replaceToken("<OFFSET_DIM>", s.offsetDim.c_str(), fragment);
890 replaceToken("<TEX_WIDTH>", de::toString(width).c_str(), fragment);
891 replaceToken("<TEX_HEIGHT>", de::toString(height).c_str(), fragment);
892 replaceToken("<TEX_DEPTH>", de::toString(depth).c_str(), fragment);
894 ProgramSources sources = makeVtxFragSources(vertex.c_str(), fragment.c_str());
896 // Build and run shader
897 ShaderProgram program(m_context.getRenderContext(), sources);
900 gl.useProgram(program.getProgram());
901 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
903 // Pass input sampler/image to shader
904 gl.activeTexture(GL_TEXTURE0);
905 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
906 gl.uniform1i(1, 0 /* sampler_unit */);
907 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
909 gl.bindTexture(target, texture);
910 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
912 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
913 draw(target, z, program);
915 Texture::Bind(gl, verifyTexture, verifyTarget);
916 Texture::GetData(gl, 0, verifyTarget, GL_RED, GL_UNSIGNED_BYTE, (GLvoid*)out_data);
917 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture::GetData");
919 //Verify only committed region
920 for (GLint y = 0; y < height; ++y)
921 for (GLint x = 0; x < width; ++x)
923 GLubyte* dataRegion = exp_data + x + y * width;
924 GLubyte* outDataRegion = out_data + x + y * width;
925 if (dataRegion[0] != outDataRegion[0])
931 mLog << "Shader compilation failed (lookup color) for target: " << target << ", format: " << format
932 << ", vertexInfoLog: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog
933 << ", fragmentInfoLog: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog
934 << ", programInfoLog: " << program.getProgramInfo().infoLog
935 << ", fragmentSource: " << fragment.c_str() << " - ";
942 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
943 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
945 Texture::Delete(gl, verifyTexture);
950 /** Preparing texture. Function overridden to increase textures size.
952 * @param gl GL API functions
953 * @param target Target for which texture is binded
954 * @param format Texture internal format
955 * @param texture Texture object
957 * @return Returns true if no error occurred, otherwise throws an exception.
959 bool SparseTextureClampLookupColorTestCase::prepareTexture(const Functions& gl, GLint target, GLint format,
962 Texture::Generate(gl, texture);
963 Texture::Bind(gl, texture, target);
965 mState.minDepth = SparseTextureUtils::getTargetDepth(target);
966 SparseTextureUtils::getTexturePageSizes(gl, target, format, mState.pageSizeX, mState.pageSizeY, mState.pageSizeZ);
968 //The <width> and <height> has to be equal for cube map textures
969 if (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY)
971 if (mState.pageSizeX > mState.pageSizeY)
972 mState.pageSizeY = mState.pageSizeX;
973 else if (mState.pageSizeX < mState.pageSizeY)
974 mState.pageSizeX = mState.pageSizeY;
977 mState.width = 4 * mState.pageSizeX;
978 mState.height = 4 * mState.pageSizeY;
979 mState.depth = 4 * mState.pageSizeZ * mState.minDepth;
981 mState.format = glu::mapGLInternalFormat(format);
986 /** Commit texture page using texPageCommitment function. Function overridden to commit whole texture region.
988 * @param gl GL API functions
989 * @param target Target for which texture is binded
990 * @param format Texture internal format
991 * @param texture Texture object
992 * @param level Texture mipmap level
994 * @return Returns true if commitment is done properly, false if commitment is not allowed or throws exception if error occurred.
996 bool SparseTextureClampLookupColorTestCase::commitTexturePage(const Functions& gl, GLint target, GLint format,
997 GLuint& texture, GLint level)
999 mLog << "Commit Region [level: " << level << "] - ";
1001 if (level > mState.levels - 1)
1002 TCU_FAIL("Invalid level");
1004 // Avoid not allowed commitments
1005 if (!isInPageSizesRange(target, level) || !isPageSizesMultiplication(target, level))
1007 mLog << "Skip commitment [level: " << level << "] - ";
1014 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1016 if (target == GL_TEXTURE_CUBE_MAP)
1019 Texture::Bind(gl, texture, target);
1020 texPageCommitment(gl, target, format, texture, level, 0, 0, 0, width, height, depth, GL_TRUE);
1021 GLU_EXPECT_NO_ERROR(gl.getError(), "texPageCommitment");
1026 /** Check if current texture size for level is greater or equal page size in a corresponding direction
1028 * @param target Target for which texture is binded
1029 * @param level Texture mipmap level
1031 * @return Returns true if the texture size condition is fulfilled, false otherwise.
1033 bool SparseTextureClampLookupColorTestCase::isInPageSizesRange(GLint target, GLint level)
1038 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1040 if (target == GL_TEXTURE_CUBE_MAP)
1043 if (width >= mState.pageSizeX && height >= mState.pageSizeY && (mState.minDepth == 0 || depth >= mState.pageSizeZ))
1051 /** Check if current texture size for level is page size multiplication in a corresponding direction
1053 * @param target Target for which texture is binded
1054 * @param level Texture mipmap level
1056 * @return Returns true if the texture size condition is fulfilled, false otherwise.
1058 bool SparseTextureClampLookupColorTestCase::isPageSizesMultiplication(GLint target, GLint level)
1063 SparseTextureUtils::getTextureLevelSize(target, mState, level, width, height, depth);
1065 if (target == GL_TEXTURE_CUBE_MAP)
1068 if ((width % mState.pageSizeX) == 0 && (height % mState.pageSizeY) == 0 && (depth % mState.pageSizeZ) == 0)
1078 * @param funcName Tested function name.
1080 * @return Returns shader source code part that uses lookup function to fetch texel from texture.
1082 std::string SparseTextureClampLookupColorTestCase::generateFunctionDef(std::string funcName)
1084 if (funcName.find("sparse", 0) != std::string::npos)
1086 return std::string(" <FUNCTION>(uni_in,\n"
1087 " <POINT_COORD><SAMPLE_DEF><ARGUMENTS>,\n"
1088 " retValue<COMPONENT_DEF>);\n");
1092 return std::string(" retValue<COMPONENT_DEF> = <FUNCTION>(uni_in,\n"
1093 " <POINT_COORD><SAMPLE_DEF><ARGUMENTS>);\n");
1099 * @param returnType Expected result variable type.
1101 * @return Returns shader source token that represent expected lookup result value.
1103 std::string SparseTextureClampLookupColorTestCase::generateExpectedResult(std::string returnType, GLint level)
1105 if (returnType == "vec4")
1106 return std::string("(") + de::toString(0.5f + (float)level / 10) + std::string(", 0, 0, 1)");
1108 return std::string("(") + de::toString(level * 10) + std::string(", 0, 0, 1)");
1113 * @param context Rendering context.
1115 SparseTextureClampTests::SparseTextureClampTests(deqp::Context& context)
1116 : TestCaseGroup(context, "sparse_texture_clamp_tests",
1117 "Verify conformance of CTS_ARB_sparse_texture_clamp implementation")
1121 /** Initializes the test group contents. */
1122 void SparseTextureClampTests::init()
1124 addChild(new ShaderExtensionTestCase(m_context, "GL_ARB_sparse_texture_clamp"));
1125 addChild(new SparseTextureClampLookupResidencyTestCase(m_context));
1126 addChild(new SparseTextureClampLookupColorTestCase(m_context));
1129 } /* gl4cts namespace */