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