1/*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-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#include "glcShaderMultisampleInterpolationTests.hpp" 25#include "deMath.h" 26#include "deRandom.hpp" 27#include "deStringUtil.hpp" 28#include "gluContextInfo.hpp" 29#include "gluDrawUtil.hpp" 30#include "gluPixelTransfer.hpp" 31#include "gluShaderProgram.hpp" 32#include "glw.h" 33#include "glwFunctions.hpp" 34#include "tcuCommandLine.hpp" 35#include "tcuStringTemplate.hpp" 36#include "tcuSurface.hpp" 37#include "tcuTestLog.hpp" 38 39namespace tcu 40{ 41static bool operator<(tcu::Vec4 const& k1, tcu::Vec4 const& k2) 42{ 43 if (k1.y() < k2.y()) 44 { 45 return true; 46 } 47 else if (k1.y() == k2.y()) 48 { 49 return k1.x() < k2.x(); 50 } 51 else 52 { 53 return false; 54 } 55} 56} 57 58namespace deqp 59{ 60 61using tcu::TestLog; 62using std::string; 63using std::vector; 64 65static std::string specializeVersion(std::string const& source, glu::GLSLVersion version, 66 std::string const& sampler = "", std::string const& outType = "", 67 std::string const& qualifier = "", std::string const& assignment = "", 68 std::string const& condition = "") 69{ 70 DE_ASSERT(version == glu::GLSL_VERSION_310_ES || version >= glu::GLSL_VERSION_440); 71 std::map<std::string, std::string> args; 72 args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(version); 73 args["SAMPLER"] = sampler; 74 args["OUT_TYPE"] = outType; 75 args["QUALIFIER"] = qualifier; 76 args["ASSIGNMENT"] = assignment; 77 args["CONDITION"] = condition; 78 if (version == glu::GLSL_VERSION_310_ES) 79 { 80 args["OES_SMI_EN"] = "#extension GL_OES_shader_multisample_interpolation : enable\n"; 81 args["OES_SMI_RQ"] = "#extension GL_OES_shader_multisample_interpolation : require\n"; 82 args["OES_SMI_CH"] = "#if !GL_OES_shader_multisample_interpolation\n" 83 " this is broken\n" 84 "#endif\n"; 85 args["OES_SV_EN"] = "#extension GL_OES_sample_variables : enable\n"; 86 } 87 else 88 { 89 args["OES_SMI_EN"] = ""; 90 args["OES_SMI_RQ"] = ""; 91 args["OES_SMI_CH"] = ""; 92 args["OES_SV_EN"] = ""; 93 } 94 return tcu::StringTemplate(source.c_str()).specialize(args); 95} 96 97class ShaderMultisampleInterpolationApiCase : public TestCase 98{ 99public: 100 ShaderMultisampleInterpolationApiCase(Context& context, const char* name, const char* description, 101 glu::GLSLVersion glslVersion); 102 ~ShaderMultisampleInterpolationApiCase(); 103 104 IterateResult iterate(); 105 106protected: 107 glu::GLSLVersion m_glslVersion; 108}; 109 110ShaderMultisampleInterpolationApiCase::ShaderMultisampleInterpolationApiCase(Context& context, const char* name, 111 const char* description, 112 glu::GLSLVersion glslVersion) 113 : TestCase(context, name, description), m_glslVersion(glslVersion) 114{ 115 DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440); 116} 117 118ShaderMultisampleInterpolationApiCase::~ShaderMultisampleInterpolationApiCase() 119{ 120} 121 122ShaderMultisampleInterpolationApiCase::IterateResult ShaderMultisampleInterpolationApiCase::iterate() 123{ 124 TestLog& log = m_testCtx.getLog(); 125 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 126 bool isOk = true; 127 128 if (m_glslVersion == glu::GLSL_VERSION_310_ES && 129 !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 130 { 131 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_shader_multisample_interpolation"); 132 return STOP; 133 } 134 135 static char const* vss = "${VERSION_DECL}\n" 136 "${OES_SMI_RQ}" 137 "in highp vec4 a_position;\n" 138 "in highp vec4 a_color;\n" 139 "sample out highp vec4 v_color;\n" 140 "void main()\n" 141 "{\n" 142 " gl_Position = a_position;\n" 143 "}\n"; 144 145 { 146 static char const* fss = "${VERSION_DECL}\n" 147 "${OES_SMI_RQ}" 148 "sample in highp vec4 v_color;\n" 149 "out highp vec4 o_color;\n" 150 "void main()\n" 151 "{\n" 152 " o_color = v_color;\n" 153 "}\n"; 154 155 glu::ShaderProgram program(m_context.getRenderContext(), 156 glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(), 157 specializeVersion(fss, m_glslVersion).c_str())); 158 log << program; 159 if (!program.isOk()) 160 { 161 TCU_FAIL("Compile failed"); 162 } 163 } 164 165 { 166 static char const* fss = "${VERSION_DECL}\n" 167 "${OES_SMI_EN}" 168 "sample in highp vec4 v_color;\n" 169 "out highp vec4 o_color;\n" 170 "void main()\n" 171 "{\n" 172 "${OES_SMI_CH}" 173 " o_color = v_color;\n" 174 "}\n"; 175 176 glu::ShaderProgram program(m_context.getRenderContext(), 177 glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(), 178 specializeVersion(fss, m_glslVersion).c_str())); 179 log << program; 180 if (!program.isOk()) 181 { 182 TCU_FAIL("Compile failed"); 183 } 184 } 185 186 GLfloat minFragmentInterpolationOffset = 0.0f; 187 gl.getFloatv(GL_MIN_FRAGMENT_INTERPOLATION_OFFSET, &minFragmentInterpolationOffset); 188 if (minFragmentInterpolationOffset > -0.5f) 189 { 190 isOk = false; 191 } 192 193 GLint fragmentInterpolationOffsetBits = 0; 194 gl.getIntegerv(GL_FRAGMENT_INTERPOLATION_OFFSET_BITS, &fragmentInterpolationOffsetBits); 195 if (fragmentInterpolationOffsetBits < 4) 196 { 197 isOk = false; 198 } 199 GLfloat ULP = 1.0f / powf(2, static_cast<float>(fragmentInterpolationOffsetBits)); 200 201 GLfloat maxFragmentInterpolationOffset = 0.0f; 202 gl.getFloatv(GL_MAX_FRAGMENT_INTERPOLATION_OFFSET, &maxFragmentInterpolationOffset); 203 if (maxFragmentInterpolationOffset < 0.5f - ULP) 204 { 205 isOk = false; 206 } 207 208 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail"); 209 return STOP; 210} 211 212class ShaderMultisampleInterpolationBaseCase : public TestCase 213{ 214public: 215 ShaderMultisampleInterpolationBaseCase(Context& context, const char* name, const char* description, 216 glu::GLSLVersion glslVersion, char const* qualifier, char const* assignment, 217 char const* condition, bool unique, GLenum internalFormat, 218 tcu::TextureFormat const& texFormat, const char* m_sampler, 219 const char* m_outType, GLfloat min, GLfloat max, GLint samples); 220 ~ShaderMultisampleInterpolationBaseCase(); 221 222 IterateResult iterate(); 223 224protected: 225 glu::GLSLVersion m_glslVersion; 226 std::string m_qualifier; 227 std::string m_assignment; 228 std::string m_condition; 229 bool m_unique; 230 GLenum m_internalFormat; 231 tcu::TextureFormat m_texFormat; 232 std::string m_sampler; 233 std::string m_outType; 234 GLfloat m_min; 235 GLfloat m_max; 236 GLint m_samples; 237 238 enum 239 { 240 WIDTH = 8, 241 HEIGHT = 8, 242 }; 243 244 int countUniquePixels(tcu::ConstPixelBufferAccess const& pixels); 245 int countUniquePixels(const std::vector<tcu::Vec4>& pixels); 246}; 247 248ShaderMultisampleInterpolationBaseCase::ShaderMultisampleInterpolationBaseCase( 249 Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion, char const* qualifier, 250 char const* assignment, char const* condition, bool unique, GLenum internalFormat, 251 tcu::TextureFormat const& texFormat, const char* sampler, const char* outType, GLfloat min, GLfloat max, 252 GLint samples) 253 : TestCase(context, name, description) 254 , m_glslVersion(glslVersion) 255 , m_qualifier(qualifier) 256 , m_assignment(assignment) 257 , m_condition(condition) 258 , m_unique(unique) 259 , m_internalFormat(internalFormat) 260 , m_texFormat(texFormat) 261 , m_sampler(sampler) 262 , m_outType(outType) 263 , m_min(min) 264 , m_max(max) 265 , m_samples(samples) 266{ 267 DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_440); 268} 269 270ShaderMultisampleInterpolationBaseCase::~ShaderMultisampleInterpolationBaseCase() 271{ 272} 273 274ShaderMultisampleInterpolationBaseCase::IterateResult ShaderMultisampleInterpolationBaseCase::iterate() 275{ 276 TestLog& log = m_testCtx.getLog(); 277 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 278 bool isOk = true; 279 bool supportsRgba32f = false; 280 281 if (m_glslVersion == glu::GLSL_VERSION_310_ES && 282 !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 283 { 284 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_shader_multisample_interpolation"); 285 return STOP; 286 } 287 288 supportsRgba32f = isContextTypeGLCore(m_context.getRenderContext().getType()) ? 289 true : 290 (m_context.getContextInfo().isExtensionSupported("GL_EXT_color_buffer_float") || 291 m_context.getContextInfo().isExtensionSupported("GL_ARB_color_buffer_float")); 292 293 if (m_internalFormat == GL_RGBA32F && !supportsRgba32f) 294 { 295 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Internalformat rgba32f not supported"); 296 return STOP; 297 } 298 299 GLint maxSamples; 300 if (((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)) || 301 ((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RG)) || 302 ((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::R)) || 303 ((m_texFormat.type == tcu::TextureFormat::HALF_FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA))) 304 { 305 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, m_internalFormat, GL_SAMPLES, 1, &maxSamples); 306 if (m_samples > maxSamples) 307 { 308 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, 309 "Test sample count greater than samples that the format supports"); 310 return STOP; 311 } 312 } 313 else if (m_texFormat.type == tcu::TextureFormat::SIGNED_INT8 || 314 m_texFormat.type == tcu::TextureFormat::UNSIGNED_INT8) 315 { 316 gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &maxSamples); 317 if (m_samples > maxSamples) 318 { 319 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count greater than MAX_INTEGER_SAMPLES"); 320 return STOP; 321 } 322 } 323 else 324 { 325 gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples); 326 if (m_samples > maxSamples) 327 { 328 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count greater than MAX_SAMPLES"); 329 return STOP; 330 } 331 } 332 333 // Create a multisample texture, or a regular texture if samples is zero. 334 GLuint tex; 335 gl.genTextures(1, &tex); 336 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex); 337 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, m_internalFormat, WIDTH, HEIGHT, GL_FALSE); 338 339 // Create a framebuffer with the texture attached. 340 GLuint fboMs; 341 gl.genFramebuffers(1, &fboMs); 342 gl.bindFramebuffer(GL_FRAMEBUFFER, fboMs); 343 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0); 344 gl.viewport(0, 0, WIDTH, HEIGHT); 345 346 static deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 }; 347 348 { 349 // Draw with one of the fragment input qualifiers and with one of the 350 // interpolate functions. Cross-check the result in the shader and 351 // output the final interpolated value. 352 353 static char const* vss = "${VERSION_DECL}\n" 354 "${OES_SMI_RQ}" 355 "layout(location = 0) in highp vec2 a_position;\n" 356 "layout(location = 1) in highp vec4 a_color;\n" 357 "out highp vec4 v_colorBase;\n" 358 "${QUALIFIER} out highp vec4 v_color;\n" 359 "void main()\n" 360 "{\n" 361 " v_colorBase = a_color;\n" 362 " v_color = a_color;\n" 363 " gl_Position = vec4(a_position, 0.0, 1.0);\n" 364 "}\n"; 365 366 static char const* fss = "${VERSION_DECL}\n" 367 "${OES_SMI_RQ}" 368 "${OES_SV_EN}" 369 "in highp vec4 v_colorBase;\n" 370 "${QUALIFIER} in highp vec4 v_color;\n" 371 "layout(location = 0) out highp ${OUT_TYPE} o_color;\n" 372 "void main()\n" 373 "{\n" 374 " highp vec4 temp = ${ASSIGNMENT};\n" 375 " bool condition = ${CONDITION};\n" 376 " o_color = ${OUT_TYPE}(temp.x, temp.y, condition, 1);\n" 377 "}\n"; 378 379 glu::ShaderProgram program( 380 m_context.getRenderContext(), 381 glu::makeVtxFragSources( 382 specializeVersion(vss, m_glslVersion, m_sampler, m_outType, m_qualifier, m_assignment, m_condition) 383 .c_str(), 384 specializeVersion(fss, m_glslVersion, m_sampler, m_outType, m_qualifier, m_assignment, m_condition) 385 .c_str())); 386 log << program; 387 if (!program.isOk()) 388 { 389 TCU_FAIL("Compile failed"); 390 } 391 392 static float const position[] = { 393 -1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f, 394 }; 395 396 const float color[] = { 397 m_min, m_min, 0.0f, 1.0f, m_min, m_max, 0.0f, 1.0f, m_max, m_min, 0.0f, 1.0f, m_max, m_max, 0.0f, 1.0f, 398 }; 399 400 gl.useProgram(program.getProgram()); 401 402 glu::VertexArrayBinding vertexArrays[] = { 403 glu::va::Float("a_position", 2, 4, 0, &position[0]), glu::va::Float("a_color", 4, 4, 0, &color[0]), 404 }; 405 glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), 406 &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); 407 408 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad"); 409 } 410 411 gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer()); 412 gl.deleteFramebuffers(1, &fboMs); 413 414 GLsizei width = WIDTH * m_samples; 415 416 GLuint rbo; 417 gl.genRenderbuffers(1, &rbo); 418 gl.bindRenderbuffer(GL_RENDERBUFFER, rbo); 419 gl.renderbufferStorage(GL_RENDERBUFFER, m_internalFormat, width, HEIGHT); 420 421 GLuint fbo; 422 gl.genFramebuffers(1, &fbo); 423 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); 424 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); 425 gl.viewport(0, 0, width, HEIGHT); 426 427 { 428 // Resolve the mutli-sample texture into a render-buffer sized such that 429 // the width can hold all samples of a pixel. 430 431 static char const* vss = "${VERSION_DECL}\n" 432 "in highp vec2 a_position;\n" 433 "void main(void)\n" 434 "{\n" 435 " gl_Position = vec4(a_position, 0.0, 1.0);\n" 436 "}\n"; 437 438 static char const* fss = "${VERSION_DECL}\n" 439 "uniform highp ${SAMPLER}MS u_texMS;\n" 440 "uniform int u_samples;\n" 441 "layout(location = 0) out highp ${OUT_TYPE} o_color;\n" 442 "void main(void)\n" 443 "{\n" 444 " ivec2 coord = ivec2(int(gl_FragCoord.x) / u_samples, gl_FragCoord.y);\n" 445 " int sampleId = int(gl_FragCoord.x) % u_samples;\n" 446 " o_color = texelFetch(u_texMS, coord, sampleId);\n" 447 "}\n"; 448 449 glu::ShaderProgram program( 450 m_context.getRenderContext(), 451 glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion, m_sampler, m_outType).c_str(), 452 specializeVersion(fss, m_glslVersion, m_sampler, m_outType).c_str())); 453 log << program; 454 if (!program.isOk()) 455 { 456 TCU_FAIL("Compile failed"); 457 } 458 459 static float const position[] = { 460 -1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f, 461 }; 462 463 gl.useProgram(program.getProgram()); 464 gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_samples"), m_samples); 465 gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_texMS"), 0); 466 467 glu::VertexArrayBinding vertexArrays[] = { 468 glu::va::Float("a_position", 2, 4, 0, &position[0]), 469 }; 470 glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), 471 &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0])); 472 473 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad"); 474 } 475 476 // Verify the results. 477 tcu::TextureLevel results(m_texFormat, width, HEIGHT); 478 tcu::PixelBufferAccess pixels = results.getAccess(); 479 std::vector<tcu::Vec4> result(pixels.getHeight() * pixels.getWidth()); 480 int uniquePixels; 481 482 if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8) 483 { 484 std::vector<GLint> data(pixels.getHeight() * pixels.getWidth() * 4); 485 gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_INT, &data[0]); 486 for (unsigned int i = 0; i < data.size(); i += 4) 487 { 488 result[i / 4] = 489 tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]); 490 } 491 uniquePixels = countUniquePixels(result); 492 } 493 else if (pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8) 494 { 495 std::vector<GLuint> data(pixels.getHeight() * pixels.getWidth() * 4); 496 gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data[0]); 497 for (unsigned int i = 0; i < data.size(); i += 4) 498 { 499 result[i / 4] = 500 tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]); 501 } 502 uniquePixels = countUniquePixels(result); 503 } 504 else 505 { 506 glu::readPixels(m_context.getRenderContext(), 0, 0, pixels); 507 uniquePixels = countUniquePixels(pixels); 508 } 509 510 int expectedUnique = WIDTH * HEIGHT * ((m_unique) ? m_samples : 1); 511 if (uniquePixels < expectedUnique) 512 { 513 // There are duplicate pixel values meaning interpolation didn't work as expected. 514 isOk = false; 515 } 516 for (int y = 0; y < pixels.getHeight(); ++y) 517 { 518 for (int x = 0; x < pixels.getWidth(); ++x) 519 { 520 tcu::Vec4 pixel; 521 if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8 || 522 pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8) 523 { 524 pixel = result[y * WIDTH + x]; 525 } 526 else 527 { 528 pixel = pixels.getPixel(x, y); 529 } 530 if (pixel.z() != 1) 531 { 532 // The ${CONDITION} check in the shader failed. 533 isOk = false; 534 } 535 } 536 } 537 538 gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer()); 539 gl.deleteFramebuffers(1, &fbo); 540 541 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 542 gl.deleteRenderbuffers(1, &rbo); 543 544 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); 545 gl.deleteTextures(1, &tex); 546 547 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail"); 548 return STOP; 549} 550 551int ShaderMultisampleInterpolationBaseCase::countUniquePixels(tcu::ConstPixelBufferAccess const& pixels) 552{ 553 std::set<tcu::Vec4> uniquePixels; 554 555 for (int y = 0; y < pixels.getHeight(); ++y) 556 { 557 for (int x = 0; x < pixels.getWidth(); ++x) 558 { 559 uniquePixels.insert(pixels.getPixel(x, y)); 560 } 561 } 562 563 return (int)uniquePixels.size(); 564} 565 566int ShaderMultisampleInterpolationBaseCase::countUniquePixels(const std::vector<tcu::Vec4>& pixels) 567{ 568 std::set<tcu::Vec4> uniquePixels; 569 570 for (unsigned int i = 0; i < pixels.size(); ++i) 571 { 572 uniquePixels.insert(pixels[i]); 573 } 574 575 return (int)uniquePixels.size(); 576} 577 578ShaderMultisampleInterpolationTests::ShaderMultisampleInterpolationTests(Context& context, glu::GLSLVersion glslVersion) 579 : TestCaseGroup(context, "shader_multisample_interpolation", "Shader Multisample Interpolation tests") 580 , m_glslVersion(glslVersion) 581{ 582} 583 584ShaderMultisampleInterpolationTests::~ShaderMultisampleInterpolationTests() 585{ 586} 587 588void ShaderMultisampleInterpolationTests::init() 589{ 590 struct Sample 591 { 592 char const* name; 593 GLint samples; 594 } samples[] = { 595 { "samples_1", 1 }, { "samples_2", 2 }, { "samples_4", 4 }, 596 }; 597 598 // shader_multisample_interpolation.api 599 tcu::TestCaseGroup* apiGroup = new tcu::TestCaseGroup(m_testCtx, "api", "API verification"); 600 apiGroup->addChild(new ShaderMultisampleInterpolationApiCase(m_context, "api", "API verification", m_glslVersion)); 601 addChild(apiGroup); 602 603 struct Case 604 { 605 char const* name; 606 char const* qualifier; 607 char const* assignment; 608 char const* condition; 609 bool unique; 610 } cases[] = { 611 { "base", "", "v_color", "true", false }, 612 { "sample", "sample", "v_color", "true", true }, 613 { "centroid", "centroid", "v_color", "true", false }, 614 { "interpolate_at_sample", "", "interpolateAtSample(v_colorBase, gl_SampleID)", "true", true }, 615 { "interpolate_at_sample_check", "sample", "interpolateAtSample(v_colorBase, gl_SampleID)", "temp == v_color", 616 true }, 617 { "interpolate_at_centroid", "", "interpolateAtCentroid(v_colorBase)", "true", false }, 618 { "interpolate_at_centroid_check", "centroid", "interpolateAtCentroid(v_colorBase)", "temp == v_color", false }, 619 { "interpolate_at_offset", "", "interpolateAtOffset(v_colorBase, gl_SamplePosition - 0.5)", "true", true }, 620 { "interpolate_at_offset_check", "sample", "interpolateAtOffset(v_colorBase, gl_SamplePosition - 0.5)", 621 "temp == v_color", true }, 622 }; 623 624 // shader_multisample_interpolation.render 625 tcu::TestCaseGroup* renderGroup = new tcu::TestCaseGroup(m_testCtx, "render", "Rendering tests"); 626 addChild(renderGroup); 627 for (int caseId = 0; caseId < DE_LENGTH_OF_ARRAY(cases); ++caseId) 628 { 629 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, cases[caseId].name, ""); 630 renderGroup->addChild(group); 631 struct Format 632 { 633 char const* name; 634 GLenum internalFormat; 635 tcu::TextureFormat textureFormat; 636 char const* sampler; 637 char const* outType; 638 GLfloat min; 639 GLfloat max; 640 } formats[] = { 641 { "rgba8", GL_RGBA8, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 642 "sampler2D", "vec4", 0.0f, 1.0f }, 643 { "rgba8i", GL_RGBA8I, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8), 644 "isampler2D", "ivec4", -128.0f, 127.0f }, 645 { "rgba8ui", GL_RGBA8UI, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8), 646 "usampler2D", "uvec4", 0.0f, 255.0f }, 647 { "rgba32f", GL_RGBA32F, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), 648 "sampler2D", "vec4", 0.0f, 1.0f }, 649 }; 650 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); ++format) 651 { 652 tcu::TestCaseGroup* formatGroup = new tcu::TestCaseGroup(m_testCtx, formats[format].name, ""); 653 group->addChild(formatGroup); 654 655 for (int sample = 0; sample < DE_LENGTH_OF_ARRAY(samples); ++sample) 656 { 657 formatGroup->addChild(new ShaderMultisampleInterpolationBaseCase( 658 m_context, samples[sample].name, "", m_glslVersion, cases[caseId].qualifier, 659 cases[caseId].assignment, cases[caseId].condition, cases[caseId].unique, 660 formats[format].internalFormat, formats[format].textureFormat, formats[format].sampler, 661 formats[format].outType, formats[format].min, formats[format].max, samples[sample].samples)); 662 } 663 } 664 } 665} 666 667} // glcts 668