• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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