x11: Fix deadlock
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fFboCompletenessTests.cpp
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