es3fFboCompletenessTests.cpp revision b5c60b02e542a61a2b658272034c830f92b4c766
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 29using namespace glw; 30using deqp::gls::Range; 31using namespace deqp::gls::FboUtil; 32using namespace deqp::gls::FboUtil::config; 33namespace fboc = deqp::gls::fboc; 34typedef tcu::TestCase::IterateResult IterateResult; 35using std::string; 36using std::ostringstream; 37 38namespace deqp 39{ 40namespace gles3 41{ 42namespace Functional 43{ 44 45static 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 56static 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 67static 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 75static 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 82static 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 89static 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 96static 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 104static 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 128static 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 134static const FormatKey s_extOESTextureStencil8[] = 135{ 136 GL_STENCIL_INDEX8, 137}; 138 139 140static 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 154class ES3Checker : public Checker 155{ 156public: 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 163private: 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 172void 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 if ((m_numSamples == 0) != (imgSamples == 0)) 195 addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Mixed multi- and single-sampled attachments"); 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 if (m_numSamples != imgSamples) 203 addPotentialFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Number of samples differ"); 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 { 216 if (m_depthStencilImage != att.imageName || m_depthStencilType != attachmentType(att)) 217 addFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Depth and stencil attachments are not the same image"); 218 } 219 } 220} 221 222struct NumLayersParams 223{ 224 GLenum textureKind; //< GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY 225 GLsizei numLayers; //< Number of layers in texture 226 GLsizei attachmentLayer; //< Layer referenced by attachment 227 228 static string getName (const NumLayersParams& params); 229 static string getDescription (const NumLayersParams& params); 230}; 231 232string NumLayersParams::getName (const NumLayersParams& params) 233{ 234 ostringstream os; 235 const string kindStr = params.textureKind == GL_TEXTURE_3D ? "3d" : "2darr"; 236 os << kindStr << "_" << params.numLayers << "_" << params.attachmentLayer; 237 return os.str(); 238} 239 240string NumLayersParams::getDescription (const NumLayersParams& params) 241{ 242 ostringstream os; 243 const string kindStr = (params.textureKind == GL_TEXTURE_3D 244 ? "3D Texture" 245 : "2D Array Texture"); 246 os << kindStr + ", " 247 << params.numLayers << " layers, " 248 << "attached layer " << params.attachmentLayer << "."; 249 return os.str(); 250} 251 252class NumLayersTest : public fboc::ParamTest<NumLayersParams> 253{ 254public: 255 NumLayersTest (fboc::Context& ctx, NumLayersParams param) 256 : fboc::ParamTest<NumLayersParams> (ctx, param) {} 257 258 IterateResult build (FboBuilder& builder); 259}; 260 261IterateResult NumLayersTest::build (FboBuilder& builder) 262{ 263 TextureLayered* texCfg = DE_NULL; 264 const GLenum target = GL_COLOR_ATTACHMENT0; 265 266 switch (m_params.textureKind) 267 { 268 case GL_TEXTURE_3D: 269 texCfg = &builder.makeConfig<Texture3D>(); 270 break; 271 case GL_TEXTURE_2D_ARRAY: 272 texCfg = &builder.makeConfig<Texture2DArray>(); 273 break; 274 default: 275 DE_ASSERT(!"Impossible case"); 276 } 277 texCfg->internalFormat = getDefaultFormat(target, GL_TEXTURE); 278 texCfg->width = 64; 279 texCfg->height = 64; 280 texCfg->numLayers = m_params.numLayers; 281 const GLuint tex = builder.glCreateTexture(*texCfg); 282 283 TextureLayerAttachment* att = &builder.makeConfig<TextureLayerAttachment>(); 284 att->layer = m_params.attachmentLayer; 285 att->imageName = tex; 286 287 builder.glAttach(target, att); 288 289 return STOP; 290} 291 292enum 293{ 294 SAMPLES_NONE = -2, 295 SAMPLES_TEXTURE = -1 296}; 297struct NumSamplesParams 298{ 299 // >= 0: renderbuffer with N samples, -1: texture, -2: no attachment 300 GLsizei numSamples[3]; 301 302 static string getName (const NumSamplesParams& params); 303 static string getDescription (const NumSamplesParams& params); 304}; 305 306string NumSamplesParams::getName (const NumSamplesParams& params) 307{ 308 ostringstream os; 309 bool first = true; 310 for (const GLsizei* ns = DE_ARRAY_BEGIN(params.numSamples); 311 ns != DE_ARRAY_END(params.numSamples); 312 ns++) 313 { 314 if (first) 315 first = false; 316 else 317 os << "_"; 318 319 if (*ns == SAMPLES_NONE) 320 os << "none"; 321 else if (*ns == SAMPLES_TEXTURE) 322 os << "tex"; 323 else 324 os << "rbo" << *ns; 325 } 326 return os.str(); 327} 328 329string NumSamplesParams::getDescription (const NumSamplesParams& params) 330{ 331 ostringstream os; 332 bool first = true; 333 static const char* const s_names[] = { "color", "depth", "stencil" }; 334 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == DE_LENGTH_OF_ARRAY(params.numSamples)); 335 336 for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_names); i++) 337 { 338 GLsizei ns = params.numSamples[i]; 339 340 if (ns == SAMPLES_NONE) 341 continue; 342 343 if (first) 344 first = false; 345 else 346 os << ", "; 347 348 if (ns == SAMPLES_TEXTURE) 349 os << "texture " << s_names[i] << " attachment"; 350 else 351 os << ns << "-sample renderbuffer " << s_names[i] << " attachment"; 352 } 353 return os.str(); 354} 355 356class NumSamplesTest : public fboc::ParamTest<NumSamplesParams> 357{ 358public: 359 NumSamplesTest (fboc::Context& ctx, NumSamplesParams param) 360 : fboc::ParamTest<NumSamplesParams> (ctx, param) {} 361 362 IterateResult build (FboBuilder& builder); 363}; 364 365IterateResult NumSamplesTest::build (FboBuilder& builder) 366{ 367 static const GLenum s_targets[] = 368 { 369 GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_DEPTH_ATTACHMENT, 370 }; 371 // Non-integer formats for each attachment type. 372 // \todo [2013-12-17 lauri] Add fixed/floating/integer metadata for formats so 373 // we can pick one smartly or maybe try several. 374 static const GLenum s_formats[] = 375 { 376 GL_RGBA8, GL_RGB565, GL_DEPTH_COMPONENT24, 377 }; 378 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_targets) == DE_LENGTH_OF_ARRAY(m_params.numSamples)); 379 380 for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_targets); i++) 381 { 382 const GLenum target = s_targets[i]; 383 const ImageFormat fmt = { s_formats[i], GL_NONE }; 384 385 const GLsizei ns = m_params.numSamples[i]; 386 if (ns == -2) 387 continue; 388 389 if (ns == -1) 390 { 391 attachTargetToNew(target, GL_TEXTURE, fmt, 64, 64, builder); 392 } 393 else 394 { 395 Renderbuffer& rboCfg = builder.makeConfig<Renderbuffer>(); 396 rboCfg.internalFormat = fmt; 397 rboCfg.width = rboCfg.height = 64; 398 rboCfg.numSamples = ns; 399 400 const GLuint rbo = builder.glCreateRbo(rboCfg); 401 // Implementations do not necessarily support sample sizes greater than 1. 402 TCU_CHECK_AND_THROW(NotSupportedError, 403 builder.getError() != GL_INVALID_OPERATION, 404 "Unsupported number of samples"); 405 RenderbufferAttachment& att = builder.makeConfig<RenderbufferAttachment>(); 406 att.imageName = rbo; 407 builder.glAttach(target, &att); 408 } 409 } 410 411 return STOP; 412} 413 414class ES3CheckerFactory : public CheckerFactory 415{ 416public: 417 Checker* createChecker (void) { return new ES3Checker(); } 418}; 419 420class TestGroup : public TestCaseGroup 421{ 422public: 423 TestGroup (Context& context); 424 void init (void); 425private: 426 ES3CheckerFactory m_checkerFactory; 427 fboc::Context m_fboc; 428}; 429 430void TestGroup::init (void) 431{ 432 addChild(m_fboc.createRenderableTests()); 433 addChild(m_fboc.createAttachmentTests()); 434 addChild(m_fboc.createSizeTests()); 435 436 TestCaseGroup* layerTests = new TestCaseGroup( 437 getContext(), "layer", "Tests for layer attachments"); 438 439 static const NumLayersParams s_layersParams[] = 440 { // textureKind numLayers attachmentKind 441 { GL_TEXTURE_2D_ARRAY, 1, 0 }, 442 { GL_TEXTURE_2D_ARRAY, 1, 3 }, 443 { GL_TEXTURE_2D_ARRAY, 4, 3 }, 444 { GL_TEXTURE_2D_ARRAY, 4, 15 }, 445 { GL_TEXTURE_3D, 1, 0 }, 446 { GL_TEXTURE_3D, 1, 15 }, 447 { GL_TEXTURE_3D, 4, 15 }, 448 { GL_TEXTURE_3D, 64, 15 }, 449 }; 450 451 for (const NumLayersParams* lp = DE_ARRAY_BEGIN(s_layersParams); 452 lp != DE_ARRAY_END(s_layersParams); 453 ++lp) 454 layerTests->addChild(new NumLayersTest(m_fboc, *lp)); 455 456 addChild(layerTests); 457 458 TestCaseGroup* sampleTests = new TestCaseGroup( 459 getContext(), "samples", "Tests for multisample attachments"); 460 461 static const NumSamplesParams s_samplesParams[] = 462 { 463 { { 0, SAMPLES_NONE, SAMPLES_NONE } }, 464 { { 1, SAMPLES_NONE, SAMPLES_NONE } }, 465 { { 2, SAMPLES_NONE, SAMPLES_NONE } }, 466 { { 0, SAMPLES_TEXTURE, SAMPLES_NONE } }, 467 { { 1, SAMPLES_TEXTURE, SAMPLES_NONE } }, 468 { { 2, SAMPLES_TEXTURE, SAMPLES_NONE } }, 469 { { 2, 1, SAMPLES_NONE } }, 470 { { 2, 2, SAMPLES_NONE } }, 471 { { 0, 0, SAMPLES_TEXTURE } }, 472 { { 1, 2, 0 } }, 473 { { 2, 2, 0 } }, 474 { { 1, 1, 1 } }, 475 { { 1, 2, 4 } }, 476 }; 477 478 for (const NumSamplesParams* lp = DE_ARRAY_BEGIN(s_samplesParams); 479 lp != DE_ARRAY_END(s_samplesParams); 480 ++lp) 481 sampleTests->addChild(new NumSamplesTest(m_fboc, *lp)); 482 483 addChild(sampleTests); 484} 485 486TestGroup::TestGroup (Context& ctx) 487 : TestCaseGroup (ctx, "completeness", "Completeness tests") 488 , m_checkerFactory () 489 , m_fboc (ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory) 490{ 491 const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es3Formats); 492 const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es3ExtFormats); 493 494 m_fboc.addFormats(stdRange); 495 m_fboc.addExtFormats(extRange); 496 m_fboc.setHaveMulticolorAtts(true); // Vanilla ES3 has multiple color attachments 497} 498 499tcu::TestCaseGroup* createFboCompletenessTests (Context& context) 500{ 501 return new TestGroup(context); 502} 503 504} // Functional 505} // gles3 506} // deqp 507