Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL (ES) 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 Framebuffer completeness tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fFboCompletenessTests.hpp"
     25 
     26 #include "glsFboCompletenessTests.hpp"
     27 #include <sstream>
     28 
     29 using namespace glw;
     30 using deqp::gls::Range;
     31 using namespace deqp::gls::FboUtil;
     32 using namespace deqp::gls::FboUtil::config;
     33 namespace fboc = deqp::gls::fboc;
     34 typedef tcu::TestCase::IterateResult IterateResult;
     35 using std::string;
     36 using std::ostringstream;
     37 
     38 namespace deqp
     39 {
     40 namespace gles3
     41 {
     42 namespace Functional
     43 {
     44 
     45 static const FormatKey s_es3ColorRenderables[] =
     46 {
     47 	// GLES3, 4.4.4: "An internal format is color-renderable if it is one of
     48 	// the formats from table 3.12 noted as color-renderable..."
     49 	GL_R8, GL_RG8, GL_RGB8, GL_RGB565, GL_RGBA4, GL_RGB5_A1, GL_RGBA8,
     50 	GL_RGB10_A2, GL_RGB10_A2UI, GL_SRGB8_ALPHA8,
     51 	GL_R8I, GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI,
     52 	GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI,
     53 	GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI,
     54 };
     55 
     56 static const FormatKey s_es3UnsizedColorRenderables[] =
     57 {
     58 	// "...or if it is unsized format RGBA or RGB."
     59 	// See Table 3.3 in GLES3.
     60 	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_UNSIGNED_BYTE),
     61 	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4),
     62 	GLS_UNSIZED_FORMATKEY(GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1),
     63 	GLS_UNSIZED_FORMATKEY(GL_RGB,	GL_UNSIGNED_BYTE),
     64 	GLS_UNSIZED_FORMATKEY(GL_RGB,	GL_UNSIGNED_SHORT_5_6_5),
     65 };
     66 
     67 static const FormatKey s_es3DepthRenderables[] =
     68 {
     69 	// GLES3, 4.4.4: "An internal format is depth-renderable if it is one of
     70 	// the formats from table 3.13."
     71 	GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32F,
     72 	GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8,
     73 };
     74 
     75 static const FormatKey s_es3StencilRboRenderables[] =
     76 {
     77 	// GLES3, 4.4.4: "An internal format is stencil-renderable if it is
     78 	// STENCIL_INDEX8..."
     79 	GL_STENCIL_INDEX8,
     80 };
     81 
     82 static const FormatKey s_es3StencilRenderables[] =
     83 {
     84 	// "...or one of the formats from table 3.13 whose base internal format is
     85 	// DEPTH_STENCIL."
     86 	GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8,
     87 };
     88 
     89 static const FormatKey s_es3TextureFloatFormats[] =
     90 {
     91 	GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F,
     92 	GL_RG32F, GL_RG16F, GL_R32F, GL_R16F,
     93 	GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F,
     94 };
     95 
     96 static const FormatKey s_es3NotRenderableTextureFormats[] =
     97 {
     98 	GL_R8_SNORM, GL_RG8_SNORM, GL_RGB8_SNORM, GL_RGBA8_SNORM,
     99 	GL_RGB9_E5, GL_SRGB8,
    100 	GL_RGB8I, GL_RGB16I, GL_RGB32I,
    101 	GL_RGB8UI, GL_RGB16UI,GL_RGB32UI,
    102 };
    103 
    104 static const FormatEntry s_es3Formats[] =
    105 {
    106 	// Renderbuffers don't support unsized formats
    107 	{ REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID,
    108 	  GLS_ARRAY_RANGE(s_es3UnsizedColorRenderables) },
    109 	{ REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
    110 	  GLS_ARRAY_RANGE(s_es3ColorRenderables) },
    111 	{ REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
    112 	  GLS_ARRAY_RANGE(s_es3DepthRenderables) },
    113 	{ REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID,
    114 	  GLS_ARRAY_RANGE(s_es3StencilRboRenderables) },
    115 	{ REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
    116 	  GLS_ARRAY_RANGE(s_es3StencilRenderables) },
    117 	{ TEXTURE_VALID,
    118 	  GLS_ARRAY_RANGE(s_es3NotRenderableTextureFormats) },
    119 
    120 	// These are not color-renderable in vanilla ES3, but we need to mark them
    121 	// as valid for textures, since EXT_color_buffer_(half_)float brings in
    122 	// color-renderability and only renderbuffer-validity.
    123 	{ TEXTURE_VALID,
    124 	  GLS_ARRAY_RANGE(s_es3TextureFloatFormats) },
    125 };
    126 
    127 // GL_EXT_color_buffer_float
    128 static const FormatKey s_extColorBufferFloatFormats[] =
    129 {
    130 	GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F,
    131 };
    132 
    133 // GL_OES_texture_stencil8
    134 static const FormatKey s_extOESTextureStencil8[] =
    135 {
    136 	GL_STENCIL_INDEX8,
    137 };
    138 
    139 
    140 static const FormatExtEntry s_es3ExtFormats[] =
    141 {
    142 	{ "GL_EXT_color_buffer_float",
    143 	  // These are already texture-valid in ES3, the extension just adds RBO
    144 	  // support and makes them color-renderable.
    145 	  REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID,
    146 	  GLS_ARRAY_RANGE(s_extColorBufferFloatFormats) },
    147 	{ "GL_OES_texture_stencil8",
    148 	  // Note: es3 RBO tests actually cover the first two requirements
    149       // - kept here for completeness
    150       REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID,
    151 	  GLS_ARRAY_RANGE(s_extOESTextureStencil8) }
    152 };
    153 
    154 class ES3Checker : public Checker
    155 {
    156 public:
    157 				ES3Checker	(void)
    158 					: m_numSamples			(-1)
    159 					, m_depthStencilImage	(0)
    160 					, m_depthStencilType	(GL_NONE) {}
    161 	void		check 		(GLenum attPoint, const Attachment& att, const Image* image);
    162 
    163 private:
    164 	//! The common number of samples of images.
    165 	GLsizei		m_numSamples;
    166 
    167 	//! The common image for depth and stencil attachments.
    168 	GLuint		m_depthStencilImage;
    169 	GLenum		m_depthStencilType;
    170 };
    171 
    172 void ES3Checker::check (GLenum attPoint, const Attachment& att, const Image* image)
    173 {
    174 	GLsizei imgSamples = imageNumSamples(*image);
    175 
    176 	if (m_numSamples == -1)
    177 	{
    178 		m_numSamples = imgSamples;
    179 	}
    180 	else
    181 	{
    182 		// GLES3: "The value of RENDERBUFFER_SAMPLES is the same for all attached
    183 		// renderbuffers and, if the attached images are a mix of renderbuffers
    184 		// and textures, the value of RENDERBUFFER_SAMPLES is zero."
    185 		//
    186 		// On creating a renderbuffer: "If _samples_ is zero, then
    187 		// RENDERBUFFER_SAMPLES is set to zero. Otherwise [...] the resulting
    188 		// value for RENDERBUFFER_SAMPLES is guaranteed to be greater than or
    189 		// equal to _samples_ and no more than the next larger sample count
    190 		// supported by the implementation."
    191 
    192 		// Either all attachments are zero-sample renderbuffers and/or
    193 		// textures, or none of them are.
    194 		require((m_numSamples == 0) == (imgSamples == 0),
    195 				GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
    196 
    197 		// If the attachments requested a different number of samples, the
    198 		// implementation is allowed to report this as incomplete. However, it
    199 		// is also possible that despite the different requests, the
    200 		// implementation allocated the same number of samples to both. Hence
    201 		// reporting the framebuffer as complete is also legal.
    202 		canRequire(m_numSamples == imgSamples,
    203 				   GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
    204 	}
    205 
    206 	// "Depth and stencil attachments, if present, are the same image."
    207 	if (attPoint == GL_DEPTH_ATTACHMENT || attPoint == GL_STENCIL_ATTACHMENT)
    208 	{
    209 		if (m_depthStencilImage == 0)
    210 		{
    211 			m_depthStencilImage = att.imageName;
    212 			m_depthStencilType = attachmentType(att);
    213 		}
    214 		else
    215 			require(m_depthStencilImage == att.imageName &&
    216 					m_depthStencilType == attachmentType(att),
    217 					GL_FRAMEBUFFER_UNSUPPORTED);
    218 	}
    219 }
    220 
    221 struct NumLayersParams
    222 {
    223 	GLenum		textureKind;		//< GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY
    224 	GLsizei		numLayers;			//< Number of layers in texture
    225 	GLsizei		attachmentLayer;	//< Layer referenced by attachment
    226 
    227 	static string	getName			(const NumLayersParams& params);
    228 	static string	getDescription	(const NumLayersParams& params);
    229 };
    230 
    231 string NumLayersParams::getName (const NumLayersParams& params)
    232 {
    233 	ostringstream os;
    234 	const string kindStr = params.textureKind == GL_TEXTURE_3D ? "3d" : "2darr";
    235 	os << kindStr << "_" << params.numLayers << "_" << params.attachmentLayer;
    236 	return os.str();
    237 }
    238 
    239 string NumLayersParams::getDescription (const NumLayersParams& params)
    240 {
    241 	ostringstream os;
    242 	const string kindStr = (params.textureKind == GL_TEXTURE_3D
    243 							? "3D Texture"
    244 							: "2D Array Texture");
    245 	os << kindStr + ", "
    246 	   << params.numLayers << " layers, "
    247 	   << "attached layer " << params.attachmentLayer << ".";
    248 	return os.str();
    249 }
    250 
    251 class NumLayersTest : public fboc::ParamTest<NumLayersParams>
    252 {
    253 public:
    254 					NumLayersTest		(fboc::Context& ctx, NumLayersParams param)
    255 						: fboc::ParamTest<NumLayersParams> (ctx, param) {}
    256 
    257 	IterateResult	build				(FboBuilder& builder);
    258 };
    259 
    260 IterateResult NumLayersTest::build (FboBuilder& builder)
    261 {
    262 	TextureLayered* texCfg = DE_NULL;
    263 	const GLenum target = GL_COLOR_ATTACHMENT0;
    264 
    265 	switch (m_params.textureKind)
    266 	{
    267 		case GL_TEXTURE_3D:
    268 			texCfg = &builder.makeConfig<Texture3D>();
    269 			break;
    270 		case GL_TEXTURE_2D_ARRAY:
    271 			texCfg = &builder.makeConfig<Texture2DArray>();
    272 			break;
    273 		default:
    274 			DE_ASSERT(!"Impossible case");
    275 	}
    276 	texCfg->internalFormat = getDefaultFormat(target, GL_TEXTURE);
    277 	texCfg->width = 64;
    278 	texCfg->height = 64;
    279 	texCfg->numLayers = m_params.numLayers;
    280 	const GLuint tex = builder.glCreateTexture(*texCfg);
    281 
    282 	TextureLayerAttachment* att = &builder.makeConfig<TextureLayerAttachment>();
    283 	att->layer = m_params.attachmentLayer;
    284 	att->imageName = tex;
    285 
    286 	builder.glAttach(target, att);
    287 
    288 	return STOP;
    289 }
    290 
    291 enum
    292 {
    293 	SAMPLES_NONE = -2,
    294 	SAMPLES_TEXTURE = -1
    295 };
    296 struct NumSamplesParams
    297 {
    298 	// >= 0: renderbuffer with N samples, -1: texture, -2: no attachment
    299 	GLsizei		numSamples[3];
    300 
    301 	static string	getName			(const NumSamplesParams& params);
    302 	static string	getDescription	(const NumSamplesParams& params);
    303 };
    304 
    305 string NumSamplesParams::getName (const NumSamplesParams& params)
    306 {
    307 	ostringstream os;
    308 	bool first = true;
    309 	for (const GLsizei* ns	=	DE_ARRAY_BEGIN(params.numSamples);
    310 		 ns 				!=	DE_ARRAY_END(params.numSamples);
    311 		 ns++)
    312 	{
    313 		if (first)
    314 			first = false;
    315 		else
    316 			os << "_";
    317 
    318 		if (*ns == SAMPLES_NONE)
    319 			os << "none";
    320 		else if (*ns == SAMPLES_TEXTURE)
    321 			os << "tex";
    322 		else
    323 			os << "rbo" << *ns;
    324 	}
    325 	return os.str();
    326 }
    327 
    328 string NumSamplesParams::getDescription (const NumSamplesParams& params)
    329 {
    330 	ostringstream os;
    331 	bool first = true;
    332 	static const char* const s_names[] = { "color", "depth", "stencil" };
    333 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == DE_LENGTH_OF_ARRAY(params.numSamples));
    334 
    335 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_names); i++)
    336 	{
    337 		GLsizei ns = params.numSamples[i];
    338 
    339 		if (ns == SAMPLES_NONE)
    340 			continue;
    341 
    342 		if (first)
    343 			first = false;
    344 		else
    345 			os << ", ";
    346 
    347 		if (ns == SAMPLES_TEXTURE)
    348 			os << "texture " << s_names[i] << " attachment";
    349 		else
    350 			os << ns << "-sample renderbuffer " << s_names[i] << " attachment";
    351 	}
    352 	return os.str();
    353 }
    354 
    355 class NumSamplesTest : public fboc::ParamTest<NumSamplesParams>
    356 {
    357 public:
    358 					NumSamplesTest		(fboc::Context& ctx, NumSamplesParams param)
    359 						: fboc::ParamTest<NumSamplesParams> (ctx, param) {}
    360 
    361 	IterateResult	build				(FboBuilder& builder);
    362 };
    363 
    364 IterateResult NumSamplesTest::build (FboBuilder& builder)
    365 {
    366 	static const GLenum s_targets[] =
    367 		{
    368 			GL_COLOR_ATTACHMENT0,	GL_COLOR_ATTACHMENT1,	GL_DEPTH_ATTACHMENT,
    369 		};
    370 	// Non-integer formats for each attachment type.
    371 	// \todo [2013-12-17 lauri] Add fixed/floating/integer metadata for formats so
    372 	// we can pick one smartly or maybe try several.
    373 	static const GLenum s_formats[] =
    374 		{
    375 			GL_RGBA8,				GL_RGB565,				GL_DEPTH_COMPONENT24,
    376 		};
    377 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_targets) == DE_LENGTH_OF_ARRAY(m_params.numSamples));
    378 
    379 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_targets); i++)
    380 	{
    381 		const GLenum target = s_targets[i];
    382 		const ImageFormat fmt = { s_formats[i], GL_NONE };
    383 
    384 		const GLsizei ns = m_params.numSamples[i];
    385 		if (ns == -2)
    386 			continue;
    387 
    388 		if (ns == -1)
    389 		{
    390 			attachTargetToNew(target, GL_TEXTURE, fmt, 64, 64, builder);
    391 		}
    392 		else
    393 		{
    394 			Renderbuffer& rboCfg = builder.makeConfig<Renderbuffer>();
    395 			rboCfg.internalFormat = fmt;
    396 			rboCfg.width = rboCfg.height = 64;
    397 			rboCfg.numSamples = ns;
    398 
    399 			const GLuint rbo = builder.glCreateRbo(rboCfg);
    400 			// Implementations do not necessarily support sample sizes greater than 1.
    401 			TCU_CHECK_AND_THROW(NotSupportedError,
    402 								builder.getError() != GL_INVALID_OPERATION,
    403 								"Unsupported number of samples");
    404 			RenderbufferAttachment& att = builder.makeConfig<RenderbufferAttachment>();
    405 			att.imageName = rbo;
    406 			builder.glAttach(target, &att);
    407 		}
    408 	}
    409 
    410 	return STOP;
    411 }
    412 
    413 class ES3CheckerFactory : public CheckerFactory
    414 {
    415 public:
    416 	Checker*			createChecker	(void) { return new ES3Checker(); }
    417 };
    418 
    419 class TestGroup : public TestCaseGroup
    420 {
    421 public:
    422 						TestGroup		(Context& context);
    423 	void				init			(void);
    424 private:
    425 	ES3CheckerFactory	m_checkerFactory;
    426 	fboc::Context		m_fboc;
    427 };
    428 
    429 void TestGroup::init (void)
    430 {
    431 	addChild(m_fboc.createRenderableTests());
    432 	addChild(m_fboc.createAttachmentTests());
    433 	addChild(m_fboc.createSizeTests());
    434 
    435 	TestCaseGroup* layerTests = new TestCaseGroup(
    436 		getContext(), "layer", "Tests for layer attachments");
    437 
    438 	static const NumLayersParams s_layersParams[] =
    439 		{ //  textureKind			numLayers	attachmentKind
    440 			{ GL_TEXTURE_2D_ARRAY,	1,			0 },
    441 			{ GL_TEXTURE_2D_ARRAY,	1,			3 },
    442 			{ GL_TEXTURE_2D_ARRAY,	4,			3 },
    443 			{ GL_TEXTURE_2D_ARRAY,	4,			15 },
    444 			{ GL_TEXTURE_3D,		1,			0 },
    445 			{ GL_TEXTURE_3D,		1,			15 },
    446 			{ GL_TEXTURE_3D,		4,			15 },
    447 			{ GL_TEXTURE_3D,		64,			15 },
    448 		};
    449 
    450 	for (const NumLayersParams* lp	=	DE_ARRAY_BEGIN(s_layersParams);
    451 		 lp							!=  DE_ARRAY_END(s_layersParams);
    452 		 ++lp)
    453 		layerTests->addChild(new NumLayersTest(m_fboc, *lp));
    454 
    455 	addChild(layerTests);
    456 
    457 	TestCaseGroup* sampleTests = new TestCaseGroup(
    458 		getContext(), "samples", "Tests for multisample attachments");
    459 
    460 	static const NumSamplesParams s_samplesParams[] =
    461 	{
    462 		{ { 0,					SAMPLES_NONE,		SAMPLES_NONE } },
    463 		{ { 1,					SAMPLES_NONE,		SAMPLES_NONE } },
    464 		{ { 2,					SAMPLES_NONE,		SAMPLES_NONE } },
    465 		{ { 0,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
    466 		{ { 1,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
    467 		{ { 2,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
    468 		{ { 2,					1,					SAMPLES_NONE } },
    469 		{ { 2,					2,					SAMPLES_NONE } },
    470 		{ { 0,					0,					SAMPLES_TEXTURE } },
    471 		{ { 1,					2,					0 } },
    472 		{ { 2,					2,					0 } },
    473 		{ { 1,					1,					1 } },
    474 		{ { 1,					2,					4 } },
    475 	};
    476 
    477 	for (const NumSamplesParams* lp	=	DE_ARRAY_BEGIN(s_samplesParams);
    478 		 lp							!=  DE_ARRAY_END(s_samplesParams);
    479 		 ++lp)
    480 		sampleTests->addChild(new NumSamplesTest(m_fboc, *lp));
    481 
    482 	addChild(sampleTests);
    483 }
    484 
    485 TestGroup::TestGroup (Context& ctx)
    486 	: TestCaseGroup		(ctx, "completeness", "Completeness tests")
    487 	, m_checkerFactory	()
    488 	, m_fboc			(ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory)
    489 {
    490 	const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es3Formats);
    491 	const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es3ExtFormats);
    492 
    493 	m_fboc.addFormats(stdRange);
    494 	m_fboc.addExtFormats(extRange);
    495 	m_fboc.setHaveMulticolorAtts(true); // Vanilla ES3 has multiple color attachments
    496 }
    497 
    498 tcu::TestCaseGroup* createFboCompletenessTests (Context& context)
    499 {
    500 	return new TestGroup(context);
    501 }
    502 
    503 } // Functional
    504 } // gles3
    505 } // deqp
    506