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