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 // GL_EXT_render_snorm
    140 static const FormatKey s_extRenderSnorm[] =
    141 {
    142 	GL_R8_SNORM, GL_RG8_SNORM, GL_RGBA8_SNORM,
    143 };
    144 
    145 static const FormatExtEntry s_es3ExtFormats[] =
    146 {
    147 	{
    148 		"GL_EXT_color_buffer_float",
    149 		// These are already texture-valid in ES3, the extension just adds RBO
    150 		// support and makes them color-renderable.
    151 		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
    152 		GLS_ARRAY_RANGE(s_extColorBufferFloatFormats)
    153 	},
    154 	{
    155 		"GL_OES_texture_stencil8",
    156 		// \note: es3 RBO tests actually cover the first two requirements
    157 		// - kept here for completeness
    158 		(deUint32)(REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
    159 		GLS_ARRAY_RANGE(s_extOESTextureStencil8)
    160 	},
    161 
    162 	// Since GLES31 is backwards compatible to GLES3, we might actually be running on a GLES31.
    163 	// Add rule changes of GLES31 that have no corresponding GLES3 extension.
    164 	//
    165 	// \note Not all feature changes are listed here but only those that alter GLES3 subset of
    166 	//       the formats
    167 	{
    168 		"DEQP_gles31_core_compatible GL_EXT_render_snorm",
    169 		(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID | RENDERBUFFER_VALID),
    170 		GLS_ARRAY_RANGE(s_extRenderSnorm)
    171 	},
    172 };
    173 
    174 class ES3Checker : public Checker
    175 {
    176 public:
    177 				ES3Checker	(const glu::RenderContext& ctx)
    178 					: Checker				(ctx)
    179 					, m_numSamples			(-1)
    180 					, m_depthStencilImage	(0)
    181 					, m_depthStencilType	(GL_NONE) {}
    182 	void		check		(GLenum attPoint, const Attachment& att, const Image* image);
    183 
    184 private:
    185 	//! The common number of samples of images.
    186 	GLsizei		m_numSamples;
    187 
    188 	//! The common image for depth and stencil attachments.
    189 	GLuint		m_depthStencilImage;
    190 	GLenum		m_depthStencilType;
    191 };
    192 
    193 void ES3Checker::check (GLenum attPoint, const Attachment& att, const Image* image)
    194 {
    195 	GLsizei imgSamples = imageNumSamples(*image);
    196 
    197 	if (m_numSamples == -1)
    198 	{
    199 		m_numSamples = imgSamples;
    200 	}
    201 	else
    202 	{
    203 		// GLES3: "The value of RENDERBUFFER_SAMPLES is the same for all attached
    204 		// renderbuffers and, if the attached images are a mix of renderbuffers
    205 		// and textures, the value of RENDERBUFFER_SAMPLES is zero."
    206 		//
    207 		// On creating a renderbuffer: "If _samples_ is zero, then
    208 		// RENDERBUFFER_SAMPLES is set to zero. Otherwise [...] the resulting
    209 		// value for RENDERBUFFER_SAMPLES is guaranteed to be greater than or
    210 		// equal to _samples_ and no more than the next larger sample count
    211 		// supported by the implementation."
    212 
    213 		// Either all attachments are zero-sample renderbuffers and/or
    214 		// textures, or none of them are.
    215 		if ((m_numSamples == 0) != (imgSamples == 0))
    216 			addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Mixed multi- and single-sampled attachments");
    217 
    218 		// If the attachments requested a different number of samples, the
    219 		// implementation is allowed to report this as incomplete. However, it
    220 		// is also possible that despite the different requests, the
    221 		// implementation allocated the same number of samples to both. Hence
    222 		// reporting the framebuffer as complete is also legal.
    223 		if (m_numSamples != imgSamples)
    224 			addPotentialFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Number of samples differ");
    225 	}
    226 
    227 	// "Depth and stencil attachments, if present, are the same image."
    228 	if (attPoint == GL_DEPTH_ATTACHMENT || attPoint == GL_STENCIL_ATTACHMENT)
    229 	{
    230 		if (m_depthStencilImage == 0)
    231 		{
    232 			m_depthStencilImage = att.imageName;
    233 			m_depthStencilType = attachmentType(att);
    234 		}
    235 		else
    236 		{
    237 			if (m_depthStencilImage != att.imageName || m_depthStencilType != attachmentType(att))
    238 				addFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Depth and stencil attachments are not the same image");
    239 		}
    240 	}
    241 }
    242 
    243 struct NumLayersParams
    244 {
    245 	GLenum		textureKind;		//< GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY
    246 	GLsizei		numLayers;			//< Number of layers in texture
    247 	GLsizei		attachmentLayer;	//< Layer referenced by attachment
    248 
    249 	static string	getName			(const NumLayersParams& params);
    250 	static string	getDescription	(const NumLayersParams& params);
    251 };
    252 
    253 string NumLayersParams::getName (const NumLayersParams& params)
    254 {
    255 	ostringstream os;
    256 	const string kindStr = params.textureKind == GL_TEXTURE_3D ? "3d" : "2darr";
    257 	os << kindStr << "_" << params.numLayers << "_" << params.attachmentLayer;
    258 	return os.str();
    259 }
    260 
    261 string NumLayersParams::getDescription (const NumLayersParams& params)
    262 {
    263 	ostringstream os;
    264 	const string kindStr = (params.textureKind == GL_TEXTURE_3D
    265 							? "3D Texture"
    266 							: "2D Array Texture");
    267 	os << kindStr + ", "
    268 	   << params.numLayers << " layers, "
    269 	   << "attached layer " << params.attachmentLayer << ".";
    270 	return os.str();
    271 }
    272 
    273 class NumLayersTest : public fboc::ParamTest<NumLayersParams>
    274 {
    275 public:
    276 					NumLayersTest		(fboc::Context& ctx, NumLayersParams param)
    277 						: fboc::ParamTest<NumLayersParams> (ctx, param) {}
    278 
    279 	IterateResult	build				(FboBuilder& builder);
    280 };
    281 
    282 IterateResult NumLayersTest::build (FboBuilder& builder)
    283 {
    284 	TextureLayered* texCfg = DE_NULL;
    285 	const GLenum target = GL_COLOR_ATTACHMENT0;
    286 
    287 	switch (m_params.textureKind)
    288 	{
    289 		case GL_TEXTURE_3D:
    290 			texCfg = &builder.makeConfig<Texture3D>();
    291 			break;
    292 		case GL_TEXTURE_2D_ARRAY:
    293 			texCfg = &builder.makeConfig<Texture2DArray>();
    294 			break;
    295 		default:
    296 			DE_FATAL("Impossible case");
    297 	}
    298 	texCfg->internalFormat = getDefaultFormat(target, GL_TEXTURE);
    299 	texCfg->width = 64;
    300 	texCfg->height = 64;
    301 	texCfg->numLayers = m_params.numLayers;
    302 	const GLuint tex = builder.glCreateTexture(*texCfg);
    303 
    304 	TextureLayerAttachment* att = &builder.makeConfig<TextureLayerAttachment>();
    305 	att->layer = m_params.attachmentLayer;
    306 	att->imageName = tex;
    307 
    308 	builder.glAttach(target, att);
    309 
    310 	return STOP;
    311 }
    312 
    313 enum
    314 {
    315 	SAMPLES_NONE = -2,
    316 	SAMPLES_TEXTURE = -1
    317 };
    318 struct NumSamplesParams
    319 {
    320 	// >= 0: renderbuffer with N samples, -1: texture, -2: no attachment
    321 	GLsizei		numSamples[3];
    322 
    323 	static string	getName			(const NumSamplesParams& params);
    324 	static string	getDescription	(const NumSamplesParams& params);
    325 };
    326 
    327 string NumSamplesParams::getName (const NumSamplesParams& params)
    328 {
    329 	ostringstream os;
    330 	bool first = true;
    331 	for (const GLsizei* ns	=	DE_ARRAY_BEGIN(params.numSamples);
    332 		 ns					!=	DE_ARRAY_END(params.numSamples);
    333 		 ns++)
    334 	{
    335 		if (first)
    336 			first = false;
    337 		else
    338 			os << "_";
    339 
    340 		if (*ns == SAMPLES_NONE)
    341 			os << "none";
    342 		else if (*ns == SAMPLES_TEXTURE)
    343 			os << "tex";
    344 		else
    345 			os << "rbo" << *ns;
    346 	}
    347 	return os.str();
    348 }
    349 
    350 string NumSamplesParams::getDescription (const NumSamplesParams& params)
    351 {
    352 	ostringstream os;
    353 	bool first = true;
    354 	static const char* const s_names[] = { "color", "depth", "stencil" };
    355 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == DE_LENGTH_OF_ARRAY(params.numSamples));
    356 
    357 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_names); i++)
    358 	{
    359 		GLsizei ns = params.numSamples[i];
    360 
    361 		if (ns == SAMPLES_NONE)
    362 			continue;
    363 
    364 		if (first)
    365 			first = false;
    366 		else
    367 			os << ", ";
    368 
    369 		if (ns == SAMPLES_TEXTURE)
    370 			os << "texture " << s_names[i] << " attachment";
    371 		else
    372 			os << ns << "-sample renderbuffer " << s_names[i] << " attachment";
    373 	}
    374 	return os.str();
    375 }
    376 
    377 class NumSamplesTest : public fboc::ParamTest<NumSamplesParams>
    378 {
    379 public:
    380 					NumSamplesTest		(fboc::Context& ctx, NumSamplesParams param)
    381 						: fboc::ParamTest<NumSamplesParams> (ctx, param) {}
    382 
    383 	IterateResult	build				(FboBuilder& builder);
    384 };
    385 
    386 IterateResult NumSamplesTest::build (FboBuilder& builder)
    387 {
    388 	static const GLenum s_targets[] =
    389 		{
    390 			GL_COLOR_ATTACHMENT0,	GL_COLOR_ATTACHMENT1,	GL_DEPTH_ATTACHMENT,
    391 		};
    392 	// Non-integer formats for each attachment type.
    393 	// \todo [2013-12-17 lauri] Add fixed/floating/integer metadata for formats so
    394 	// we can pick one smartly or maybe try several.
    395 	static const GLenum s_formats[] =
    396 		{
    397 			GL_RGBA8,				GL_RGB565,				GL_DEPTH_COMPONENT24,
    398 		};
    399 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_targets) == DE_LENGTH_OF_ARRAY(m_params.numSamples));
    400 
    401 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_targets); i++)
    402 	{
    403 		const GLenum target = s_targets[i];
    404 		const ImageFormat fmt = { s_formats[i], GL_NONE };
    405 
    406 		const GLsizei ns = m_params.numSamples[i];
    407 		if (ns == -2)
    408 			continue;
    409 
    410 		if (ns == -1)
    411 		{
    412 			attachTargetToNew(target, GL_TEXTURE, fmt, 64, 64, builder);
    413 		}
    414 		else
    415 		{
    416 			Renderbuffer& rboCfg = builder.makeConfig<Renderbuffer>();
    417 			rboCfg.internalFormat = fmt;
    418 			rboCfg.width = rboCfg.height = 64;
    419 			rboCfg.numSamples = ns;
    420 
    421 			const GLuint rbo = builder.glCreateRbo(rboCfg);
    422 			// Implementations do not necessarily support sample sizes greater than 1.
    423 			TCU_CHECK_AND_THROW(NotSupportedError,
    424 								builder.getError() != GL_INVALID_OPERATION,
    425 								"Unsupported number of samples");
    426 			RenderbufferAttachment& att = builder.makeConfig<RenderbufferAttachment>();
    427 			att.imageName = rbo;
    428 			builder.glAttach(target, &att);
    429 		}
    430 	}
    431 
    432 	return STOP;
    433 }
    434 
    435 class ES3CheckerFactory : public CheckerFactory
    436 {
    437 public:
    438 	Checker*			createChecker	(const glu::RenderContext& ctx) { return new ES3Checker(ctx); }
    439 };
    440 
    441 class TestGroup : public TestCaseGroup
    442 {
    443 public:
    444 						TestGroup		(Context& context);
    445 	void				init			(void);
    446 private:
    447 	ES3CheckerFactory	m_checkerFactory;
    448 	fboc::Context		m_fboc;
    449 };
    450 
    451 void TestGroup::init (void)
    452 {
    453 	addChild(m_fboc.createRenderableTests());
    454 	addChild(m_fboc.createAttachmentTests());
    455 	addChild(m_fboc.createSizeTests());
    456 
    457 	TestCaseGroup* layerTests = new TestCaseGroup(
    458 		getContext(), "layer", "Tests for layer attachments");
    459 
    460 	static const NumLayersParams s_layersParams[] =
    461 		{ //  textureKind			numLayers	attachmentKind
    462 			{ GL_TEXTURE_2D_ARRAY,	1,			0 },
    463 			{ GL_TEXTURE_2D_ARRAY,	1,			3 },
    464 			{ GL_TEXTURE_2D_ARRAY,	4,			3 },
    465 			{ GL_TEXTURE_2D_ARRAY,	4,			15 },
    466 			{ GL_TEXTURE_3D,		1,			0 },
    467 			{ GL_TEXTURE_3D,		1,			15 },
    468 			{ GL_TEXTURE_3D,		4,			15 },
    469 			{ GL_TEXTURE_3D,		64,			15 },
    470 		};
    471 
    472 	for (const NumLayersParams* lp	=	DE_ARRAY_BEGIN(s_layersParams);
    473 		 lp							!=  DE_ARRAY_END(s_layersParams);
    474 		 ++lp)
    475 		layerTests->addChild(new NumLayersTest(m_fboc, *lp));
    476 
    477 	addChild(layerTests);
    478 
    479 	TestCaseGroup* sampleTests = new TestCaseGroup(
    480 		getContext(), "samples", "Tests for multisample attachments");
    481 
    482 	static const NumSamplesParams s_samplesParams[] =
    483 	{
    484 		{ { 0,					SAMPLES_NONE,		SAMPLES_NONE } },
    485 		{ { 1,					SAMPLES_NONE,		SAMPLES_NONE } },
    486 		{ { 2,					SAMPLES_NONE,		SAMPLES_NONE } },
    487 		{ { 0,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
    488 		{ { 1,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
    489 		{ { 2,					SAMPLES_TEXTURE,	SAMPLES_NONE } },
    490 		{ { 2,					1,					SAMPLES_NONE } },
    491 		{ { 2,					2,					SAMPLES_NONE } },
    492 		{ { 0,					0,					SAMPLES_TEXTURE } },
    493 		{ { 1,					2,					0 } },
    494 		{ { 2,					2,					0 } },
    495 		{ { 1,					1,					1 } },
    496 		{ { 1,					2,					4 } },
    497 	};
    498 
    499 	for (const NumSamplesParams* lp	=	DE_ARRAY_BEGIN(s_samplesParams);
    500 		 lp							!=  DE_ARRAY_END(s_samplesParams);
    501 		 ++lp)
    502 		sampleTests->addChild(new NumSamplesTest(m_fboc, *lp));
    503 
    504 	addChild(sampleTests);
    505 }
    506 
    507 TestGroup::TestGroup (Context& ctx)
    508 	: TestCaseGroup		(ctx, "completeness", "Completeness tests")
    509 	, m_checkerFactory	()
    510 	, m_fboc			(ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory)
    511 {
    512 	const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es3Formats);
    513 	const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es3ExtFormats);
    514 
    515 	m_fboc.addFormats(stdRange);
    516 	m_fboc.addExtFormats(extRange);
    517 	m_fboc.setHaveMulticolorAtts(true); // Vanilla ES3 has multiple color attachments
    518 }
    519 
    520 tcu::TestCaseGroup* createFboCompletenessTests (Context& context)
    521 {
    522 	return new TestGroup(context);
    523 }
    524 
    525 } // Functional
    526 } // gles3
    527 } // deqp
    528