Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 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 FBO multisample tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fFboMultisampleTests.hpp"
     25 #include "es3fFboTestCase.hpp"
     26 #include "es3fFboTestUtil.hpp"
     27 #include "gluTextureUtil.hpp"
     28 #include "tcuImageCompare.hpp"
     29 #include "tcuTextureUtil.hpp"
     30 #include "tcuTestLog.hpp"
     31 #include "deStringUtil.hpp"
     32 #include "deRandom.hpp"
     33 #include "sglrContextUtil.hpp"
     34 #include "glwEnums.hpp"
     35 
     36 namespace deqp
     37 {
     38 namespace gles3
     39 {
     40 namespace Functional
     41 {
     42 
     43 using std::string;
     44 using tcu::TestLog;
     45 using tcu::Vec2;
     46 using tcu::Vec3;
     47 using tcu::Vec4;
     48 using tcu::IVec2;
     49 using tcu::IVec3;
     50 using tcu::IVec4;
     51 using tcu::UVec4;
     52 using namespace FboTestUtil;
     53 
     54 class BasicFboMultisampleCase : public FboTestCase
     55 {
     56 public:
     57 	BasicFboMultisampleCase (Context& context, const char* name, const char* desc, deUint32 colorFormat, deUint32 depthStencilFormat, const IVec2& size, int numSamples)
     58 		: FboTestCase			(context, name, desc)
     59 		, m_colorFormat			(colorFormat)
     60 		, m_depthStencilFormat	(depthStencilFormat)
     61 		, m_size				(size)
     62 		, m_numSamples			(numSamples)
     63 	{
     64 	}
     65 
     66 protected:
     67 	void preCheck (void)
     68 	{
     69 		checkFormatSupport	(m_colorFormat);
     70 		checkSampleCount	(m_colorFormat, m_numSamples);
     71 
     72 		if (m_depthStencilFormat != GL_NONE)
     73 		{
     74 			checkFormatSupport	(m_depthStencilFormat);
     75 			checkSampleCount	(m_depthStencilFormat, m_numSamples);
     76 		}
     77 	}
     78 
     79 	void render (tcu::Surface& dst)
     80 	{
     81 		tcu::TextureFormat		colorFmt				= glu::mapGLInternalFormat(m_colorFormat);
     82 		tcu::TextureFormat		depthStencilFmt			= m_depthStencilFormat != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFormat) : tcu::TextureFormat();
     83 		tcu::TextureFormatInfo	colorFmtInfo			= tcu::getTextureFormatInfo(colorFmt);
     84 		bool					depth					= depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS;
     85 		bool					stencil					= depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS;
     86 		GradientShader			gradShader				(getFragmentOutputType(colorFmt));
     87 		FlatColorShader			flatShader				(getFragmentOutputType(colorFmt));
     88 		deUint32				gradShaderID			= getCurrentContext()->createProgram(&gradShader);
     89 		deUint32				flatShaderID			= getCurrentContext()->createProgram(&flatShader);
     90 		deUint32				msaaFbo					= 0;
     91 		deUint32				resolveFbo				= 0;
     92 		deUint32				msaaColorRbo			= 0;
     93 		deUint32				resolveColorRbo			= 0;
     94 		deUint32				msaaDepthStencilRbo		= 0;
     95 		deUint32				resolveDepthStencilRbo	= 0;
     96 
     97 		// Create framebuffers.
     98 		for (int ndx = 0; ndx < 2; ndx++)
     99 		{
    100 			deUint32&	fbo				= ndx ? resolveFbo				: msaaFbo;
    101 			deUint32&	colorRbo		= ndx ? resolveColorRbo			: msaaColorRbo;
    102 			deUint32&	depthStencilRbo	= ndx ? resolveDepthStencilRbo	: msaaDepthStencilRbo;
    103 			int			samples			= ndx ? 0						: m_numSamples;
    104 
    105 			glGenRenderbuffers(1, &colorRbo);
    106 			glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
    107 			glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, m_colorFormat, m_size.x(), m_size.y());
    108 
    109 			if (depth || stencil)
    110 			{
    111 				glGenRenderbuffers(1, &depthStencilRbo);
    112 				glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
    113 				glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, m_depthStencilFormat, m_size.x(), m_size.y());
    114 			}
    115 
    116 			glGenFramebuffers(1, &fbo);
    117 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    118 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
    119 			if (depth)
    120 				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
    121 			if (stencil)
    122 				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
    123 
    124 			checkError();
    125 			checkFramebufferStatus(GL_FRAMEBUFFER);
    126 		}
    127 
    128 		glBindFramebuffer(GL_FRAMEBUFFER, msaaFbo);
    129 		glViewport(0, 0, m_size.x(), m_size.y());
    130 
    131 		// Clear depth and stencil buffers.
    132 		glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
    133 
    134 		// Fill MSAA fbo with gradient, depth = [-1..1]
    135 		glEnable(GL_DEPTH_TEST);
    136 		gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax);
    137 		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
    138 
    139 		// Render random-colored quads.
    140 		{
    141 			const int		numQuads	= 8;
    142 			de::Random		rnd			(9);
    143 
    144 			glDepthFunc(GL_ALWAYS);
    145 			glEnable(GL_STENCIL_TEST);
    146 			glStencilFunc(GL_ALWAYS, 0, 0xffu);
    147 			glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
    148 
    149 			for (int ndx = 0; ndx < numQuads; ndx++)
    150 			{
    151 				float	r		= rnd.getFloat();
    152 				float	g		= rnd.getFloat();
    153 				float	b		= rnd.getFloat();
    154 				float	a		= rnd.getFloat();
    155 				float	x0		= rnd.getFloat(-1.0f, 1.0f);
    156 				float	y0		= rnd.getFloat(-1.0f, 1.0f);
    157 				float	z0		= rnd.getFloat(-1.0f, 1.0f);
    158 				float	x1		= rnd.getFloat(-1.0f, 1.0f);
    159 				float	y1		= rnd.getFloat(-1.0f, 1.0f);
    160 				float	z1		= rnd.getFloat(-1.0f, 1.0f);
    161 
    162 				flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(r,g,b,a) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin);
    163 				sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(x0, y0, z0), Vec3(x1, y1, z1));
    164 			}
    165 		}
    166 
    167 		glDisable(GL_DEPTH_TEST);
    168 		glDisable(GL_STENCIL_TEST);
    169 		checkError();
    170 
    171 		// Resolve using glBlitFramebuffer().
    172 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFbo);
    173 		glBlitFramebuffer(0, 0, m_size.x(), m_size.y(), 0, 0, m_size.x(), m_size.y(), GL_COLOR_BUFFER_BIT | (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0), GL_NEAREST);
    174 
    175 		glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFbo);
    176 
    177 		if (depth)
    178 		{
    179 			// Visualize depth.
    180 			const int	numSteps	= 8;
    181 			const float	step		= 2.0f / (float)numSteps;
    182 
    183 			glEnable(GL_DEPTH_TEST);
    184 			glDepthFunc(GL_LESS);
    185 			glDepthMask(GL_FALSE);
    186 			glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
    187 
    188 			for (int ndx = 0; ndx < numSteps; ndx++)
    189 			{
    190 				float d = -1.0f + step*(float)ndx;
    191 				float c = (float)ndx / (float)(numSteps-1);
    192 
    193 				flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, c, 1.0f) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin);
    194 				sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, d), Vec3(1.0f, 1.0f, d));
    195 			}
    196 
    197 			glDisable(GL_DEPTH_TEST);
    198 		}
    199 
    200 		if (stencil)
    201 		{
    202 			// Visualize stencil.
    203 			const int	numSteps	= 4;
    204 			const int	step		= 1;
    205 
    206 			glEnable(GL_STENCIL_TEST);
    207 			glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    208 			glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
    209 
    210 			for (int ndx = 0; ndx < numSteps; ndx++)
    211 			{
    212 				int		s	= step*ndx;
    213 				float	c	= (float)ndx / (float)(numSteps-1);
    214 
    215 				glStencilFunc(GL_EQUAL, s, 0xffu);
    216 
    217 				flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, c, 0.0f, 1.0f) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin);
    218 				sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    219 			}
    220 
    221 			glDisable(GL_STENCIL_TEST);
    222 		}
    223 
    224 		readPixels(dst, 0, 0, m_size.x(), m_size.y(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias);
    225 	}
    226 
    227 	bool colorCompare (const tcu::Surface& reference, const tcu::Surface& result)
    228 	{
    229 		const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_colorFormat), tcu::RGBA(12, 12, 12, 12)));
    230 
    231 		return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
    232 	}
    233 
    234 	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
    235 	{
    236 		if (m_depthStencilFormat != GL_NONE)
    237 			return FboTestCase::compare(reference, result);
    238 		else
    239 			return colorCompare(reference, result);
    240 	}
    241 
    242 private:
    243 	deUint32	m_colorFormat;
    244 	deUint32	m_depthStencilFormat;
    245 	IVec2		m_size;
    246 	int			m_numSamples;
    247 };
    248 
    249 FboMultisampleTests::FboMultisampleTests (Context& context)
    250 	: TestCaseGroup(context, "msaa", "Multisample FBO tests")
    251 {
    252 }
    253 
    254 FboMultisampleTests::~FboMultisampleTests (void)
    255 {
    256 }
    257 
    258 void FboMultisampleTests::init (void)
    259 {
    260 	static const deUint32 colorFormats[] =
    261 	{
    262 		// RGBA formats
    263 		GL_RGBA8,
    264 		GL_SRGB8_ALPHA8,
    265 		GL_RGB10_A2,
    266 		GL_RGBA4,
    267 		GL_RGB5_A1,
    268 
    269 		// RGB formats
    270 		GL_RGB8,
    271 		GL_RGB565,
    272 
    273 		// RG formats
    274 		GL_RG8,
    275 
    276 		// R formats
    277 		GL_R8,
    278 
    279 		// GL_EXT_color_buffer_float
    280 		GL_RGBA32F,
    281 		GL_RGBA16F,
    282 		GL_R11F_G11F_B10F,
    283 		GL_RG32F,
    284 		GL_RG16F,
    285 		GL_R32F,
    286 		GL_R16F
    287 	};
    288 
    289 	static const deUint32 depthStencilFormats[] =
    290 	{
    291 		GL_DEPTH_COMPONENT32F,
    292 		GL_DEPTH_COMPONENT24,
    293 		GL_DEPTH_COMPONENT16,
    294 		GL_DEPTH32F_STENCIL8,
    295 		GL_DEPTH24_STENCIL8,
    296 		GL_STENCIL_INDEX8
    297 	};
    298 
    299 	static const int sampleCounts[] = { 2, 4, 8 };
    300 
    301 	for (int sampleCntNdx = 0; sampleCntNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCntNdx++)
    302 	{
    303 		int					samples				= sampleCounts[sampleCntNdx];
    304 		tcu::TestCaseGroup*	sampleCountGroup	= new tcu::TestCaseGroup(m_testCtx, (de::toString(samples) + "_samples").c_str(), "");
    305 		addChild(sampleCountGroup);
    306 
    307 		// Color formats.
    308 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
    309 			sampleCountGroup->addChild(new BasicFboMultisampleCase(m_context, getFormatName(colorFormats[fmtNdx]), "", colorFormats[fmtNdx], GL_NONE, IVec2(119, 131), samples));
    310 
    311 		// Depth/stencil formats.
    312 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
    313 			sampleCountGroup->addChild(new BasicFboMultisampleCase(m_context, getFormatName(depthStencilFormats[fmtNdx]), "", GL_RGBA8, depthStencilFormats[fmtNdx], IVec2(119, 131), samples));
    314 	}
    315 }
    316 
    317 } // Functional
    318 } // gles3
    319 } // deqp
    320