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
QualityWarning(const std::string & message)60 QualityWarning::QualityWarning (const std::string& message)
61 : tcu::Exception(message)
62 {
63 }
64
MultisampleRenderCase(Context & context,const char * name,const char * desc,int numSamples,RenderTarget target,int renderSize,int flags)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
~MultisampleRenderCase(void)92 MultisampleRenderCase::~MultisampleRenderCase (void)
93 {
94 MultisampleRenderCase::deinit();
95 }
96
init(void)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
deinit(void)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
iterate(void)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
preDraw(void)388 void MultisampleRenderCase::preDraw (void)
389 {
390 }
391
postDraw(void)392 void MultisampleRenderCase::postDraw (void)
393 {
394 }
395
preTest(void)396 void MultisampleRenderCase::preTest (void)
397 {
398 }
399
postTest(void)400 void MultisampleRenderCase::postTest (void)
401 {
402 }
403
verifyResultImageAndSetResult(const tcu::Surface & resultImage)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
verifyResultBuffersAndSetResult(const std::vector<tcu::Surface> & resultBuffers)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
getIterationDescription(int iteration) const442 std::string MultisampleRenderCase::getIterationDescription (int iteration) const
443 {
444 DE_UNREF(iteration);
445 DE_ASSERT(false);
446 return "";
447 }
448
drawOneIteration(void)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
genVertexSource(int numTargetSamples) const671 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
genMSSamplerSource(int numTargetSamples) const681 std::string MultisampleRenderCase::genMSSamplerSource (int numTargetSamples) const
682 {
683 if (m_verifyTextureSampleBuffers)
684 return genMSTextureLayerFetchSource(numTargetSamples);
685 else
686 return genMSTextureResolverSource(numTargetSamples);
687 }
688
genMSTextureResolverSource(int numTargetSamples) const689 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
genMSTextureLayerFetchSource(int numTargetSamples) const725 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
verifySampleBuffers(const std::vector<tcu::Surface> & resultBuffers)752 bool MultisampleRenderCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
753 {
754 DE_UNREF(resultBuffers);
755 DE_ASSERT(false);
756 return false;
757 }
758
setupRenderData(void)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