1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 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 Special float stress tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es3sSpecialFloatTests.hpp" 25#include "gluRenderContext.hpp" 26#include "gluShaderProgram.hpp" 27#include "gluPixelTransfer.hpp" 28#include "gluStrUtil.hpp" 29#include "gluContextInfo.hpp" 30#include "glwEnums.hpp" 31#include "glwFunctions.hpp" 32#include "tcuRenderTarget.hpp" 33#include "tcuSurface.hpp" 34#include "tcuTestLog.hpp" 35#include "tcuVectorUtil.hpp" 36#include "deStringUtil.hpp" 37#include "deMath.h" 38#include "deRandom.hpp" 39 40#include <limits> 41#include <sstream> 42 43using namespace glw; 44 45namespace deqp 46{ 47namespace gles3 48{ 49namespace Stress 50{ 51namespace 52{ 53 54static const int TEST_CANVAS_SIZE = 256; 55static const int TEST_TEXTURE_SIZE = 128; 56static const int TEST_TEXTURE_CUBE_SIZE = 32; 57static const deUint32 s_specialFloats[] = 58{ 59 0x00000000, // zero 60 0x80000000, // negative zero 61 0x3F800000, // one 62 0xBF800000, // negative one 63 0x00800000, // minimum positive normalized value 64 0x80800000, // maximum negative normalized value 65 0x00000001, // minimum positive denorm value 66 0x80000001, // maximum negative denorm value 67 0x7F7FFFFF, // maximum finite value. 68 0xFF7FFFFF, // minimum finite value. 69 0x7F800000, // inf 70 0xFF800000, // -inf 71 0x34000000, // epsilon 72 0xB4000000, // negative epsilon 73 0x7FC00000, // quiet_NaN 74 0xFFC00000, // negative quiet_NaN 75 0x7FC00001, // signaling_NaN 76 0xFFC00001, // negative signaling_NaN 77 0x7FEAAAAA, // quiet payloaded NaN (payload of repeated pattern of 101010...) 78 0xFFEAAAAA, // negative quiet payloaded NaN ( .. ) 79 0x7FAAAAAA, // signaling payloaded NaN ( .. ) 80 0xFFAAAAAA, // negative signaling payloaded NaN ( .. ) 81}; 82 83static const char* const s_colorPassthroughFragmentShaderSource = "#version 300 es\n" 84 "layout(location = 0) out mediump vec4 fragColor;\n" 85 "in mediump vec4 v_out;\n" 86 "void main ()\n" 87 "{\n" 88 " fragColor = v_out;\n" 89 "}\n"; 90static const char* const s_attrPassthroughVertexShaderSource = "#version 300 es\n" 91 "in highp vec4 a_pos;\n" 92 "in highp vec4 a_attr;\n" 93 "out highp vec4 v_attr;\n" 94 "void main ()\n" 95 "{\n" 96 " v_attr = a_attr;\n" 97 " gl_Position = a_pos;\n" 98 "}\n"; 99 100class RenderCase : public TestCase 101{ 102public: 103 enum RenderTargetType 104 { 105 RENDERTARGETTYPE_SCREEN, 106 RENDERTARGETTYPE_FBO 107 }; 108 109 RenderCase (Context& context, const char* name, const char* desc, RenderTargetType renderTargetType = RENDERTARGETTYPE_SCREEN); 110 virtual ~RenderCase (void); 111 112 virtual void init (void); 113 virtual void deinit (void); 114 115protected: 116 bool checkResultImage (const tcu::Surface& result); 117 bool drawTestPattern (bool useTexture); 118 119 virtual std::string genVertexSource (void) const = 0; 120 virtual std::string genFragmentSource (void) const = 0; 121 122 const glu::ShaderProgram* m_program; 123 const RenderTargetType m_renderTargetType; 124}; 125 126RenderCase::RenderCase (Context& context, const char* name, const char* desc, RenderTargetType renderTargetType) 127 : TestCase (context, name, desc) 128 , m_program (DE_NULL) 129 , m_renderTargetType (renderTargetType) 130{ 131} 132 133RenderCase::~RenderCase (void) 134{ 135 deinit(); 136} 137 138void RenderCase::init (void) 139{ 140 const int width = m_context.getRenderTarget().getWidth(); 141 const int height = m_context.getRenderTarget().getHeight(); 142 143 // check target size 144 if (m_renderTargetType == RENDERTARGETTYPE_SCREEN) 145 { 146 if (width < TEST_CANVAS_SIZE || height < TEST_CANVAS_SIZE) 147 throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(TEST_CANVAS_SIZE) + "x" + de::toString(TEST_CANVAS_SIZE)); 148 } 149 else if (m_renderTargetType == RENDERTARGETTYPE_FBO) 150 { 151 GLint maxTexSize = 0; 152 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); 153 154 if (maxTexSize < TEST_CANVAS_SIZE) 155 throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_CANVAS_SIZE)); 156 } 157 else 158 DE_ASSERT(false); 159 160 // gen shader 161 162 m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shader." << tcu::TestLog::EndMessage; 163 164 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(genVertexSource()) << glu::FragmentSource(genFragmentSource())); 165 m_testCtx.getLog() << *m_program; 166 167 if (!m_program->isOk()) 168 throw tcu::TestError("shader compile failed"); 169} 170 171void RenderCase::deinit (void) 172{ 173 if (m_program) 174 { 175 delete m_program; 176 m_program = DE_NULL; 177 } 178} 179 180bool RenderCase::checkResultImage (const tcu::Surface& result) 181{ 182 tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 183 bool error = false; 184 185 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output image." << tcu::TestLog::EndMessage; 186 187 for (int y = 0; y < TEST_CANVAS_SIZE; ++y) 188 for (int x = 0; x < TEST_CANVAS_SIZE; ++x) 189 { 190 const tcu::RGBA col = result.getPixel(x, y); 191 192 if (col.getGreen() == 255) 193 errorMask.setPixel(x, y, tcu::RGBA::green()); 194 else 195 { 196 errorMask.setPixel(x, y, tcu::RGBA::red()); 197 error = true; 198 } 199 } 200 201 if (error) 202 { 203 m_testCtx.getLog() << tcu::TestLog::Message << "Result image has missing or invalid pixels" << tcu::TestLog::EndMessage; 204 m_testCtx.getLog() 205 << tcu::TestLog::ImageSet("Results", "Result verification") 206 << tcu::TestLog::Image("Result", "Result", result) 207 << tcu::TestLog::Image("Error mask", "Error mask", errorMask) 208 << tcu::TestLog::EndImageSet; 209 } 210 else 211 { 212 m_testCtx.getLog() 213 << tcu::TestLog::ImageSet("Results", "Result verification") 214 << tcu::TestLog::Image("Result", "Result", result) 215 << tcu::TestLog::EndImageSet; 216 } 217 218 return !error; 219} 220 221bool RenderCase::drawTestPattern (bool useTexture) 222{ 223 static const tcu::Vec4 fullscreenQuad[4] = 224 { 225 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 226 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 227 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 228 tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), 229 }; 230 const char* const vertexSource = "#version 300 es\n" 231 "in highp vec4 a_pos;\n" 232 "out mediump vec4 v_position;\n" 233 "void main ()\n" 234 "{\n" 235 " v_position = a_pos;\n" 236 " gl_Position = a_pos;\n" 237 "}\n"; 238 const char* const fragmentSourceNoTex = "#version 300 es\n" 239 "layout(location = 0) out mediump vec4 fragColor;\n" 240 "in mediump vec4 v_position;\n" 241 "void main ()\n" 242 "{\n" 243 " fragColor = vec4((v_position.x + 1.0) * 0.5, 1.0, 1.0, 1.0);\n" 244 "}\n"; 245 const char* const fragmentSourceTex = "#version 300 es\n" 246 "layout(location = 0) out mediump vec4 fragColor;\n" 247 "uniform mediump sampler2D u_sampler;\n" 248 "in mediump vec4 v_position;\n" 249 "void main ()\n" 250 "{\n" 251 " fragColor = texture(u_sampler, v_position.xy);\n" 252 "}\n"; 253 const char* const fragmentSource = (useTexture) ? (fragmentSourceTex) : (fragmentSourceNoTex); 254 const tcu::RGBA formatThreshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold(); 255 256 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 257 tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 258 bool error = false; 259 260 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a test pattern to detect " << ((useTexture) ? ("texture sampling") : ("")) << " side-effects." << tcu::TestLog::EndMessage; 261 262 // draw pattern 263 { 264 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 265 const glu::ShaderProgram patternProgram (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource)); 266 const GLint positionLoc = gl.getAttribLocation(patternProgram.getProgram(), "a_pos"); 267 GLuint textureID = 0; 268 269 if (useTexture) 270 { 271 const int textureSize = 32; 272 std::vector<tcu::Vector<deUint8, 4> > buffer(textureSize*textureSize); 273 274 for (int x = 0; x < textureSize; ++x) 275 for (int y = 0; y < textureSize; ++y) 276 { 277 // sum of two axis aligned gradients. Each gradient is 127 at the edges and 0 at the center. 278 // pattern is symmetric (x and y) => no discontinuity near boundary => no need to worry of results with LINEAR filtering near boundaries 279 const deUint8 redComponent = (deUint8)de::clamp(de::abs((float)x / (float)textureSize - 0.5f) * 255.0f + de::abs((float)y / (float)textureSize - 0.5f) * 255.0f, 0.0f, 255.0f); 280 281 buffer[x * textureSize + y] = tcu::Vector<deUint8, 4>(redComponent, 255, 255, 255); 282 } 283 284 gl.genTextures(1, &textureID); 285 gl.bindTexture(GL_TEXTURE_2D, textureID); 286 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureSize, textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer[0].getPtr()); 287 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 288 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 289 } 290 291 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 292 gl.clear(GL_COLOR_BUFFER_BIT); 293 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 294 gl.useProgram(patternProgram.getProgram()); 295 296 if (useTexture) 297 gl.uniform1i(gl.getUniformLocation(patternProgram.getProgram(), "u_sampler"), 0); 298 299 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &fullscreenQuad[0]); 300 301 gl.enableVertexAttribArray(positionLoc); 302 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 303 gl.disableVertexAttribArray(positionLoc); 304 305 gl.useProgram(0); 306 gl.finish(); 307 GLU_EXPECT_NO_ERROR(gl.getError(), "RenderCase::drawTestPattern"); 308 309 if (textureID) 310 gl.deleteTextures(1, &textureID); 311 312 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 313 } 314 315 // verify pattern 316 for (int y = 0; y < TEST_CANVAS_SIZE; ++y) 317 for (int x = 0; x < TEST_CANVAS_SIZE; ++x) 318 { 319 const float texGradientPosX = deFloatFrac((float)x * 2.0f / (float)TEST_CANVAS_SIZE); 320 const float texGradientPosY = deFloatFrac((float)y * 2.0f / (float)TEST_CANVAS_SIZE); 321 const deUint8 texRedComponent = (deUint8)de::clamp(de::abs(texGradientPosX - 0.5f) * 255.0f + de::abs(texGradientPosY - 0.5f) * 255.0f, 0.0f, 255.0f); 322 323 const tcu::RGBA refColTexture = tcu::RGBA(texRedComponent, 255, 255, 255); 324 const tcu::RGBA refColGradient = tcu::RGBA((int)((float)x / (float)TEST_CANVAS_SIZE * 255.0f), 255, 255, 255); 325 const tcu::RGBA& refCol = (useTexture) ? (refColTexture) : (refColGradient); 326 327 const int colorThreshold = 10; 328 const tcu::RGBA col = resultImage.getPixel(x, y); 329 const tcu::IVec4 colorDiff = tcu::abs(col.toIVec() - refCol.toIVec()); 330 331 if (colorDiff.x() > formatThreshold.getRed() + colorThreshold || 332 colorDiff.y() > formatThreshold.getGreen() + colorThreshold || 333 colorDiff.z() > formatThreshold.getBlue() + colorThreshold) 334 { 335 errorMask.setPixel(x, y, tcu::RGBA::red()); 336 error = true; 337 } 338 else 339 errorMask.setPixel(x, y, tcu::RGBA::green()); 340 } 341 342 // report error 343 if (error) 344 { 345 m_testCtx.getLog() << tcu::TestLog::Message << "Test pattern has missing/invalid pixels" << tcu::TestLog::EndMessage; 346 m_testCtx.getLog() 347 << tcu::TestLog::ImageSet("Results", "Result verification") 348 << tcu::TestLog::Image("Result", "Result", resultImage) 349 << tcu::TestLog::Image("Error mask", "Error mask", errorMask) 350 << tcu::TestLog::EndImageSet; 351 } 352 else 353 m_testCtx.getLog() << tcu::TestLog::Message << "No side-effects found." << tcu::TestLog::EndMessage; 354 355 return !error; 356} 357 358class FramebufferRenderCase : public RenderCase 359{ 360public: 361 enum FrameBufferType 362 { 363 FBO_DEFAULT = 0, 364 FBO_RGBA4, 365 FBO_RGB5_A1, 366 FBO_RGB565, 367 FBO_RGBA8, 368 FBO_RGB10_A2, 369 FBO_RGBA_FLOAT16, 370 FBO_RGBA_FLOAT32, 371 372 FBO_LAST 373 }; 374 375 FramebufferRenderCase (Context& context, const char* name, const char* desc, FrameBufferType fboType); 376 virtual ~FramebufferRenderCase (void); 377 378 virtual void init (void); 379 virtual void deinit (void); 380 IterateResult iterate (void); 381 382 virtual void testFBO (void) = DE_NULL; 383 384protected: 385 const FrameBufferType m_fboType; 386 387private: 388 GLuint m_texID; 389 GLuint m_fboID; 390}; 391 392FramebufferRenderCase::FramebufferRenderCase (Context& context, const char* name, const char* desc, FrameBufferType fboType) 393 : RenderCase (context, name, desc, (fboType == FBO_DEFAULT) ? (RENDERTARGETTYPE_SCREEN) : (RENDERTARGETTYPE_FBO)) 394 , m_fboType (fboType) 395 , m_texID (0) 396 , m_fboID (0) 397{ 398 DE_ASSERT(m_fboType < FBO_LAST); 399} 400 401FramebufferRenderCase::~FramebufferRenderCase (void) 402{ 403 deinit(); 404} 405 406void FramebufferRenderCase::init (void) 407{ 408 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 409 410 // check requirements 411 if (m_fboType == FBO_RGBA_FLOAT16) 412 { 413 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_half_float") && 414 !m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float")) 415 throw tcu::NotSupportedError("Color renderable half float texture required."); 416 } 417 else if (m_fboType == FBO_RGBA_FLOAT32) 418 { 419 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float")) 420 throw tcu::NotSupportedError("Color renderable float texture required."); 421 } 422 423 // gen shader 424 RenderCase::init(); 425 426 // create render target 427 if (m_fboType == FBO_DEFAULT) 428 { 429 m_testCtx.getLog() << tcu::TestLog::Message << "Using default framebuffer." << tcu::TestLog::EndMessage; 430 } 431 else 432 { 433 GLuint internalFormat = 0; 434 GLuint format = 0; 435 GLuint type = 0; 436 437 switch (m_fboType) 438 { 439 case FBO_RGBA4: internalFormat = GL_RGBA4; format = GL_RGBA; type = GL_UNSIGNED_SHORT_4_4_4_4; break; 440 case FBO_RGB5_A1: internalFormat = GL_RGB5_A1; format = GL_RGBA; type = GL_UNSIGNED_SHORT_5_5_5_1; break; 441 case FBO_RGB565: internalFormat = GL_RGB565; format = GL_RGB; type = GL_UNSIGNED_SHORT_5_6_5; break; 442 case FBO_RGBA8: internalFormat = GL_RGBA8; format = GL_RGBA; type = GL_UNSIGNED_BYTE; break; 443 case FBO_RGB10_A2: internalFormat = GL_RGB10_A2; format = GL_RGBA; type = GL_UNSIGNED_INT_2_10_10_10_REV; break; 444 case FBO_RGBA_FLOAT16: internalFormat = GL_RGBA16F; format = GL_RGBA; type = GL_HALF_FLOAT; break; 445 case FBO_RGBA_FLOAT32: internalFormat = GL_RGBA32F; format = GL_RGBA; type = GL_FLOAT; break; 446 447 default: 448 DE_ASSERT(false); 449 break; 450 } 451 452 m_testCtx.getLog() << tcu::TestLog::Message 453 << "Creating fbo. Texture internalFormat = " << glu::getTextureFormatStr(internalFormat) 454 << ", format = " << glu::getTextureFormatStr(format) 455 << ", type = " << glu::getTypeStr(type) 456 << tcu::TestLog::EndMessage; 457 458 // gen texture 459 gl.genTextures(1, &m_texID); 460 gl.bindTexture(GL_TEXTURE_2D, m_texID); 461 gl.texImage2D(GL_TEXTURE_2D, 0, internalFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, 0, format, type, DE_NULL); 462 GLU_EXPECT_NO_ERROR(gl.getError(), "texture init"); 463 464 // gen fbo 465 gl.genFramebuffers(1, &m_fboID); 466 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboID); 467 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texID, 0); 468 GLU_EXPECT_NO_ERROR(gl.getError(), "fbo init"); 469 470 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 471 throw tcu::NotSupportedError("could not create fbo for testing."); 472 } 473} 474 475void FramebufferRenderCase::deinit (void) 476{ 477 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 478 479 if (m_texID) 480 { 481 gl.deleteTextures(1, &m_texID); 482 m_texID = 0; 483 } 484 485 if (m_fboID) 486 { 487 gl.deleteFramebuffers(1, &m_fboID); 488 m_fboID = 0; 489 } 490} 491 492FramebufferRenderCase::IterateResult FramebufferRenderCase::iterate (void) 493{ 494 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 495 496 // bind fbo (or don't if we are using default) 497 if (m_fboID) 498 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboID); 499 500 // do something with special floats 501 testFBO(); 502 503 return STOP; 504} 505 506/*--------------------------------------------------------------------*//*! 507 * \brief Tests special floats as vertex attributes 508 * 509 * Tests that special floats transferred to the shader using vertex 510 * attributes do not change the results of normal floating point 511 * calculations. Special floats are put to 4-vector's x and y components and 512 * value 1.0 is put to z and w. The resulting fragment's green channel 513 * should be 1.0 everywhere. 514 * 515 * After the calculation test a test pattern is drawn to detect possible 516 * floating point operation anomalies. 517 *//*--------------------------------------------------------------------*/ 518class VertexAttributeCase : public RenderCase 519{ 520public: 521 enum Storage 522 { 523 STORAGE_BUFFER = 0, 524 STORAGE_CLIENT, 525 526 STORAGE_LAST 527 }; 528 enum ShaderType 529 { 530 TYPE_VERTEX = 0, 531 TYPE_FRAGMENT, 532 533 TYPE_LAST 534 }; 535 536 VertexAttributeCase (Context& context, const char* name, const char* desc, Storage storage, ShaderType type); 537 ~VertexAttributeCase (void); 538 539 void init (void); 540 void deinit (void); 541 IterateResult iterate (void); 542 543private: 544 std::string genVertexSource (void) const; 545 std::string genFragmentSource (void) const; 546 547 const Storage m_storage; 548 const ShaderType m_type; 549 GLuint m_positionVboID; 550 GLuint m_attribVboID; 551 GLuint m_elementVboID; 552}; 553 554VertexAttributeCase::VertexAttributeCase (Context& context, const char* name, const char* desc, Storage storage, ShaderType type) 555 : RenderCase (context, name, desc) 556 , m_storage (storage) 557 , m_type (type) 558 , m_positionVboID (0) 559 , m_attribVboID (0) 560 , m_elementVboID (0) 561{ 562 DE_ASSERT(storage < STORAGE_LAST); 563 DE_ASSERT(type < TYPE_LAST); 564} 565 566VertexAttributeCase::~VertexAttributeCase (void) 567{ 568 deinit(); 569} 570 571void VertexAttributeCase::init (void) 572{ 573 RenderCase::init(); 574 575 // init gl resources 576 if (m_storage == STORAGE_BUFFER) 577 { 578 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 579 580 gl.genBuffers(1, &m_positionVboID); 581 gl.genBuffers(1, &m_attribVboID); 582 gl.genBuffers(1, &m_elementVboID); 583 } 584} 585 586void VertexAttributeCase::deinit (void) 587{ 588 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 589 590 RenderCase::deinit(); 591 592 if (m_attribVboID) 593 { 594 gl.deleteBuffers(1, &m_attribVboID); 595 m_attribVboID = 0; 596 } 597 598 if (m_positionVboID) 599 { 600 gl.deleteBuffers(1, &m_positionVboID); 601 m_positionVboID = 0; 602 } 603 604 if (m_elementVboID) 605 { 606 gl.deleteBuffers(1, &m_elementVboID); 607 m_elementVboID = 0; 608 } 609} 610 611VertexAttributeCase::IterateResult VertexAttributeCase::iterate (void) 612{ 613 // Create a [s_specialFloats] X [s_specialFloats] grid of vertices with each vertex having 2 [s_specialFloats] values 614 // and calculate some basic operations with the floating point values. If all goes well, nothing special should happen 615 616 std::vector<tcu::Vec4> gridVertices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats)); 617 std::vector<tcu::UVec4> gridAttributes (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats)); 618 std::vector<deUint16> indices ((DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * 6); 619 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 620 621 // vertices 622 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 623 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 624 { 625 const deUint32 one = 0x3F800000; 626 const float posX = (float)x / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) - 1] to [-1, 1] 627 const float posY = (float)y / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; 628 629 gridVertices[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 630 gridAttributes[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::UVec4(s_specialFloats[x], s_specialFloats[y], one, one); 631 } 632 633 // tiles 634 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++x) 635 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++y) 636 { 637 const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) + y) * 6; 638 639 indices[baseNdx + 0] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 640 indices[baseNdx + 1] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 641 indices[baseNdx + 2] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 642 643 indices[baseNdx + 3] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 644 indices[baseNdx + 4] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 645 indices[baseNdx + 5] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 646 } 647 648 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a grid with the shader. Setting a_attr for each vertex to (special, special, 1, 1)." << tcu::TestLog::EndMessage; 649 650 // Draw grid 651 { 652 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 653 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 654 const GLint attribLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr"); 655 656 if (m_storage == STORAGE_BUFFER) 657 { 658 gl.bindBuffer(GL_ARRAY_BUFFER, m_positionVboID); 659 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(gridVertices.size() * sizeof(tcu::Vec4)), &gridVertices[0], GL_STATIC_DRAW); 660 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate"); 661 662 gl.bindBuffer(GL_ARRAY_BUFFER, m_attribVboID); 663 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(gridAttributes.size() * sizeof(tcu::UVec4)), &gridAttributes[0], GL_STATIC_DRAW); 664 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate"); 665 666 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementVboID); 667 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(indices.size() * sizeof(deUint16)), &indices[0], GL_STATIC_DRAW); 668 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate"); 669 } 670 671 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 672 gl.clear(GL_COLOR_BUFFER_BIT); 673 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 674 gl.useProgram(m_program->getProgram()); 675 676 if (m_storage == STORAGE_BUFFER) 677 { 678 gl.bindBuffer(GL_ARRAY_BUFFER, m_positionVboID); 679 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 680 681 gl.bindBuffer(GL_ARRAY_BUFFER, m_attribVboID); 682 gl.vertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 683 684 gl.enableVertexAttribArray(positionLoc); 685 gl.enableVertexAttribArray(attribLoc); 686 gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, DE_NULL); 687 gl.disableVertexAttribArray(positionLoc); 688 gl.disableVertexAttribArray(attribLoc); 689 690 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 691 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 692 } 693 else if (m_storage == STORAGE_CLIENT) 694 { 695 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 696 gl.vertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridAttributes[0]); 697 698 gl.enableVertexAttribArray(positionLoc); 699 gl.enableVertexAttribArray(attribLoc); 700 gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]); 701 gl.disableVertexAttribArray(positionLoc); 702 gl.disableVertexAttribArray(attribLoc); 703 } 704 else 705 DE_ASSERT(false); 706 707 gl.useProgram(0); 708 gl.finish(); 709 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttributeCase::iterate"); 710 711 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 712 } 713 714 // verify everywhere was drawn (all pixels have Green = 255) 715 if (!checkResultImage(resultImage)) 716 { 717 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments"); 718 return STOP; 719 } 720 721 // test drawing still works 722 if (!drawTestPattern(false)) 723 { 724 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed"); 725 return STOP; 726 } 727 728 // all ok 729 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 730 return STOP; 731} 732 733std::string VertexAttributeCase::genVertexSource (void) const 734{ 735 if (m_type == TYPE_VERTEX) 736 return 737 "#version 300 es\n" 738 "in highp vec4 a_pos;\n" 739 "in highp vec4 a_attr;\n" 740 "out mediump vec4 v_out;\n" 741 "void main ()\n" 742 "{\n" 743 " highp vec2 a1 = a_attr.xz + a_attr.yw; // add\n" 744 " highp vec2 a2 = a_attr.xz - a_attr.yw; // sub\n" 745 " highp vec2 a3 = a_attr.xz * a_attr.yw; // mul\n" 746 " highp vec2 a4 = a_attr.xz / a_attr.yw; // div\n" 747 " highp vec2 a5 = a_attr.xz + a_attr.yw * a_attr.xz; // fma\n" 748 "\n" 749 " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y) - 6.0);\n" 750 " v_out = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x, 1.0);\n" 751 " gl_Position = a_pos;\n" 752 "}\n"; 753 else 754 return s_attrPassthroughVertexShaderSource; 755} 756 757std::string VertexAttributeCase::genFragmentSource (void) const 758{ 759 if (m_type == TYPE_VERTEX) 760 return s_colorPassthroughFragmentShaderSource; 761 else 762 return 763 "#version 300 es\n" 764 "layout(location = 0) out mediump vec4 fragColor;\n" 765 "in highp vec4 v_attr;\n" 766 "void main ()\n" 767 "{\n" 768 " highp vec2 a1 = v_attr.xz + v_attr.yw; // add\n" 769 " highp vec2 a2 = v_attr.xz - v_attr.yw; // sub\n" 770 " highp vec2 a3 = v_attr.xz * v_attr.yw; // mul\n" 771 " highp vec2 a4 = v_attr.xz / v_attr.yw; // div\n" 772 " highp vec2 a5 = v_attr.xz + v_attr.yw * v_attr.xz; // fma\n" 773 " highp vec2 a6 = dFdx(v_attr.xz);\n" 774 "\n" 775 " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y + a6.y) - 6.0);\n" 776 " fragColor = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x+a6.x, 1.0);\n" 777 "}\n"; 778} 779 780/*--------------------------------------------------------------------*//*! 781 * \brief Tests special floats as uniforms 782 * 783 * Tests that special floats transferred to the shader as uniforms do 784 * not change the results of normal floating point calculations. Special 785 * floats are put to 4-vector's x and y components and value 1.0 is put to 786 * z and w. The resulting fragment's green channel should be 1.0 787 * everywhere. 788 * 789 * After the calculation test a test pattern is drawn to detect possible 790 * floating point operation anomalies. 791 *//*--------------------------------------------------------------------*/ 792class UniformCase : public RenderCase 793{ 794public: 795 enum ShaderType 796 { 797 TYPE_VERTEX = 0, 798 TYPE_FRAGMENT, 799 }; 800 801 UniformCase (Context& context, const char* name, const char* desc, ShaderType type); 802 ~UniformCase (void); 803 804 void init (void); 805 void deinit (void); 806 IterateResult iterate (void); 807 808private: 809 std::string genVertexSource (void) const; 810 std::string genFragmentSource (void) const; 811 812 const ShaderType m_type; 813}; 814 815UniformCase::UniformCase (Context& context, const char* name, const char* desc, ShaderType type) 816 : RenderCase (context, name, desc) 817 , m_type (type) 818{ 819} 820 821UniformCase::~UniformCase (void) 822{ 823 deinit(); 824} 825 826void UniformCase::init (void) 827{ 828 RenderCase::init(); 829} 830 831void UniformCase::deinit (void) 832{ 833 RenderCase::deinit(); 834} 835 836UniformCase::IterateResult UniformCase::iterate (void) 837{ 838 // Create a [s_specialFloats] X [s_specialFloats] grid of tile with each tile having 2 [s_specialFloats] values 839 // and calculate some basic operations with the floating point values. If all goes well, nothing special should happen 840 841 std::vector<tcu::Vec4> gridVertices ((DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1)); 842 std::vector<deUint16> indices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats) * 6); 843 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 844 845 // vertices 846 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++x) 847 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++y) 848 { 849 const float posX = (float)x / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) ] to [-1, 1] 850 const float posY = (float)y / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; 851 852 gridVertices[x * (DE_LENGTH_OF_ARRAY(s_specialFloats)+1) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 853 } 854 855 // tiles 856 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 857 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 858 { 859 const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats)) + y) * 6; 860 861 indices[baseNdx + 0] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0)); 862 indices[baseNdx + 1] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1)); 863 indices[baseNdx + 2] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0)); 864 865 indices[baseNdx + 3] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+0)); 866 indices[baseNdx + 4] = (deUint16)((x+1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1)); 867 indices[baseNdx + 5] = (deUint16)((x+0) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) + (y+1)); 868 } 869 870 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a grid with the shader. Setting u_special for vertex each tile to (special, special, 1, 1)." << tcu::TestLog::EndMessage; 871 872 // Draw grid 873 { 874 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 875 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 876 const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special"); 877 878 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 879 gl.clear(GL_COLOR_BUFFER_BIT); 880 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 881 gl.useProgram(m_program->getProgram()); 882 883 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 884 gl.enableVertexAttribArray(positionLoc); 885 886 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 887 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 888 { 889 const deUint32 one = 0x3F800000; 890 const tcu::UVec4 uniformValue = tcu::UVec4(s_specialFloats[x], s_specialFloats[y], one, one); 891 const int indexIndex = (x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y) * 6; 892 893 gl.uniform4fv(specialLoc, 1, (const float*)uniformValue.getPtr()); 894 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]); 895 } 896 897 898 gl.disableVertexAttribArray(positionLoc); 899 900 gl.useProgram(0); 901 gl.finish(); 902 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformCase::iterate"); 903 904 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 905 } 906 907 // verify everywhere was drawn (all pixels have Green = 255) 908 if (!checkResultImage(resultImage)) 909 { 910 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments"); 911 return STOP; 912 } 913 914 // test drawing still works 915 if (!drawTestPattern(false)) 916 { 917 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed"); 918 return STOP; 919 } 920 921 // all ok 922 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 923 return STOP; 924} 925 926std::string UniformCase::genVertexSource (void) const 927{ 928 if (m_type == TYPE_VERTEX) 929 return 930 "#version 300 es\n" 931 "in highp vec4 a_pos;\n" 932 "uniform highp vec4 u_special;\n" 933 "out mediump vec4 v_out;\n" 934 "void main ()\n" 935 "{\n" 936 " highp vec2 a1 = u_special.xz + u_special.yw; // add\n" 937 " highp vec2 a2 = u_special.xz - u_special.yw; // sub\n" 938 " highp vec2 a3 = u_special.xz * u_special.yw; // mul\n" 939 " highp vec2 a4 = u_special.xz / u_special.yw; // div\n" 940 " highp vec2 a5 = u_special.xz + u_special.yw * u_special.xz; // fma\n" 941 "\n" 942 " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y) - 6.0);\n" 943 " v_out = vec4(a1.x*a3.x + a2.x*a4.x, green, a5.x, 1.0);\n" 944 " gl_Position = a_pos;\n" 945 "}\n"; 946 else 947 return 948 "#version 300 es\n" 949 "in highp vec4 a_pos;\n" 950 "void main ()\n" 951 "{\n" 952 " gl_Position = a_pos;\n" 953 "}\n"; 954} 955 956std::string UniformCase::genFragmentSource (void) const 957{ 958 if (m_type == TYPE_VERTEX) 959 return s_colorPassthroughFragmentShaderSource; 960 else 961 return 962 "#version 300 es\n" 963 "layout(location = 0) out mediump vec4 fragColor;\n" 964 "uniform highp vec4 u_special;\n" 965 "void main ()\n" 966 "{\n" 967 " highp vec2 a1 = u_special.xz + u_special.yw; // add\n" 968 " highp vec2 a2 = u_special.xz - u_special.yw; // sub\n" 969 " highp vec2 a3 = u_special.xz * u_special.yw; // mul\n" 970 " highp vec2 a4 = u_special.xz / u_special.yw; // div\n" 971 " highp vec2 a5 = u_special.xz + u_special.yw * u_special.xz; // fma\n" 972 " highp vec2 a6 = mod(u_special.xz, u_special.yw);\n" 973 " highp vec2 a7 = mix(u_special.xz, u_special.yw, a6);\n" 974 "\n" 975 " highp float green = 1.0 - abs((a1.y + a2.y + a3.y + a4.y + a5.y + a6.y + a7.y) - 7.0);\n" 976 " fragColor = vec4(a1.x*a3.x, green, a5.x*a4.x + a2.x*a7.x, 1.0);\n" 977 "}\n"; 978} 979 980/*--------------------------------------------------------------------*//*! 981 * \brief Tests special floats in floating point textures 982 * 983 * Tests that sampling special floats from a floating point texture 984 * does not affect the values of other color components of the sample. Test 985 * samples a RG texture with R channel filled with special floats and G 986 * channel filled with test values. 987 * 988 * Tests that linear sampling using compare mode = COMPARE_REF_TO_TEXTURE 989 * of a floating point depth texture containing special floating point 990 * values does not produce values outside the [0, 1] range. 991 * 992 * After the calculation test a test pattern is drawn to detect possible 993 * texture sampling anomalies. 994 *//*--------------------------------------------------------------------*/ 995class TextureCase : public RenderCase 996{ 997public: 998 enum ShaderType 999 { 1000 TYPE_VERTEX = 0, 1001 TYPE_FRAGMENT, 1002 1003 TYPE_LAST 1004 }; 1005 enum TextureType 1006 { 1007 TEXTURE_FLOAT = 0, 1008 TEXTURE_DEPTH, 1009 1010 TEXTURE_LAST 1011 }; 1012 enum UploadType 1013 { 1014 UPLOAD_CLIENT = 0, 1015 UPLOAD_PBO, 1016 1017 UPLOAD_LAST 1018 }; 1019 1020 TextureCase (Context& context, const char* name, const char* desc, ShaderType type, TextureType texType, UploadType uploadType); 1021 ~TextureCase (void); 1022 1023 void init (void); 1024 void deinit (void); 1025 IterateResult iterate (void); 1026 1027private: 1028 std::string genVertexSource (void) const; 1029 std::string genFragmentSource (void) const; 1030 1031 const ShaderType m_type; 1032 const TextureType m_textureType; 1033 const UploadType m_uploadType; 1034 GLuint m_textureID; 1035 GLuint m_pboID; 1036}; 1037 1038TextureCase::TextureCase (Context& context, const char* name, const char* desc, ShaderType type, TextureType texType, UploadType uploadType) 1039 : RenderCase (context, name, desc) 1040 , m_type (type) 1041 , m_textureType (texType) 1042 , m_uploadType (uploadType) 1043 , m_textureID (0) 1044 , m_pboID (0) 1045{ 1046 DE_ASSERT(type < TYPE_LAST); 1047 DE_ASSERT(texType < TEXTURE_LAST); 1048 DE_ASSERT(uploadType < UPLOAD_LAST); 1049} 1050 1051TextureCase::~TextureCase (void) 1052{ 1053 deinit(); 1054} 1055 1056void TextureCase::init (void) 1057{ 1058 // requirements 1059 { 1060 GLint maxTextureSize = 0; 1061 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 1062 if (maxTextureSize < TEST_TEXTURE_SIZE) 1063 throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_TEXTURE_SIZE)); 1064 } 1065 1066 RenderCase::init(); 1067 1068 // gen texture 1069 { 1070 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1071 de::Random rnd (12345); 1072 1073 gl.genTextures(1, &m_textureID); 1074 gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1075 1076 if (m_uploadType == UPLOAD_PBO) 1077 { 1078 gl.genBuffers(1, &m_pboID); 1079 gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pboID); 1080 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init"); 1081 } 1082 1083 if (m_textureType == TEXTURE_FLOAT) 1084 { 1085 std::vector<deUint32> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*2); 1086 const deUint32* dataPtr = (m_uploadType == UPLOAD_CLIENT) ? (&texData[0]) : (DE_NULL); 1087 1088 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a 2D 2-component float texture. Pixel contents are of form (special, 1)." << tcu::TestLog::EndMessage; 1089 1090 // set green channel to 1.0 1091 for (int x = 0; x < TEST_TEXTURE_SIZE; ++x) 1092 for (int y = 0; y < TEST_TEXTURE_SIZE; ++y) 1093 { 1094 texData[(x * TEST_TEXTURE_SIZE + y) * 2 + 0] = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1095 texData[(x * TEST_TEXTURE_SIZE + y) * 2 + 1] = 0x3F800000; // one 1096 } 1097 1098 if (m_uploadType == UPLOAD_PBO) 1099 gl.bufferData(GL_PIXEL_UNPACK_BUFFER, (glw::GLsizeiptr)(texData.size() * sizeof(deUint32)), &texData[0], GL_STATIC_DRAW); 1100 1101 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RG32F, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_RG, GL_FLOAT, dataPtr); 1102 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1103 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1104 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init"); 1105 } 1106 else if (m_textureType == TEXTURE_DEPTH) 1107 { 1108 std::vector<deUint32> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE); 1109 const deUint32* dataPtr = (m_uploadType == UPLOAD_CLIENT) ? (&texData[0]) : (DE_NULL); 1110 1111 m_testCtx.getLog() << tcu::TestLog::Message 1112 << "Creating a 2D depth texture and filling it with special floating point values.\n" 1113 << " TEXTURE_COMPARE_MODE = COMPARE_REF_TO_TEXTURE" 1114 << tcu::TestLog::EndMessage; 1115 1116 for (int x = 0; x < TEST_TEXTURE_SIZE; ++x) 1117 for (int y = 0; y < TEST_TEXTURE_SIZE; ++y) 1118 texData[x * TEST_TEXTURE_SIZE + y] = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1119 1120 if (m_uploadType == UPLOAD_PBO) 1121 gl.bufferData(GL_PIXEL_UNPACK_BUFFER, (glw::GLsizeiptr)(texData.size() * sizeof(deUint32)), &texData[0], GL_STATIC_DRAW); 1122 1123 gl.texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, dataPtr); 1124 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 1125 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); 1126 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1127 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1128 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::init"); 1129 } 1130 else 1131 DE_ASSERT(false); 1132 1133 if (m_uploadType == UPLOAD_PBO) 1134 { 1135 m_testCtx.getLog() << tcu::TestLog::Message << "PBO used for image upload." << tcu::TestLog::EndMessage; 1136 1137 gl.bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 1138 gl.deleteBuffers(1, &m_pboID); 1139 m_pboID = 0; 1140 } 1141 } 1142} 1143 1144void TextureCase::deinit (void) 1145{ 1146 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1147 1148 RenderCase::deinit(); 1149 1150 if (m_textureID) 1151 { 1152 gl.deleteTextures(1, &m_textureID); 1153 m_textureID = 0; 1154 } 1155 if (m_pboID) 1156 { 1157 gl.deleteBuffers(1, &m_pboID); 1158 m_pboID = 0; 1159 } 1160} 1161 1162TextureCase::IterateResult TextureCase::iterate (void) 1163{ 1164 // Draw a grid and texture it with a floating point texture containing special values. If all goes well, nothing special should happen 1165 1166 const int gridSize = 16; 1167 std::vector<tcu::Vec4> gridVertices (gridSize * gridSize); 1168 std::vector<tcu::Vec2> gridTexCoords (gridSize * gridSize); 1169 std::vector<deUint16> indices ((gridSize - 1) * (gridSize - 1) * 6); 1170 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1171 1172 // vertices 1173 for (int x = 0; x < gridSize; ++x) 1174 for (int y = 0; y < gridSize; ++y) 1175 { 1176 const float posX = (float)x / ((float)gridSize - 1.0f) * 2.0f - 1.0f; // map from [0, gridSize - 1] to [-1, 1] 1177 const float posY = (float)y / ((float)gridSize - 1.0f) * 2.0f - 1.0f; 1178 const float texCoordX = deFloatPow(2.0f, (float)x - (float)gridSize / 2.0f); 1179 const float texCoordY = deFloatPow(2.0f, (float)y - (float)gridSize / 2.0f); 1180 1181 gridVertices[x * gridSize + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 1182 gridTexCoords[x * gridSize + y] = tcu::Vec2(texCoordX, texCoordY); 1183 } 1184 1185 // tiles 1186 for (int x = 0; x < gridSize - 1; ++x) 1187 for (int y = 0; y < gridSize - 1; ++y) 1188 { 1189 const int baseNdx = (x * (gridSize - 1) + y) * 6; 1190 1191 indices[baseNdx + 0] = (deUint16)((x+0) * gridSize + (y+0)); 1192 indices[baseNdx + 1] = (deUint16)((x+1) * gridSize + (y+1)); 1193 indices[baseNdx + 2] = (deUint16)((x+1) * gridSize + (y+0)); 1194 1195 indices[baseNdx + 3] = (deUint16)((x+0) * gridSize + (y+0)); 1196 indices[baseNdx + 4] = (deUint16)((x+1) * gridSize + (y+1)); 1197 indices[baseNdx + 5] = (deUint16)((x+0) * gridSize + (y+1)); 1198 } 1199 1200 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a textured grid with the shader." << tcu::TestLog::EndMessage; 1201 1202 // Draw grid 1203 { 1204 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1205 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 1206 const GLint texCoordLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr"); 1207 const GLint samplerLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampler"); 1208 1209 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1210 gl.clear(GL_COLOR_BUFFER_BIT); 1211 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1212 gl.useProgram(m_program->getProgram()); 1213 1214 gl.uniform1i(samplerLoc, 0); 1215 gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1216 1217 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 1218 gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, &gridTexCoords[0]); 1219 1220 gl.enableVertexAttribArray(positionLoc); 1221 gl.enableVertexAttribArray(texCoordLoc); 1222 gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]); 1223 gl.disableVertexAttribArray(positionLoc); 1224 gl.disableVertexAttribArray(texCoordLoc); 1225 1226 gl.useProgram(0); 1227 gl.finish(); 1228 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureCase::iterate"); 1229 1230 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 1231 } 1232 1233 // verify everywhere was drawn (all pixels have Green = 255) 1234 if (!checkResultImage(resultImage)) 1235 { 1236 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments"); 1237 return STOP; 1238 } 1239 1240 // test drawing and textures still works 1241 if (!drawTestPattern(true)) 1242 { 1243 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed"); 1244 return STOP; 1245 } 1246 1247 // all ok 1248 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1249 return STOP; 1250} 1251 1252std::string TextureCase::genVertexSource (void) const 1253{ 1254 // vertex shader is passthrough, fragment does the calculations 1255 if (m_type == TYPE_FRAGMENT) 1256 return s_attrPassthroughVertexShaderSource; 1257 1258 // vertex shader does the calculations 1259 std::ostringstream buf; 1260 buf << "#version 300 es\n" 1261 "in highp vec4 a_pos;\n" 1262 "in highp vec2 a_attr;\n" 1263 "out mediump vec4 v_out;\n"; 1264 1265 if (m_textureType == TEXTURE_FLOAT) 1266 buf << "uniform highp sampler2D u_sampler;\n"; 1267 else if (m_textureType == TEXTURE_DEPTH) 1268 buf << "uniform highp sampler2DShadow u_sampler;\n"; 1269 else 1270 DE_ASSERT(DE_FALSE); 1271 1272 buf << "void main ()\n" 1273 "{\n"; 1274 1275 if (m_textureType == TEXTURE_FLOAT) 1276 buf << " v_out = vec4(textureLod(u_sampler, a_attr, 0.0).rg, 1.0, 1.0);\n"; 1277 else if (m_textureType == TEXTURE_DEPTH) 1278 buf << " highp float a1 = textureLod(u_sampler, vec3(a_attr, 0.0), 0.0);\n" 1279 " v_out = vec4(a1, (a1 > 1.0 || a1 < 0.0) ? (0.0) : (1.0), 1.0, 1.0);\n"; 1280 else 1281 DE_ASSERT(DE_FALSE); 1282 1283 buf << " gl_Position = a_pos;\n" 1284 "}\n"; 1285 return buf.str(); 1286} 1287 1288std::string TextureCase::genFragmentSource (void) const 1289{ 1290 // fragment shader is passthrough 1291 if (m_type == TYPE_VERTEX) 1292 return s_colorPassthroughFragmentShaderSource; 1293 1294 // fragment shader does the calculations 1295 std::ostringstream buf; 1296 buf << "#version 300 es\n" 1297 "layout(location = 0) out mediump vec4 fragColor;\n"; 1298 1299 if (m_textureType == TEXTURE_FLOAT) 1300 buf << "uniform highp sampler2D u_sampler;\n"; 1301 else if (m_textureType == TEXTURE_DEPTH) 1302 buf << "uniform highp sampler2DShadow u_sampler;\n"; 1303 else 1304 DE_ASSERT(DE_FALSE); 1305 1306 buf << "in highp vec4 v_attr;\n" 1307 "void main ()\n" 1308 "{\n"; 1309 1310 if (m_textureType == TEXTURE_FLOAT) 1311 buf << " highp vec2 a1 = texture(u_sampler, v_attr.xy).rg;\n" 1312 " fragColor = vec4(a1.x, a1.y, 1.0, 1.0);\n"; 1313 else if (m_textureType == TEXTURE_DEPTH) 1314 buf << " highp float a1 = texture(u_sampler, vec3(v_attr.xy, 0.0));\n" 1315 " fragColor = vec4(a1, (a1 > 1.0 || a1 < 0.0) ? (0.0) : (1.0), 1.0, 1.0);\n"; 1316 else 1317 DE_ASSERT(DE_FALSE); 1318 1319 buf << "}\n"; 1320 return buf.str(); 1321} 1322 1323/*--------------------------------------------------------------------*//*! 1324 * \brief Tests special floats as texture samping arguments 1325 * 1326 * Tests that special floats given as texture coordinates or LOD levels 1327 * to sampling functions do not return invalid values (values not in the 1328 * texture). Every texel's green component is 1.0. 1329 * 1330 * After the calculation test a test pattern is drawn to detect possible 1331 * texture sampling anomalies. 1332 *//*--------------------------------------------------------------------*/ 1333class TextureSamplerCase : public RenderCase 1334{ 1335public: 1336 enum ShaderType 1337 { 1338 TYPE_VERTEX = 0, 1339 TYPE_FRAGMENT, 1340 1341 TYPE_LAST 1342 }; 1343 enum TestType 1344 { 1345 TEST_TEX_COORD = 0, 1346 TEST_LOD, 1347 TEST_GRAD, 1348 TEST_TEX_COORD_CUBE, 1349 1350 TEST_LAST 1351 }; 1352 1353 TextureSamplerCase (Context& context, const char* name, const char* desc, ShaderType type, TestType testType); 1354 ~TextureSamplerCase (void); 1355 1356 void init (void); 1357 void deinit (void); 1358 IterateResult iterate (void); 1359 1360private: 1361 std::string genVertexSource (void) const; 1362 std::string genFragmentSource (void) const; 1363 1364 const ShaderType m_type; 1365 const TestType m_testType; 1366 GLuint m_textureID; 1367}; 1368 1369TextureSamplerCase::TextureSamplerCase (Context& context, const char* name, const char* desc, ShaderType type, TestType testType) 1370 : RenderCase (context, name, desc) 1371 , m_type (type) 1372 , m_testType (testType) 1373 , m_textureID (0) 1374{ 1375 DE_ASSERT(type < TYPE_LAST); 1376 DE_ASSERT(testType < TEST_LAST); 1377} 1378 1379TextureSamplerCase::~TextureSamplerCase (void) 1380{ 1381 deinit(); 1382} 1383 1384void TextureSamplerCase::init (void) 1385{ 1386 // requirements 1387 { 1388 GLint maxTextureSize = 0; 1389 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 1390 if (maxTextureSize < TEST_TEXTURE_SIZE) 1391 throw tcu::NotSupportedError(std::string("GL_MAX_TEXTURE_SIZE must be at least ") + de::toString(TEST_TEXTURE_SIZE)); 1392 } 1393 1394 RenderCase::init(); 1395 1396 // gen texture 1397 { 1398 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1399 std::vector<deUint8> texData (TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*4); 1400 de::Random rnd (12345); 1401 1402 gl.genTextures(1, &m_textureID); 1403 1404 for (int x = 0; x < TEST_TEXTURE_SIZE; ++x) 1405 for (int y = 0; y < TEST_TEXTURE_SIZE; ++y) 1406 { 1407 // RGBA8, green and alpha channel are always 255 for verification 1408 texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 0] = rnd.getUint32() & 0xFF; 1409 texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 1] = 0xFF; 1410 texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 2] = rnd.getUint32() & 0xFF; 1411 texData[(x * TEST_TEXTURE_SIZE + y) * 4 + 3] = 0xFF; 1412 } 1413 1414 if (m_testType == TEST_TEX_COORD) 1415 { 1416 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a 2D texture with a test pattern." << tcu::TestLog::EndMessage; 1417 1418 gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1419 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]); 1420 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1421 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1422 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init"); 1423 } 1424 else if (m_testType == TEST_LOD || m_testType == TEST_GRAD) 1425 { 1426 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a mipmapped 2D texture with a test pattern." << tcu::TestLog::EndMessage; 1427 1428 gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1429 1430 for (int level = 0; (TEST_TEXTURE_SIZE >> level); ++level) 1431 gl.texImage2D(GL_TEXTURE_2D, level, GL_RGBA8, TEST_TEXTURE_SIZE >> level, TEST_TEXTURE_SIZE >> level, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]); 1432 1433 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1434 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1435 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init"); 1436 } 1437 else if (m_testType == TEST_TEX_COORD_CUBE) 1438 { 1439 DE_STATIC_ASSERT(TEST_TEXTURE_CUBE_SIZE <= TEST_TEXTURE_SIZE); 1440 1441 static const GLenum faces[] = 1442 { 1443 GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1444 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1445 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 1446 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 1447 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 1448 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1449 }; 1450 1451 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a cube map with a test pattern." << tcu::TestLog::EndMessage; 1452 1453 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textureID); 1454 1455 for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); ++faceNdx) 1456 gl.texImage2D(faces[faceNdx], 0, GL_RGBA8, TEST_TEXTURE_CUBE_SIZE, TEST_TEXTURE_CUBE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData[0]); 1457 1458 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1459 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1460 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::init"); 1461 } 1462 else 1463 DE_ASSERT(DE_FALSE); 1464 } 1465} 1466 1467void TextureSamplerCase::deinit (void) 1468{ 1469 RenderCase::deinit(); 1470 1471 if (m_textureID) 1472 { 1473 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1474 1475 gl.deleteTextures(1, &m_textureID); 1476 m_textureID = 0; 1477 } 1478} 1479 1480TextureSamplerCase::IterateResult TextureSamplerCase::iterate (void) 1481{ 1482 // Draw a grid and texture it with a texture and sample it using special special values. The result samples should all have the green channel at 255 as per the test image. 1483 1484 std::vector<tcu::Vec4> gridVertices (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats)); 1485 std::vector<tcu::UVec2> gridTexCoords (DE_LENGTH_OF_ARRAY(s_specialFloats) * DE_LENGTH_OF_ARRAY(s_specialFloats)); 1486 std::vector<deUint16> indices ((DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) * 6); 1487 tcu::Surface resultImage (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1488 1489 // vertices 1490 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 1491 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 1492 { 1493 const float posX = (float)x / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) - 1] to [-1, 1] 1494 const float posY = (float)y / ((float)DE_LENGTH_OF_ARRAY(s_specialFloats) - 1.0f) * 2.0f - 1.0f; 1495 1496 gridVertices[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 1497 gridTexCoords[x * DE_LENGTH_OF_ARRAY(s_specialFloats) + y] = tcu::UVec2(s_specialFloats[x], s_specialFloats[y]); 1498 } 1499 1500 // tiles 1501 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++x) 1502 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) - 1; ++y) 1503 { 1504 const int baseNdx = (x * (DE_LENGTH_OF_ARRAY(s_specialFloats) - 1) + y) * 6; 1505 1506 indices[baseNdx + 0] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 1507 indices[baseNdx + 1] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 1508 indices[baseNdx + 2] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 1509 1510 indices[baseNdx + 3] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+0)); 1511 indices[baseNdx + 4] = (deUint16)((x+1) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 1512 indices[baseNdx + 5] = (deUint16)((x+0) * DE_LENGTH_OF_ARRAY(s_specialFloats) + (y+1)); 1513 } 1514 1515 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing a textured grid with the shader. Sampling from the texture using special floating point values." << tcu::TestLog::EndMessage; 1516 1517 // Draw grid 1518 { 1519 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1520 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 1521 const GLint texCoordLoc = gl.getAttribLocation(m_program->getProgram(), "a_attr"); 1522 const GLint samplerLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampler"); 1523 1524 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1525 gl.clear(GL_COLOR_BUFFER_BIT); 1526 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1527 gl.useProgram(m_program->getProgram()); 1528 1529 gl.uniform1i(samplerLoc, 0); 1530 if (m_testType != TEST_TEX_COORD_CUBE) 1531 gl.bindTexture(GL_TEXTURE_2D, m_textureID); 1532 else 1533 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textureID); 1534 1535 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 1536 gl.vertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, &gridTexCoords[0]); 1537 1538 gl.enableVertexAttribArray(positionLoc); 1539 gl.enableVertexAttribArray(texCoordLoc); 1540 gl.drawElements(GL_TRIANGLES, (glw::GLsizei)(indices.size()), GL_UNSIGNED_SHORT, &indices[0]); 1541 gl.disableVertexAttribArray(positionLoc); 1542 gl.disableVertexAttribArray(texCoordLoc); 1543 1544 gl.useProgram(0); 1545 gl.finish(); 1546 GLU_EXPECT_NO_ERROR(gl.getError(), "TextureSamplerCase::iterate"); 1547 1548 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 1549 } 1550 1551 // verify everywhere was drawn and samples were from the texture (all pixels have Green = 255) 1552 if (!checkResultImage(resultImage)) 1553 { 1554 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing or invalid fragments"); 1555 return STOP; 1556 } 1557 1558 // test drawing and textures still works 1559 if (!drawTestPattern(true)) 1560 { 1561 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "test pattern failed"); 1562 return STOP; 1563 } 1564 1565 // all ok 1566 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1567 return STOP; 1568} 1569 1570std::string TextureSamplerCase::genVertexSource (void) const 1571{ 1572 // vertex shader is passthrough, fragment does the calculations 1573 if (m_type == TYPE_FRAGMENT) 1574 return s_attrPassthroughVertexShaderSource; 1575 1576 // vertex shader does the calculations 1577 std::ostringstream buf; 1578 buf << "#version 300 es\n" 1579 "in highp vec4 a_pos;\n" 1580 "in highp vec2 a_attr;\n"; 1581 1582 if (m_testType != TEST_TEX_COORD_CUBE) 1583 buf << "uniform highp sampler2D u_sampler;\n"; 1584 else 1585 buf << "uniform highp samplerCube u_sampler;\n"; 1586 1587 buf << "out mediump vec4 v_out;\n" 1588 "void main ()\n" 1589 "{\n"; 1590 1591 if (m_testType == TEST_TEX_COORD) 1592 buf << " v_out = textureLod(u_sampler, a_attr, 0.0);\n"; 1593 else if (m_testType == TEST_LOD) 1594 buf << " v_out = textureLod(u_sampler, a_attr, a_attr.x);\n"; 1595 else if (m_testType == TEST_GRAD) 1596 buf << " v_out = textureGrad(u_sampler, a_attr, a_attr, a_attr.yx);\n"; 1597 else if (m_testType == TEST_TEX_COORD_CUBE) 1598 buf << " v_out = textureLod(u_sampler, vec3(a_attr, a_attr.x + a_attr.y), 0.0);\n"; 1599 else 1600 DE_ASSERT(DE_FALSE); 1601 1602 buf << "\n" 1603 " gl_Position = a_pos;\n" 1604 "}\n"; 1605 1606 return buf.str(); 1607} 1608 1609std::string TextureSamplerCase::genFragmentSource (void) const 1610{ 1611 // fragment shader is passthrough 1612 if (m_type == TYPE_VERTEX) 1613 return s_colorPassthroughFragmentShaderSource; 1614 1615 // fragment shader does the calculations 1616 std::ostringstream buf; 1617 buf << "#version 300 es\n" 1618 "layout(location = 0) out mediump vec4 fragColor;\n"; 1619 1620 if (m_testType != TEST_TEX_COORD_CUBE) 1621 buf << "uniform highp sampler2D u_sampler;\n"; 1622 else 1623 buf << "uniform highp samplerCube u_sampler;\n"; 1624 1625 buf << "in highp vec4 v_attr;\n" 1626 "void main ()\n" 1627 "{\n"; 1628 1629 if (m_testType == TEST_TEX_COORD) 1630 buf << " fragColor = texture(u_sampler, v_attr.xy);\n"; 1631 else if (m_testType == TEST_LOD) 1632 buf << " fragColor = texture(u_sampler, v_attr.xy, v_attr.x);\n"; 1633 else if (m_testType == TEST_GRAD) 1634 buf << " fragColor = textureGrad(u_sampler, v_attr.xy, v_attr.xy, v_attr.yx);\n"; 1635 else if (m_testType == TEST_TEX_COORD_CUBE) 1636 buf << " fragColor = texture(u_sampler, vec3(v_attr.xy,v_attr.x + v_attr.y));\n"; 1637 else 1638 DE_ASSERT(DE_FALSE); 1639 1640 buf << "}\n"; 1641 1642 return buf.str(); 1643} 1644 1645/*--------------------------------------------------------------------*//*! 1646 * \brief Tests special floats as fragment shader outputs 1647 * 1648 * Tests that outputting special floats from a fragment shader does not change 1649 * the normal floating point values of outputted from a fragment shader. Special 1650 * floats are outputted in the green component, normal floating point values 1651 * in the red and blue component. Potential changes are tested by rendering 1652 * test pattern two times with different floating point values. The resulting 1653 * images' red and blue channels should be equal. 1654 *//*--------------------------------------------------------------------*/ 1655class OutputCase : public FramebufferRenderCase 1656{ 1657public: 1658 OutputCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type); 1659 ~OutputCase (void); 1660 1661 void testFBO (void); 1662 1663private: 1664 std::string genVertexSource (void) const; 1665 std::string genFragmentSource (void) const; 1666}; 1667 1668OutputCase::OutputCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type) 1669 : FramebufferRenderCase (context, name, desc, type) 1670{ 1671} 1672 1673OutputCase::~OutputCase (void) 1674{ 1675 deinit(); 1676} 1677 1678void OutputCase::testFBO (void) 1679{ 1680 // Create a 1 X [s_specialFloats] grid of tiles (stripes). 1681 std::vector<tcu::Vec4> gridVertices ((DE_LENGTH_OF_ARRAY(s_specialFloats) + 1) * 2); 1682 std::vector<deUint16> indices (DE_LENGTH_OF_ARRAY(s_specialFloats) * 6); 1683 tcu::TextureFormat textureFormat (tcu::TextureFormat::RGBA, (m_fboType == FBO_RGBA_FLOAT16 || m_fboType == FBO_RGBA_FLOAT32) ? (tcu::TextureFormat::FLOAT) : (tcu::TextureFormat::UNORM_INT8)); 1684 tcu::TextureLevel specialImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1685 tcu::TextureLevel normalImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1686 1687 // vertices 1688 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++y) 1689 { 1690 const float posY = (float)y / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats) ] to [-1, 1] 1691 1692 gridVertices[y * 2 + 0] = tcu::Vec4(-1.0, posY, 0.0f, 1.0f); 1693 gridVertices[y * 2 + 1] = tcu::Vec4( 1.0, posY, 0.0f, 1.0f); 1694 } 1695 1696 // tiles 1697 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 1698 { 1699 const int baseNdx = y * 6; 1700 1701 indices[baseNdx + 0] = (deUint16)((y + 0) * 2); 1702 indices[baseNdx + 1] = (deUint16)((y + 1) * 2); 1703 indices[baseNdx + 2] = (deUint16)((y + 1) * 2 + 1); 1704 1705 indices[baseNdx + 3] = (deUint16)((y + 0) * 2); 1706 indices[baseNdx + 4] = (deUint16)((y + 1) * 2 + 1); 1707 indices[baseNdx + 5] = (deUint16)((y + 0) * 2 + 1); 1708 } 1709 1710 // Draw grids 1711 { 1712 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1713 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 1714 const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special"); 1715 1716 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1717 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1718 gl.useProgram(m_program->getProgram()); 1719 GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw"); 1720 1721 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 1722 gl.enableVertexAttribArray(positionLoc); 1723 1724 // draw 2 passes. Special and normal. 1725 for (int passNdx = 0; passNdx < 2; ++passNdx) 1726 { 1727 const bool specialPass = (passNdx == 0); 1728 1729 m_testCtx.getLog() << tcu::TestLog::Message << "Pass " << passNdx << ": Drawing stripes with the shader. Setting u_special for each stripe to (" << ((specialPass) ? ("special") : ("1.0")) << ")." << tcu::TestLog::EndMessage; 1730 1731 // draw stripes 1732 gl.clear(GL_COLOR_BUFFER_BIT); 1733 for (int y = 0; y < DE_LENGTH_OF_ARRAY(s_specialFloats); ++y) 1734 { 1735 const deUint32 one = 0x3F800000; 1736 const deUint32 special = s_specialFloats[y]; 1737 const deUint32 uniformValue = (specialPass) ? (special) : (one); 1738 const int indexIndex = y * 6; 1739 1740 gl.uniform1fv(specialLoc, 1, (const float*)&uniformValue); 1741 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]); 1742 } 1743 1744 gl.finish(); 1745 glu::readPixels(m_context.getRenderContext(), 0, 0, ((specialPass) ? (specialImage) : (normalImage)).getAccess()); 1746 } 1747 1748 gl.disableVertexAttribArray(positionLoc); 1749 gl.useProgram(0); 1750 GLU_EXPECT_NO_ERROR(gl.getError(), "OutputCase::iterate"); 1751 } 1752 1753 // Check results 1754 { 1755 tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1756 const tcu::RGBA badPixelColor = tcu::RGBA::red(); 1757 const tcu::RGBA okPixelColor = tcu::RGBA::green(); 1758 int badPixels = 0; 1759 1760 m_testCtx.getLog() << tcu::TestLog::Message << "Checking passes have identical red and blue channels and the green channel is correct in the constant pass." << tcu::TestLog::EndMessage; 1761 1762 for (int y = 0; y < specialImage.getHeight(); ++y) 1763 for (int x = 0; x < specialImage.getWidth(); ++x) 1764 { 1765 const float greenThreshold = 0.1f; 1766 const tcu::Vec4 cNormal = normalImage.getAccess().getPixel(x, y); 1767 const tcu::Vec4 cSpecial = specialImage.getAccess().getPixel(x, y); 1768 1769 if (cNormal.x() != cSpecial.x() || cNormal.z() != cSpecial.z() || cNormal.y() < 1.0f - greenThreshold) 1770 { 1771 ++badPixels; 1772 errorMask.setPixel(x, y, badPixelColor); 1773 } 1774 else 1775 errorMask.setPixel(x, y, okPixelColor); 1776 } 1777 1778 m_testCtx.getLog() << tcu::TestLog::Message << "Found " << badPixels << " invalid pixel(s)." << tcu::TestLog::EndMessage; 1779 1780 if (badPixels) 1781 { 1782 m_testCtx.getLog() 1783 << tcu::TestLog::ImageSet("Results", "Result verification") 1784 << tcu::TestLog::Image("Image with special green channel", "Image with special green channel", specialImage) 1785 << tcu::TestLog::Image("Image with constant green channel", "Image with constant green channel", normalImage) 1786 << tcu::TestLog::Image("Error Mask", "Error Mask", errorMask) 1787 << tcu::TestLog::EndImageSet; 1788 1789 // all ok? 1790 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 1791 } 1792 else 1793 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1794 } 1795} 1796 1797std::string OutputCase::genVertexSource (void) const 1798{ 1799 return 1800 "#version 300 es\n" 1801 "in highp vec4 a_pos;\n" 1802 "out highp vec2 v_pos;\n" 1803 "void main ()\n" 1804 "{\n" 1805 " gl_Position = a_pos;\n" 1806 " v_pos = a_pos.xy;\n" 1807 "}\n"; 1808} 1809 1810std::string OutputCase::genFragmentSource (void) const 1811{ 1812 return 1813 "#version 300 es\n" 1814 "layout(location = 0) out highp vec4 fragColor;\n" 1815 "uniform highp float u_special;\n" 1816 "in highp vec2 v_pos;\n" 1817 "void main ()\n" 1818 "{\n" 1819 " fragColor = vec4((v_pos.x + 1.0) * 0.5, u_special, (v_pos.y + 1.0) * 0.5, 1.0);\n" 1820 "}\n"; 1821} 1822 1823/*--------------------------------------------------------------------*//*! 1824 * \brief Tests special floats in blending 1825 * 1826 * Tests special floats as alpha and color components with various blending 1827 * modes. Test draws a test pattern and then does various blend operations 1828 * with special float values. After the blending test another test pattern 1829 * is drawn to detect possible blending anomalies. Test patterns should be 1830 * identical. 1831 *//*--------------------------------------------------------------------*/ 1832class BlendingCase : public FramebufferRenderCase 1833{ 1834public: 1835 BlendingCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type); 1836 ~BlendingCase (void); 1837 1838 void testFBO (void); 1839 1840private: 1841 void drawTestImage (tcu::PixelBufferAccess dst, GLuint uColorLoc, int maxVertexIndex); 1842 1843 std::string genVertexSource (void) const; 1844 std::string genFragmentSource (void) const; 1845}; 1846 1847BlendingCase::BlendingCase (Context& context, const char* name, const char* desc, FramebufferRenderCase::FrameBufferType type) 1848 : FramebufferRenderCase (context, name, desc, type) 1849{ 1850} 1851 1852BlendingCase::~BlendingCase (void) 1853{ 1854 deinit(); 1855} 1856 1857void BlendingCase::testFBO (void) 1858{ 1859 static const GLenum equations[] = 1860 { 1861 GL_FUNC_ADD, 1862 GL_FUNC_SUBTRACT, 1863 GL_FUNC_REVERSE_SUBTRACT, 1864 GL_MIN, 1865 GL_MAX 1866 }; 1867 static const GLenum functions[] = 1868 { 1869 GL_ZERO, 1870 GL_ONE, 1871 GL_SRC_COLOR, 1872 GL_ONE_MINUS_SRC_COLOR, 1873 GL_SRC_ALPHA, 1874 GL_ONE_MINUS_SRC_ALPHA, 1875 }; 1876 1877 // Create a [BlendFuncs] X [s_specialFloats] grid of tiles. ( BlendFuncs = equations x functions ) 1878 1879 const int numBlendFuncs = DE_LENGTH_OF_ARRAY(equations) * DE_LENGTH_OF_ARRAY(functions); 1880 std::vector<tcu::Vec4> gridVertices ((numBlendFuncs + 1) * (DE_LENGTH_OF_ARRAY(s_specialFloats) + 1)); 1881 std::vector<deUint16> indices (numBlendFuncs * DE_LENGTH_OF_ARRAY(s_specialFloats) * 6); 1882 tcu::TextureFormat textureFormat (tcu::TextureFormat::RGBA, (m_fboType == FBO_RGBA_FLOAT16 || m_fboType == FBO_RGBA_FLOAT32) ? (tcu::TextureFormat::FLOAT) : (tcu::TextureFormat::UNORM_INT8)); 1883 tcu::TextureLevel beforeImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1884 tcu::TextureLevel afterImage (textureFormat, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1885 1886 // vertices 1887 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats) + 1; ++x) 1888 for (int y = 0; y < numBlendFuncs + 1; ++y) 1889 { 1890 const float posX = (float)x / (float)DE_LENGTH_OF_ARRAY(s_specialFloats) * 2.0f - 1.0f; // map from [0, len(s_specialFloats)] to [-1, 1] 1891 const float posY = (float)y / (float)numBlendFuncs * 2.0f - 1.0f; 1892 1893 gridVertices[x * (numBlendFuncs + 1) + y] = tcu::Vec4(posX, posY, 0.0f, 1.0f); 1894 } 1895 1896 // tiles 1897 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 1898 for (int y = 0; y < numBlendFuncs; ++y) 1899 { 1900 const int baseNdx = (x * numBlendFuncs + y) * 6; 1901 1902 indices[baseNdx + 0] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+0)); 1903 indices[baseNdx + 1] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+1)); 1904 indices[baseNdx + 2] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+0)); 1905 1906 indices[baseNdx + 3] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+0)); 1907 indices[baseNdx + 4] = (deUint16)((x+1) * (numBlendFuncs + 1) + (y+1)); 1908 indices[baseNdx + 5] = (deUint16)((x+0) * (numBlendFuncs + 1) + (y+1)); 1909 } 1910 1911 // Draw tiles 1912 { 1913 const int numPasses = 5; 1914 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1915 const GLint positionLoc = gl.getAttribLocation(m_program->getProgram(), "a_pos"); 1916 const GLint specialLoc = gl.getUniformLocation(m_program->getProgram(), "u_special"); 1917 1918 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 1919 gl.clear(GL_COLOR_BUFFER_BIT); 1920 gl.viewport(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1921 gl.useProgram(m_program->getProgram()); 1922 gl.enable(GL_BLEND); 1923 GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw"); 1924 1925 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &gridVertices[0]); 1926 gl.enableVertexAttribArray(positionLoc); 1927 1928 // draw "before" image 1929 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing pre-draw pattern." << tcu::TestLog::EndMessage; 1930 drawTestImage(beforeImage.getAccess(), specialLoc, (int)gridVertices.size() - 1); 1931 GLU_EXPECT_NO_ERROR(gl.getError(), "pre-draw pattern"); 1932 1933 // draw multiple passes with special floats 1934 gl.clear(GL_COLOR_BUFFER_BIT); 1935 for (int passNdx = 0; passNdx < numPasses; ++passNdx) 1936 { 1937 de::Random rnd(123 + 567 * passNdx); 1938 1939 m_testCtx.getLog() 1940 << tcu::TestLog::Message 1941 << "Pass " << passNdx << ": Drawing tiles with the shader.\n" 1942 << "\tVarying u_special for each tile.\n" 1943 << "\tVarying blend function and blend equation for each tile.\n" 1944 << tcu::TestLog::EndMessage; 1945 1946 // draw tiles 1947 for (int x = 0; x < DE_LENGTH_OF_ARRAY(s_specialFloats); ++x) 1948 for (int y = 0; y < numBlendFuncs; ++y) 1949 { 1950 const GLenum blendEquation = equations[y % DE_LENGTH_OF_ARRAY(equations)]; 1951 const GLenum blendFunction = functions[y / DE_LENGTH_OF_ARRAY(equations)]; 1952 const GLenum blendFunctionDst = rnd.choose<GLenum>(DE_ARRAY_BEGIN(functions), DE_ARRAY_END(functions)); 1953 const int indexIndex = (x * numBlendFuncs + y) * 6; 1954 1955 // "rnd.get"s are run in a deterministic order 1956 const deUint32 componentR = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1957 const deUint32 componentG = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1958 const deUint32 componentB = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1959 const deUint32 componentA = rnd.choose<deUint32>(DE_ARRAY_BEGIN(s_specialFloats), DE_ARRAY_END(s_specialFloats)); 1960 const tcu::UVec4 uniformValue = tcu::UVec4(componentR, componentG, componentB, componentA); 1961 1962 gl.uniform4fv(specialLoc, 1, (const float*)uniformValue.getPtr()); 1963 gl.blendEquation(blendEquation); 1964 gl.blendFunc(blendFunction, blendFunctionDst); 1965 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[indexIndex]); 1966 } 1967 } 1968 GLU_EXPECT_NO_ERROR(gl.getError(), "special passes"); 1969 1970 // draw "after" image 1971 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing post-draw pattern." << tcu::TestLog::EndMessage; 1972 drawTestImage(afterImage.getAccess(), specialLoc, (int)gridVertices.size() - 1); 1973 GLU_EXPECT_NO_ERROR(gl.getError(), "post-draw pattern"); 1974 1975 gl.disableVertexAttribArray(positionLoc); 1976 gl.useProgram(0); 1977 GLU_EXPECT_NO_ERROR(gl.getError(), "OutputCase::iterate"); 1978 } 1979 1980 // Check results 1981 { 1982 tcu::Surface errorMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1983 const tcu::RGBA badPixelColor = tcu::RGBA::red(); 1984 const tcu::RGBA okPixelColor = tcu::RGBA::green(); 1985 int badPixels = 0; 1986 1987 m_testCtx.getLog() << tcu::TestLog::Message << "Checking patterns are identical." << tcu::TestLog::EndMessage; 1988 1989 for (int y = 0; y < beforeImage.getHeight(); ++y) 1990 for (int x = 0; x < beforeImage.getWidth(); ++x) 1991 { 1992 const tcu::Vec4 cBefore = beforeImage.getAccess().getPixel(x, y); 1993 const tcu::Vec4 cAfter = afterImage.getAccess().getPixel(x, y); 1994 1995 if (cBefore != cAfter) 1996 { 1997 ++badPixels; 1998 errorMask.setPixel(x, y, badPixelColor); 1999 } 2000 else 2001 errorMask.setPixel(x, y, okPixelColor); 2002 } 2003 2004 m_testCtx.getLog() << tcu::TestLog::Message << "Found " << badPixels << " invalid pixel(s)." << tcu::TestLog::EndMessage; 2005 2006 if (badPixels) 2007 { 2008 m_testCtx.getLog() 2009 << tcu::TestLog::ImageSet("Results", "Result verification") 2010 << tcu::TestLog::Image("Pattern drawn before special float blending", "Pattern drawn before special float blending", beforeImage) 2011 << tcu::TestLog::Image("Pattern drawn after special float blending", "Pattern drawn after special float blending", afterImage) 2012 << tcu::TestLog::EndImageSet; 2013 2014 // all ok? 2015 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 2016 } 2017 else 2018 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2019 } 2020} 2021 2022void BlendingCase::drawTestImage (tcu::PixelBufferAccess dst, GLuint uColorLoc, int maxVertexIndex) 2023{ 2024 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2025 de::Random rnd (123); 2026 2027 gl.clear(GL_COLOR_BUFFER_BIT); 2028 gl.blendEquation(GL_FUNC_ADD); 2029 gl.blendFunc(GL_ONE, GL_ONE); 2030 2031 for (int tri = 0; tri < 20; ++tri) 2032 { 2033 tcu::Vec4 color; 2034 color.x() = rnd.getFloat(); 2035 color.y() = rnd.getFloat(); 2036 color.z() = rnd.getFloat(); 2037 color.w() = rnd.getFloat(); 2038 gl.uniform4fv(uColorLoc, 1, color.getPtr()); 2039 2040 deUint16 indices[3]; 2041 indices[0] = (deUint16)rnd.getInt(0, maxVertexIndex); 2042 indices[1] = (deUint16)rnd.getInt(0, maxVertexIndex); 2043 indices[2] = (deUint16)rnd.getInt(0, maxVertexIndex); 2044 2045 gl.drawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices); 2046 } 2047 2048 gl.finish(); 2049 glu::readPixels(m_context.getRenderContext(), 0, 0, dst); 2050} 2051 2052std::string BlendingCase::genVertexSource (void) const 2053{ 2054 return 2055 "#version 300 es\n" 2056 "in highp vec4 a_pos;\n" 2057 "void main ()\n" 2058 "{\n" 2059 " gl_Position = a_pos;\n" 2060 "}\n"; 2061} 2062 2063std::string BlendingCase::genFragmentSource (void) const 2064{ 2065 return 2066 "#version 300 es\n" 2067 "layout(location = 0) out highp vec4 fragColor;\n" 2068 "uniform highp vec4 u_special;\n" 2069 "void main ()\n" 2070 "{\n" 2071 " fragColor = u_special;\n" 2072 "}\n"; 2073} 2074 2075} //anonymous 2076 2077SpecialFloatTests::SpecialFloatTests (Context& context) 2078 : TestCaseGroup(context, "special_float", "Special float tests") 2079{ 2080} 2081 2082SpecialFloatTests::~SpecialFloatTests (void) 2083{ 2084} 2085 2086void SpecialFloatTests::init (void) 2087{ 2088 tcu::TestCaseGroup* const vertexGroup = new tcu::TestCaseGroup(m_testCtx, "vertex", "Run vertex shader with special float values"); 2089 tcu::TestCaseGroup* const fragmentGroup = new tcu::TestCaseGroup(m_testCtx, "fragment", "Run fragment shader with special float values"); 2090 tcu::TestCaseGroup* const framebufferGroup = new tcu::TestCaseGroup(m_testCtx, "framebuffer", "Test framebuffers containing special float values"); 2091 2092 // .vertex 2093 { 2094 vertexGroup->addChild(new VertexAttributeCase (m_context, "attribute_buffer", "special attribute values in a buffer", VertexAttributeCase::STORAGE_BUFFER, VertexAttributeCase::TYPE_VERTEX)); 2095 vertexGroup->addChild(new VertexAttributeCase (m_context, "attribute_client", "special attribute values in a client storage", VertexAttributeCase::STORAGE_CLIENT, VertexAttributeCase::TYPE_VERTEX)); 2096 vertexGroup->addChild(new UniformCase (m_context, "uniform", "special uniform values", UniformCase::TYPE_VERTEX)); 2097 vertexGroup->addChild(new TextureCase (m_context, "texture", "texture with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_CLIENT)); 2098 vertexGroup->addChild(new TextureCase (m_context, "texture_pbo", "texture (via pbo) with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_PBO)); 2099 vertexGroup->addChild(new TextureCase (m_context, "texture_shadow", "shadow texture with special floating point values", TextureCase::TYPE_VERTEX, TextureCase::TEXTURE_DEPTH, TextureCase::UPLOAD_CLIENT)); 2100 vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord", "special texture coords", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_TEX_COORD)); 2101 vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord_cube", "special texture coords to cubemap", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_TEX_COORD_CUBE)); 2102 vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_lod", "special texture lod", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_LOD)); 2103 vertexGroup->addChild(new TextureSamplerCase (m_context, "sampler_grad", "special texture grad", TextureSamplerCase::TYPE_VERTEX, TextureSamplerCase::TEST_GRAD)); 2104 2105 addChild(vertexGroup); 2106 } 2107 2108 // .fragment 2109 { 2110 fragmentGroup->addChild(new VertexAttributeCase (m_context, "attribute_buffer", "special attribute values in a buffer", VertexAttributeCase::STORAGE_BUFFER, VertexAttributeCase::TYPE_FRAGMENT)); 2111 fragmentGroup->addChild(new VertexAttributeCase (m_context, "attribute_client", "special attribute values in a client storage", VertexAttributeCase::STORAGE_CLIENT, VertexAttributeCase::TYPE_FRAGMENT)); 2112 fragmentGroup->addChild(new UniformCase (m_context, "uniform", "special uniform values", UniformCase::TYPE_FRAGMENT)); 2113 fragmentGroup->addChild(new TextureCase (m_context, "texture", "texture with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_CLIENT)); 2114 fragmentGroup->addChild(new TextureCase (m_context, "texture_pbo", "texture (via pbo) with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_FLOAT, TextureCase::UPLOAD_PBO)); 2115 fragmentGroup->addChild(new TextureCase (m_context, "texture_shadow", "shadow texture with special floating point values", TextureCase::TYPE_FRAGMENT, TextureCase::TEXTURE_DEPTH, TextureCase::UPLOAD_CLIENT)); 2116 fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord", "special texture coords", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_TEX_COORD)); 2117 fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_tex_coord_cube", "special texture coords to cubemap", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_TEX_COORD_CUBE)); 2118 fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_lod", "special texture lod", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_LOD)); 2119 fragmentGroup->addChild(new TextureSamplerCase (m_context, "sampler_grad", "special texture grad", TextureSamplerCase::TYPE_FRAGMENT, TextureSamplerCase::TEST_GRAD)); 2120 2121 addChild(fragmentGroup); 2122 } 2123 2124 // .framebuffer 2125 { 2126 framebufferGroup->addChild(new OutputCase (m_context, "write_default", "write special floating point values to default framebuffer", FramebufferRenderCase::FBO_DEFAULT)); 2127 framebufferGroup->addChild(new OutputCase (m_context, "write_rgba4", "write special floating point values to RGBA4 framebuffer", FramebufferRenderCase::FBO_RGBA4)); 2128 framebufferGroup->addChild(new OutputCase (m_context, "write_rgb5_a1", "write special floating point values to RGB5_A1 framebuffer", FramebufferRenderCase::FBO_RGB5_A1)); 2129 framebufferGroup->addChild(new OutputCase (m_context, "write_rgb565", "write special floating point values to RGB565 framebuffer", FramebufferRenderCase::FBO_RGB565)); 2130 framebufferGroup->addChild(new OutputCase (m_context, "write_rgba8", "write special floating point values to RGBA8 framebuffer", FramebufferRenderCase::FBO_RGBA8)); 2131 framebufferGroup->addChild(new OutputCase (m_context, "write_rgb10_a2", "write special floating point values to RGB10_A2 framebuffer", FramebufferRenderCase::FBO_RGB10_A2)); 2132 framebufferGroup->addChild(new OutputCase (m_context, "write_float16", "write special floating point values to float16 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT16)); 2133 framebufferGroup->addChild(new OutputCase (m_context, "write_float32", "write special floating point values to float32 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT32)); 2134 2135 framebufferGroup->addChild(new BlendingCase (m_context, "blend_default", "blend special floating point values in a default framebuffer", FramebufferRenderCase::FBO_DEFAULT)); 2136 framebufferGroup->addChild(new BlendingCase (m_context, "blend_rgba8", "blend special floating point values in a RGBA8 framebuffer", FramebufferRenderCase::FBO_RGBA8)); 2137 framebufferGroup->addChild(new BlendingCase (m_context, "blend_float16", "blend special floating point values in a float16 framebuffer", FramebufferRenderCase::FBO_RGBA_FLOAT16)); 2138 2139 addChild(framebufferGroup); 2140 } 2141} 2142 2143} // Stress 2144} // gles3 2145} // deqp 2146