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