• 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 "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