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