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
35 namespace deqp
36 {
37 namespace gles31
38 {
39 namespace Functional
40 {
41 namespace MultisampleShaderRenderUtil
42 {
43 namespace
44 {
45
46 static 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
QualityWarning(const std::string & message)57 QualityWarning::QualityWarning (const std::string& message)
58 : tcu::Exception(message)
59 {
60 }
61
MultisampleRenderCase(Context & context,const char * name,const char * desc,int numSamples,RenderTarget target,int renderSize,int flags)62 MultisampleRenderCase::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
~MultisampleRenderCase(void)89 MultisampleRenderCase::~MultisampleRenderCase (void)
90 {
91 MultisampleRenderCase::deinit();
92 }
93
init(void)94 void 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
deinit(void)295 void 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
iterate(void)358 MultisampleRenderCase::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
preDraw(void)380 void MultisampleRenderCase::preDraw (void)
381 {
382 }
383
postDraw(void)384 void MultisampleRenderCase::postDraw (void)
385 {
386 }
387
preTest(void)388 void MultisampleRenderCase::preTest (void)
389 {
390 }
391
postTest(void)392 void MultisampleRenderCase::postTest (void)
393 {
394 }
395
verifyResultImageAndSetResult(const tcu::Surface & resultImage)396 void 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
verifyResultBuffersAndSetResult(const std::vector<tcu::Surface> & resultBuffers)415 void 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
getIterationDescription(int iteration) const434 std::string MultisampleRenderCase::getIterationDescription (int iteration) const
435 {
436 DE_UNREF(iteration);
437 DE_ASSERT(false);
438 return "";
439 }
440
drawOneIteration(void)441 void 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
genVertexSource(int numTargetSamples) const661 std::string MultisampleRenderCase::genVertexSource (int numTargetSamples) const
662 {
663 DE_UNREF(numTargetSamples);
664 return std::string(s_vertexSource);
665 }
666
genMSSamplerSource(int numTargetSamples) const667 std::string MultisampleRenderCase::genMSSamplerSource (int numTargetSamples) const
668 {
669 if (m_verifyTextureSampleBuffers)
670 return genMSTextureLayerFetchSource(numTargetSamples);
671 else
672 return genMSTextureResolverSource(numTargetSamples);
673 }
674
genMSTextureResolverSource(int numTargetSamples) const675 std::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
genMSTextureLayerFetchSource(int numTargetSamples) const708 std::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
verifySampleBuffers(const std::vector<tcu::Surface> & resultBuffers)732 bool MultisampleRenderCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
733 {
734 DE_UNREF(resultBuffers);
735 DE_ASSERT(false);
736 return false;
737 }
738
setupRenderData(void)739 void 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