1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 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 Multisample shader render case 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fMultisampleShaderRenderCase.hpp" 25 #include "tcuRenderTarget.hpp" 26 #include "tcuSurface.hpp" 27 #include "tcuTestLog.hpp" 28 #include "tcuStringTemplate.hpp" 29 #include "gluShaderProgram.hpp" 30 #include "gluRenderContext.hpp" 31 #include "gluPixelTransfer.hpp" 32 #include "glwFunctions.hpp" 33 #include "glwEnums.hpp" 34 #include "deStringUtil.hpp" 35 36 namespace deqp 37 { 38 namespace gles31 39 { 40 namespace Functional 41 { 42 namespace MultisampleShaderRenderUtil 43 { 44 using std::map; 45 using std::string; 46 namespace 47 { 48 49 static const char* const s_vertexSource = "${GLSL_VERSION_DECL}\n" 50 "in highp vec4 a_position;\n" 51 "out highp vec4 v_position;\n" 52 "void main (void)\n" 53 "{\n" 54 " gl_Position = a_position;\n" 55 " v_position = a_position;\n" 56 "}"; 57 58 } // anonymous 59 60 QualityWarning::QualityWarning (const std::string& message) 61 : tcu::Exception(message) 62 { 63 } 64 65 MultisampleRenderCase::MultisampleRenderCase (Context& context, const char* name, const char* desc, int numSamples, RenderTarget target, int renderSize, int flags) 66 : TestCase (context, name, desc) 67 , m_numRequestedSamples (numSamples) 68 , m_renderTarget (target) 69 , m_renderSize (renderSize) 70 , m_perIterationShader ((flags & FLAG_PER_ITERATION_SHADER) != 0) 71 , m_verifyTextureSampleBuffers ((flags & FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS) != 0 && target == TARGET_TEXTURE) 72 , m_numTargetSamples (-1) 73 , m_buffer (0) 74 , m_resolveBuffer (0) 75 , m_program (DE_NULL) 76 , m_fbo (0) 77 , m_fboTexture (0) 78 , m_textureSamplerProgram (DE_NULL) 79 , m_fboRbo (0) 80 , m_resolveFbo (0) 81 , m_resolveFboTexture (0) 82 , m_iteration (0) 83 , m_numIterations (1) 84 , m_renderMode (0) 85 , m_renderCount (0) 86 , m_renderVao (0) 87 , m_resolveVao (0) 88 { 89 DE_ASSERT(target < TARGET_LAST); 90 } 91 92 MultisampleRenderCase::~MultisampleRenderCase (void) 93 { 94 MultisampleRenderCase::deinit(); 95 } 96 97 void MultisampleRenderCase::init (void) 98 { 99 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 100 deInt32 queriedSampleCount = -1; 101 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 102 map<string, string> args; 103 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 104 105 // requirements 106 107 switch (m_renderTarget) 108 { 109 case TARGET_DEFAULT: 110 { 111 if (m_context.getRenderTarget().getWidth() < m_renderSize || m_context.getRenderTarget().getHeight() < m_renderSize) 112 throw tcu::NotSupportedError("Test requires render target with size " + de::toString(m_renderSize) + "x" + de::toString(m_renderSize) + " or greater"); 113 break; 114 } 115 116 case TARGET_TEXTURE: 117 { 118 deInt32 maxTextureSamples = 0; 119 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, 1, &maxTextureSamples); 120 121 if (m_numRequestedSamples > maxTextureSamples) 122 throw tcu::NotSupportedError("Sample count not supported"); 123 break; 124 } 125 126 case TARGET_RENDERBUFFER: 127 { 128 deInt32 maxRboSamples = 0; 129 gl.getInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, 1, &maxRboSamples); 130 131 if (m_numRequestedSamples > maxRboSamples) 132 throw tcu::NotSupportedError("Sample count not supported"); 133 break; 134 } 135 136 default: 137 DE_ASSERT(false); 138 } 139 140 // resources 141 142 { 143 gl.genBuffers(1, &m_buffer); 144 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 145 146 setupRenderData(); 147 GLU_EXPECT_NO_ERROR(gl.getError(), "setup data"); 148 149 gl.genVertexArrays(1, &m_renderVao); 150 GLU_EXPECT_NO_ERROR(gl.getError(), "gen vao"); 151 152 // buffer for MSAA texture resolving 153 { 154 static const tcu::Vec4 fullscreenQuad[] = 155 { 156 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 157 tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), 158 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 159 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 160 }; 161 162 gl.genBuffers(1, &m_resolveBuffer); 163 gl.bindBuffer(GL_ARRAY_BUFFER, m_resolveBuffer); 164 gl.bufferData(GL_ARRAY_BUFFER, (int)sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW); 165 GLU_EXPECT_NO_ERROR(gl.getError(), "setup data"); 166 } 167 } 168 169 // msaa targets 170 171 if (m_renderTarget == TARGET_TEXTURE) 172 { 173 const deUint32 textureTarget = (m_numRequestedSamples == 0) ? (GL_TEXTURE_2D) : (GL_TEXTURE_2D_MULTISAMPLE); 174 175 gl.genVertexArrays(1, &m_resolveVao); 176 GLU_EXPECT_NO_ERROR(gl.getError(), "gen vao"); 177 178 gl.genTextures(1, &m_fboTexture); 179 gl.bindTexture(textureTarget, m_fboTexture); 180 if (m_numRequestedSamples == 0) 181 { 182 gl.texStorage2D(textureTarget, 1, GL_RGBA8, m_renderSize, m_renderSize); 183 gl.texParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 184 gl.texParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 185 } 186 else 187 gl.texStorage2DMultisample(textureTarget, m_numRequestedSamples, GL_RGBA8, m_renderSize, m_renderSize, GL_FALSE); 188 GLU_EXPECT_NO_ERROR(gl.getError(), "gen tex"); 189 190 gl.genFramebuffers(1, &m_fbo); 191 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 192 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureTarget, m_fboTexture, 0); 193 GLU_EXPECT_NO_ERROR(gl.getError(), "gen fbo"); 194 195 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 196 throw tcu::TestError("fbo not complete"); 197 198 if (m_numRequestedSamples != 0) 199 { 200 // for shader 201 gl.getTexLevelParameteriv(GL_TEXTURE_2D_MULTISAMPLE, 0, GL_TEXTURE_SAMPLES, &queriedSampleCount); 202 203 // logging 204 m_testCtx.getLog() << tcu::TestLog::Message << "Asked for " << m_numRequestedSamples << " samples, got " << queriedSampleCount << " samples." << tcu::TestLog::EndMessage; 205 206 // sanity 207 if (queriedSampleCount < m_numRequestedSamples) 208 throw tcu::TestError("Got less texture samples than asked for"); 209 } 210 211 // texture sampler shader 212 m_textureSamplerProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 213 << glu::VertexSource(tcu::StringTemplate(s_vertexSource).specialize(args)) 214 << glu::FragmentSource(genMSSamplerSource(queriedSampleCount))); 215 if (!m_textureSamplerProgram->isOk()) 216 { 217 m_testCtx.getLog() << tcu::TestLog::Section("SamplerShader", "Sampler shader") << *m_textureSamplerProgram << tcu::TestLog::EndSection; 218 throw tcu::TestError("could not build program"); 219 } 220 } 221 else if (m_renderTarget == TARGET_RENDERBUFFER) 222 { 223 gl.genRenderbuffers(1, &m_fboRbo); 224 gl.bindRenderbuffer(GL_RENDERBUFFER, m_fboRbo); 225 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_numRequestedSamples, GL_RGBA8, m_renderSize, m_renderSize); 226 GLU_EXPECT_NO_ERROR(gl.getError(), "gen rbo"); 227 228 gl.genFramebuffers(1, &m_fbo); 229 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 230 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_fboRbo); 231 GLU_EXPECT_NO_ERROR(gl.getError(), "gen fbo"); 232 233 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 234 throw tcu::TestError("fbo not complete"); 235 236 // logging 237 gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &queriedSampleCount); 238 m_testCtx.getLog() << tcu::TestLog::Message << "Asked for " << m_numRequestedSamples << " samples, got " << queriedSampleCount << " samples." << tcu::TestLog::EndMessage; 239 240 // sanity 241 if (queriedSampleCount < m_numRequestedSamples) 242 throw tcu::TestError("Got less renderbuffer samples samples than asked for"); 243 } 244 245 // fbo for resolving the multisample fbo 246 if (m_renderTarget != TARGET_DEFAULT) 247 { 248 gl.genTextures(1, &m_resolveFboTexture); 249 gl.bindTexture(GL_TEXTURE_2D, m_resolveFboTexture); 250 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, m_renderSize, m_renderSize); 251 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 252 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 253 GLU_EXPECT_NO_ERROR(gl.getError(), "gen tex"); 254 255 gl.genFramebuffers(1, &m_resolveFbo); 256 gl.bindFramebuffer(GL_FRAMEBUFFER, m_resolveFbo); 257 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_resolveFboTexture, 0); 258 GLU_EXPECT_NO_ERROR(gl.getError(), "gen fbo"); 259 260 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 261 throw tcu::TestError("resolve fbo not complete"); 262 } 263 264 // create verifier shader and set targetSampleCount 265 266 { 267 int realSampleCount = -1; 268 269 if (m_renderTarget == TARGET_TEXTURE) 270 { 271 if (m_numRequestedSamples == 0) 272 realSampleCount = 1; // non msaa texture 273 else 274 realSampleCount = de::max(1, queriedSampleCount); // msaa texture 275 } 276 else if (m_renderTarget == TARGET_RENDERBUFFER) 277 { 278 realSampleCount = de::max(1, queriedSampleCount); // msaa rbo 279 } 280 else if (m_renderTarget == TARGET_DEFAULT) 281 { 282 realSampleCount = de::max(1, m_context.getRenderTarget().getNumSamples()); 283 } 284 else 285 DE_ASSERT(DE_FALSE); 286 287 // is set and is valid 288 DE_ASSERT(realSampleCount != -1); 289 DE_ASSERT(realSampleCount != 0); 290 m_numTargetSamples = realSampleCount; 291 } 292 293 if (!m_perIterationShader) 294 { 295 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(genVertexSource(m_numTargetSamples)) << glu::FragmentSource(genFragmentSource(m_numTargetSamples))); 296 m_testCtx.getLog() << tcu::TestLog::Section("RenderShader", "Render shader") << *m_program << tcu::TestLog::EndSection; 297 if (!m_program->isOk()) 298 throw tcu::TestError("could not build program"); 299 300 } 301 } 302 303 void MultisampleRenderCase::deinit (void) 304 { 305 if (m_buffer) 306 { 307 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffer); 308 m_buffer = 0; 309 } 310 311 if (m_resolveBuffer) 312 { 313 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_resolveBuffer); 314 m_resolveBuffer = 0; 315 } 316 317 delete m_program; 318 m_program = DE_NULL; 319 320 if (m_fbo) 321 { 322 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_fbo); 323 m_fbo = 0; 324 } 325 326 if (m_fboTexture) 327 { 328 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_fboTexture); 329 m_fboTexture = 0; 330 } 331 332 delete m_textureSamplerProgram; 333 m_textureSamplerProgram = DE_NULL; 334 335 if (m_fboRbo) 336 { 337 m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_fboRbo); 338 m_fboRbo = 0; 339 } 340 341 if (m_resolveFbo) 342 { 343 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_resolveFbo); 344 m_resolveFbo = 0; 345 } 346 347 if (m_resolveFboTexture) 348 { 349 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_resolveFboTexture); 350 m_resolveFboTexture = 0; 351 } 352 353 if (m_renderVao) 354 { 355 m_context.getRenderContext().getFunctions().deleteVertexArrays(1, &m_renderVao); 356 m_renderVao = 0; 357 } 358 359 if (m_resolveVao) 360 { 361 m_context.getRenderContext().getFunctions().deleteVertexArrays(1, &m_resolveVao); 362 m_resolveVao = 0; 363 } 364 } 365 366 MultisampleRenderCase::IterateResult MultisampleRenderCase::iterate (void) 367 { 368 // default value 369 if (m_iteration == 0) 370 { 371 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 372 preTest(); 373 } 374 375 drawOneIteration(); 376 377 // next iteration 378 ++m_iteration; 379 if (m_iteration < m_numIterations) 380 return CONTINUE; 381 else 382 { 383 postTest(); 384 return STOP; 385 } 386 } 387 388 void MultisampleRenderCase::preDraw (void) 389 { 390 } 391 392 void MultisampleRenderCase::postDraw (void) 393 { 394 } 395 396 void MultisampleRenderCase::preTest (void) 397 { 398 } 399 400 void MultisampleRenderCase::postTest (void) 401 { 402 } 403 404 void MultisampleRenderCase::verifyResultImageAndSetResult (const tcu::Surface& resultImage) 405 { 406 // verify using case-specific verification 407 408 try 409 { 410 if (!verifyImage(resultImage)) 411 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 412 } 413 catch (const QualityWarning& ex) 414 { 415 m_testCtx.getLog() << tcu::TestLog::Message << "Quality warning, error = " << ex.what() << tcu::TestLog::EndMessage; 416 417 // Failures are more important than warnings 418 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 419 m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, ex.what()); 420 } 421 } 422 423 void MultisampleRenderCase::verifyResultBuffersAndSetResult (const std::vector<tcu::Surface>& resultBuffers) 424 { 425 // verify using case-specific verification 426 427 try 428 { 429 if (!verifySampleBuffers(resultBuffers)) 430 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 431 } 432 catch (const QualityWarning& ex) 433 { 434 m_testCtx.getLog() << tcu::TestLog::Message << "Quality warning, error = " << ex.what() << tcu::TestLog::EndMessage; 435 436 // Failures are more important than warnings 437 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 438 m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, ex.what()); 439 } 440 } 441 442 std::string MultisampleRenderCase::getIterationDescription (int iteration) const 443 { 444 DE_UNREF(iteration); 445 DE_ASSERT(false); 446 return ""; 447 } 448 449 void MultisampleRenderCase::drawOneIteration (void) 450 { 451 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 452 const std::string sectionDescription = (m_numIterations > 1) ? ("Iteration " + de::toString(m_iteration+1) + "/" + de::toString(m_numIterations) + ": " + getIterationDescription(m_iteration)) : ("Test"); 453 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration), sectionDescription); 454 455 // Per iteration shader? 456 if (m_perIterationShader) 457 { 458 delete m_program; 459 m_program = DE_NULL; 460 461 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 462 << glu::VertexSource(genVertexSource(m_numTargetSamples)) 463 << glu::FragmentSource(genFragmentSource(m_numTargetSamples))); 464 m_testCtx.getLog() << tcu::TestLog::Section("RenderShader", "Render shader") << *m_program << tcu::TestLog::EndSection; 465 if (!m_program->isOk()) 466 throw tcu::TestError("could not build program"); 467 468 } 469 470 // render 471 { 472 if (m_renderTarget == TARGET_TEXTURE || m_renderTarget == TARGET_RENDERBUFFER) 473 { 474 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 475 GLU_EXPECT_NO_ERROR(gl.getError(), "bind fbo"); 476 477 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << m_renderSceneDescription << " with render shader to fbo." << tcu::TestLog::EndMessage; 478 } 479 else 480 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << m_renderSceneDescription << " with render shader to default framebuffer." << tcu::TestLog::EndMessage; 481 482 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 483 gl.clear(GL_COLOR_BUFFER_BIT); 484 gl.viewport(0, 0, m_renderSize, m_renderSize); 485 GLU_EXPECT_NO_ERROR(gl.getError(), "clear"); 486 487 gl.bindVertexArray(m_renderVao); 488 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer); 489 490 // set attribs 491 DE_ASSERT(!m_renderAttribs.empty()); 492 for (std::map<std::string, Attrib>::const_iterator it = m_renderAttribs.begin(); it != m_renderAttribs.end(); ++it) 493 { 494 const deInt32 location = gl.getAttribLocation(m_program->getProgram(), it->first.c_str()); 495 496 if (location != -1) 497 { 498 gl.vertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, it->second.stride, (deUint8*)DE_NULL + it->second.offset); 499 gl.enableVertexAttribArray(location); 500 } 501 } 502 GLU_EXPECT_NO_ERROR(gl.getError(), "set attrib"); 503 504 gl.useProgram(m_program->getProgram()); 505 preDraw(); 506 gl.drawArrays(m_renderMode, 0, m_renderCount); 507 postDraw(); 508 gl.useProgram(0); 509 gl.bindVertexArray(0); 510 GLU_EXPECT_NO_ERROR(gl.getError(), "draw"); 511 512 if (m_renderTarget == TARGET_TEXTURE || m_renderTarget == TARGET_RENDERBUFFER) 513 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 514 } 515 516 // read 517 { 518 if (m_renderTarget == TARGET_DEFAULT) 519 { 520 tcu::Surface resultImage(m_renderSize, m_renderSize); 521 522 m_testCtx.getLog() << tcu::TestLog::Message << "Reading pixels from default framebuffer." << tcu::TestLog::EndMessage; 523 524 // default directly 525 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 526 GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels"); 527 528 // set test result 529 verifyResultImageAndSetResult(resultImage); 530 } 531 else if (m_renderTarget == TARGET_RENDERBUFFER) 532 { 533 tcu::Surface resultImage(m_renderSize, m_renderSize); 534 535 // rbo by blitting to non-multisample fbo 536 537 m_testCtx.getLog() << tcu::TestLog::Message << "Blitting result from fbo to single sample fbo. (Resolve multisample)" << tcu::TestLog::EndMessage; 538 539 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo); 540 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolveFbo); 541 gl.blitFramebuffer(0, 0, m_renderSize, m_renderSize, 0, 0, m_renderSize, m_renderSize, GL_COLOR_BUFFER_BIT, GL_NEAREST); 542 GLU_EXPECT_NO_ERROR(gl.getError(), "blit resolve"); 543 544 m_testCtx.getLog() << tcu::TestLog::Message << "Reading pixels from single sample framebuffer." << tcu::TestLog::EndMessage; 545 546 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_resolveFbo); 547 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 548 GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels"); 549 550 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 551 552 // set test result 553 verifyResultImageAndSetResult(resultImage); 554 } 555 else if (m_renderTarget == TARGET_TEXTURE && !m_verifyTextureSampleBuffers) 556 { 557 const deInt32 posLocation = gl.getAttribLocation(m_textureSamplerProgram->getProgram(), "a_position"); 558 const deInt32 samplerLocation = gl.getUniformLocation(m_textureSamplerProgram->getProgram(), "u_sampler"); 559 const deUint32 textureTarget = (m_numRequestedSamples == 0) ? (GL_TEXTURE_2D) : (GL_TEXTURE_2D_MULTISAMPLE); 560 tcu::Surface resultImage (m_renderSize, m_renderSize); 561 562 if (m_numRequestedSamples) 563 m_testCtx.getLog() << tcu::TestLog::Message << "Using sampler shader to sample the multisample texture to single sample framebuffer." << tcu::TestLog::EndMessage; 564 else 565 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing texture to single sample framebuffer. Using sampler shader." << tcu::TestLog::EndMessage; 566 567 if (samplerLocation == -1) 568 throw tcu::TestError("Location u_sampler was -1."); 569 570 // resolve multisample texture by averaging 571 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 572 gl.clear(GL_COLOR_BUFFER_BIT); 573 gl.viewport(0, 0, m_renderSize, m_renderSize); 574 GLU_EXPECT_NO_ERROR(gl.getError(), "clear"); 575 576 gl.bindVertexArray(m_resolveVao); 577 gl.bindBuffer(GL_ARRAY_BUFFER, m_resolveBuffer); 578 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 579 gl.enableVertexAttribArray(posLocation); 580 GLU_EXPECT_NO_ERROR(gl.getError(), "set attrib"); 581 582 gl.activeTexture(GL_TEXTURE0); 583 gl.bindTexture(textureTarget, m_fboTexture); 584 GLU_EXPECT_NO_ERROR(gl.getError(), "bind tex"); 585 586 gl.useProgram(m_textureSamplerProgram->getProgram()); 587 gl.uniform1i(samplerLocation, 0); 588 589 gl.bindFramebuffer(GL_FRAMEBUFFER, m_resolveFbo); 590 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 591 592 gl.useProgram(0); 593 gl.bindVertexArray(0); 594 GLU_EXPECT_NO_ERROR(gl.getError(), "draw"); 595 596 m_testCtx.getLog() << tcu::TestLog::Message << "Reading pixels from single sample framebuffer." << tcu::TestLog::EndMessage; 597 598 glu::readPixels(m_context.getRenderContext(), 0, 0, resultImage.getAccess()); 599 GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels"); 600 601 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 602 603 // set test result 604 verifyResultImageAndSetResult(resultImage); 605 } 606 else if (m_renderTarget == TARGET_TEXTURE && m_verifyTextureSampleBuffers) 607 { 608 const deInt32 posLocation = gl.getAttribLocation(m_textureSamplerProgram->getProgram(), "a_position"); 609 const deInt32 samplerLocation = gl.getUniformLocation(m_textureSamplerProgram->getProgram(), "u_sampler"); 610 const deInt32 sampleLocation = gl.getUniformLocation(m_textureSamplerProgram->getProgram(), "u_sampleNdx"); 611 const deUint32 textureTarget = (m_numRequestedSamples == 0) ? (GL_TEXTURE_2D) : (GL_TEXTURE_2D_MULTISAMPLE); 612 std::vector<tcu::Surface> resultBuffers (m_numTargetSamples); 613 614 if (m_numRequestedSamples) 615 m_testCtx.getLog() << tcu::TestLog::Message << "Reading multisample texture sample buffers." << tcu::TestLog::EndMessage; 616 else 617 m_testCtx.getLog() << tcu::TestLog::Message << "Reading texture." << tcu::TestLog::EndMessage; 618 619 if (samplerLocation == -1) 620 throw tcu::TestError("Location u_sampler was -1."); 621 if (sampleLocation == -1) 622 throw tcu::TestError("Location u_sampleNdx was -1."); 623 624 for (int sampleNdx = 0; sampleNdx < m_numTargetSamples; ++sampleNdx) 625 resultBuffers[sampleNdx].setSize(m_renderSize, m_renderSize); 626 627 // read sample buffers to different surfaces 628 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 629 gl.clear(GL_COLOR_BUFFER_BIT); 630 gl.viewport(0, 0, m_renderSize, m_renderSize); 631 GLU_EXPECT_NO_ERROR(gl.getError(), "clear"); 632 633 gl.bindVertexArray(m_resolveVao); 634 gl.bindBuffer(GL_ARRAY_BUFFER, m_resolveBuffer); 635 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 636 gl.enableVertexAttribArray(posLocation); 637 GLU_EXPECT_NO_ERROR(gl.getError(), "set attrib"); 638 639 gl.activeTexture(GL_TEXTURE0); 640 gl.bindTexture(textureTarget, m_fboTexture); 641 GLU_EXPECT_NO_ERROR(gl.getError(), "bind tex"); 642 643 gl.bindFramebuffer(GL_FRAMEBUFFER, m_resolveFbo); 644 gl.useProgram(m_textureSamplerProgram->getProgram()); 645 gl.uniform1i(samplerLocation, 0); 646 647 m_testCtx.getLog() << tcu::TestLog::Message << "Reading sample buffers" << tcu::TestLog::EndMessage; 648 649 for (int sampleNdx = 0; sampleNdx < m_numTargetSamples; ++sampleNdx) 650 { 651 gl.uniform1i(sampleLocation, sampleNdx); 652 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 653 GLU_EXPECT_NO_ERROR(gl.getError(), "draw"); 654 655 glu::readPixels(m_context.getRenderContext(), 0, 0, resultBuffers[sampleNdx].getAccess()); 656 GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels"); 657 } 658 659 gl.useProgram(0); 660 gl.bindVertexArray(0); 661 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 662 663 // verify sample buffers 664 verifyResultBuffersAndSetResult(resultBuffers); 665 } 666 else 667 DE_ASSERT(false); 668 } 669 } 670 671 std::string MultisampleRenderCase::genVertexSource (int numTargetSamples) const 672 { 673 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 674 map<string, string> args; 675 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 676 677 DE_UNREF(numTargetSamples); 678 return std::string(tcu::StringTemplate(s_vertexSource).specialize(args)); 679 } 680 681 std::string MultisampleRenderCase::genMSSamplerSource (int numTargetSamples) const 682 { 683 if (m_verifyTextureSampleBuffers) 684 return genMSTextureLayerFetchSource(numTargetSamples); 685 else 686 return genMSTextureResolverSource(numTargetSamples); 687 } 688 689 std::string MultisampleRenderCase::genMSTextureResolverSource (int numTargetSamples) const 690 { 691 // default behavior: average 692 693 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 694 map<string, string> args; 695 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 696 const bool isSingleSampleTarget = (m_numRequestedSamples == 0); 697 std::ostringstream buf; 698 699 buf << "${GLSL_VERSION_DECL}\n" 700 "in mediump vec4 v_position;\n" 701 "layout(location = 0) out mediump vec4 fragColor;\n" 702 "uniform mediump " << ((isSingleSampleTarget) ? ("sampler2D") : ("sampler2DMS")) << " u_sampler;\n" 703 "void main (void)\n" 704 "{\n" 705 " mediump vec2 relPosition = (v_position.xy + vec2(1.0, 1.0)) / 2.0;\n" 706 " mediump ivec2 fetchPos = ivec2(floor(relPosition * " << m_renderSize << ".0));\n" 707 " mediump vec4 colorSum = vec4(0.0, 0.0, 0.0, 0.0);\n" 708 "\n"; 709 710 if (isSingleSampleTarget) 711 buf << " colorSum = texelFetch(u_sampler, fetchPos, 0);\n" 712 "\n"; 713 else 714 buf << " for (int sampleNdx = 0; sampleNdx < " << numTargetSamples << "; ++sampleNdx)\n" 715 " colorSum += texelFetch(u_sampler, fetchPos, sampleNdx);\n" 716 " colorSum /= " << numTargetSamples << ".0;\n" 717 "\n"; 718 719 buf << " fragColor = vec4(colorSum.xyz, 1.0);\n" 720 "}\n"; 721 722 return tcu::StringTemplate(buf.str()).specialize(args); 723 } 724 725 std::string MultisampleRenderCase::genMSTextureLayerFetchSource (int numTargetSamples) const 726 { 727 DE_UNREF(numTargetSamples); 728 729 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 730 map<string, string> args; 731 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 732 const bool isSingleSampleTarget = (m_numRequestedSamples == 0); 733 std::ostringstream buf; 734 735 buf << "${GLSL_VERSION_DECL}\n" 736 "in mediump vec4 v_position;\n" 737 "layout(location = 0) out mediump vec4 fragColor;\n" 738 "uniform mediump " << ((isSingleSampleTarget) ? ("sampler2D") : ("sampler2DMS")) << " u_sampler;\n" 739 "uniform mediump int u_sampleNdx;\n" 740 "void main (void)\n" 741 "{\n" 742 " mediump vec2 relPosition = (v_position.xy + vec2(1.0, 1.0)) / 2.0;\n" 743 " mediump ivec2 fetchPos = ivec2(floor(relPosition * " << m_renderSize << ".0));\n" 744 "\n" 745 " mediump vec4 color = texelFetch(u_sampler, fetchPos, u_sampleNdx);\n" 746 " fragColor = vec4(color.rgb, 1.0);\n" 747 "}\n"; 748 749 return tcu::StringTemplate(buf.str()).specialize(args); 750 } 751 752 bool MultisampleRenderCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers) 753 { 754 DE_UNREF(resultBuffers); 755 DE_ASSERT(false); 756 return false; 757 } 758 759 void MultisampleRenderCase::setupRenderData (void) 760 { 761 static const tcu::Vec4 fullscreenQuad[] = 762 { 763 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 764 tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), 765 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 766 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 767 }; 768 769 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 770 771 m_renderMode = GL_TRIANGLE_STRIP; 772 m_renderCount = 4; 773 m_renderSceneDescription = "quad"; 774 775 m_renderAttribs["a_position"].offset = 0; 776 m_renderAttribs["a_position"].stride = sizeof(float[4]); 777 778 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer); 779 gl.bufferData(GL_ARRAY_BUFFER, (int)sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW); 780 } 781 782 } // MultisampleShaderRenderUtil 783 } // Functional 784 } // gles31 785 } // deqp 786