es31fMultisampleShaderRenderCase.cpp revision fb059fdb43c8b6073ada028a68124263c59a000a
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
36namespace deqp
37{
38namespace gles31
39{
40namespace Functional
41{
42namespace MultisampleShaderRenderUtil
43{
44using std::map;
45using std::string;
46namespace
47{
48
49static 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
60QualityWarning::QualityWarning (const std::string& message)
61	: tcu::Exception(message)
62{
63}
64
65MultisampleRenderCase::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
92MultisampleRenderCase::~MultisampleRenderCase (void)
93{
94	MultisampleRenderCase::deinit();
95}
96
97void 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
303void 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
366MultisampleRenderCase::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
388void MultisampleRenderCase::preDraw (void)
389{
390}
391
392void MultisampleRenderCase::postDraw (void)
393{
394}
395
396void MultisampleRenderCase::preTest (void)
397{
398}
399
400void MultisampleRenderCase::postTest (void)
401{
402}
403
404void 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
423void 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
442std::string	MultisampleRenderCase::getIterationDescription (int iteration) const
443{
444	DE_UNREF(iteration);
445	DE_ASSERT(false);
446	return "";
447}
448
449void 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
671std::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
681std::string MultisampleRenderCase::genMSSamplerSource (int numTargetSamples) const
682{
683	if (m_verifyTextureSampleBuffers)
684		return genMSTextureLayerFetchSource(numTargetSamples);
685	else
686		return genMSTextureResolverSource(numTargetSamples);
687}
688
689std::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
725std::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
752bool MultisampleRenderCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers)
753{
754	DE_UNREF(resultBuffers);
755	DE_ASSERT(false);
756	return false;
757}
758
759void 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