You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
528 lines
16 KiB
528 lines
16 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL (ES) Module
|
|
* -----------------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Framebuffer completeness tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es3fFboCompletenessTests.hpp"
|
|
|
|
#include "glsFboCompletenessTests.hpp"
|
|
#include <sstream>
|
|
|
|
using namespace glw;
|
|
using deqp::gls::Range;
|
|
using namespace deqp::gls::FboUtil;
|
|
using namespace deqp::gls::FboUtil::config;
|
|
namespace fboc = deqp::gls::fboc;
|
|
typedef tcu::TestCase::IterateResult IterateResult;
|
|
using std::string;
|
|
using std::ostringstream;
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles3
|
|
{
|
|
namespace Functional
|
|
{
|
|
|
|
static const FormatKey s_es3ColorRenderables[] =
|
|
{
|
|
// GLES3, 4.4.4: "An internal format is color-renderable if it is one of
|
|
// the formats from table 3.12 noted as color-renderable..."
|
|
GL_R8, GL_RG8, GL_RGB8, GL_RGB565, GL_RGBA4, GL_RGB5_A1, GL_RGBA8,
|
|
GL_RGB10_A2, GL_RGB10_A2UI, GL_SRGB8_ALPHA8,
|
|
GL_R8I, GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI,
|
|
GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI,
|
|
GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI,
|
|
};
|
|
|
|
static const FormatKey s_es3UnsizedColorRenderables[] =
|
|
{
|
|
// "...or if it is unsized format RGBA or RGB."
|
|
// See Table 3.3 in GLES3.
|
|
GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_BYTE),
|
|
GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4),
|
|
GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1),
|
|
GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_BYTE),
|
|
GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_SHORT_5_6_5),
|
|
};
|
|
|
|
static const FormatKey s_es3DepthRenderables[] =
|
|
{
|
|
// GLES3, 4.4.4: "An internal format is depth-renderable if it is one of
|
|
// the formats from table 3.13."
|
|
GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32F,
|
|
GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8,
|
|
};
|
|
|
|
static const FormatKey s_es3StencilRboRenderables[] =
|
|
{
|
|
// GLES3, 4.4.4: "An internal format is stencil-renderable if it is
|
|
// STENCIL_INDEX8..."
|
|
GL_STENCIL_INDEX8,
|
|
};
|
|
|
|
static const FormatKey s_es3StencilRenderables[] =
|
|
{
|
|
// "...or one of the formats from table 3.13 whose base internal format is
|
|
// DEPTH_STENCIL."
|
|
GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8,
|
|
};
|
|
|
|
static const FormatKey s_es3TextureFloatFormats[] =
|
|
{
|
|
GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F,
|
|
GL_RG32F, GL_RG16F, GL_R32F, GL_R16F,
|
|
GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F,
|
|
};
|
|
|
|
static const FormatKey s_es3NotRenderableTextureFormats[] =
|
|
{
|
|
GL_R8_SNORM, GL_RG8_SNORM, GL_RGB8_SNORM, GL_RGBA8_SNORM,
|
|
GL_RGB9_E5, GL_SRGB8,
|
|
GL_RGB8I, GL_RGB16I, GL_RGB32I,
|
|
GL_RGB8UI, GL_RGB16UI,GL_RGB32UI,
|
|
};
|
|
|
|
static const FormatEntry s_es3Formats[] =
|
|
{
|
|
// Renderbuffers don't support unsized formats
|
|
{ REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID,
|
|
GLS_ARRAY_RANGE(s_es3UnsizedColorRenderables) },
|
|
{ REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
|
|
GLS_ARRAY_RANGE(s_es3ColorRenderables) },
|
|
{ REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
|
|
GLS_ARRAY_RANGE(s_es3DepthRenderables) },
|
|
{ REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID,
|
|
GLS_ARRAY_RANGE(s_es3StencilRboRenderables) },
|
|
{ REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID,
|
|
GLS_ARRAY_RANGE(s_es3StencilRenderables) },
|
|
{ TEXTURE_VALID,
|
|
GLS_ARRAY_RANGE(s_es3NotRenderableTextureFormats) },
|
|
|
|
// These are not color-renderable in vanilla ES3, but we need to mark them
|
|
// as valid for textures, since EXT_color_buffer_(half_)float brings in
|
|
// color-renderability and only renderbuffer-validity.
|
|
{ TEXTURE_VALID,
|
|
GLS_ARRAY_RANGE(s_es3TextureFloatFormats) },
|
|
};
|
|
|
|
// GL_EXT_color_buffer_float
|
|
static const FormatKey s_extColorBufferFloatFormats[] =
|
|
{
|
|
GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F,
|
|
};
|
|
|
|
// GL_OES_texture_stencil8
|
|
static const FormatKey s_extOESTextureStencil8[] =
|
|
{
|
|
GL_STENCIL_INDEX8,
|
|
};
|
|
|
|
// GL_EXT_render_snorm
|
|
static const FormatKey s_extRenderSnorm[] =
|
|
{
|
|
GL_R8_SNORM, GL_RG8_SNORM, GL_RGBA8_SNORM,
|
|
};
|
|
|
|
static const FormatExtEntry s_es3ExtFormats[] =
|
|
{
|
|
{
|
|
"GL_EXT_color_buffer_float",
|
|
// These are already texture-valid in ES3, the extension just adds RBO
|
|
// support and makes them color-renderable.
|
|
(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
|
|
GLS_ARRAY_RANGE(s_extColorBufferFloatFormats)
|
|
},
|
|
{
|
|
"GL_OES_texture_stencil8",
|
|
// \note: es3 RBO tests actually cover the first two requirements
|
|
// - kept here for completeness
|
|
(deUint32)(REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
|
|
GLS_ARRAY_RANGE(s_extOESTextureStencil8)
|
|
},
|
|
|
|
// Since GLES31 is backwards compatible to GLES3, we might actually be running on a GLES31.
|
|
// Add rule changes of GLES31 that have no corresponding GLES3 extension.
|
|
//
|
|
// \note Not all feature changes are listed here but only those that alter GLES3 subset of
|
|
// the formats
|
|
{
|
|
"DEQP_gles31_core_compatible GL_EXT_render_snorm",
|
|
(deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID | RENDERBUFFER_VALID),
|
|
GLS_ARRAY_RANGE(s_extRenderSnorm)
|
|
},
|
|
};
|
|
|
|
class ES3Checker : public Checker
|
|
{
|
|
public:
|
|
ES3Checker (const glu::RenderContext& ctx)
|
|
: Checker (ctx)
|
|
, m_numSamples (-1)
|
|
, m_depthStencilImage (0)
|
|
, m_depthStencilType (GL_NONE) {}
|
|
void check (GLenum attPoint, const Attachment& att, const Image* image);
|
|
|
|
private:
|
|
//! The common number of samples of images.
|
|
GLsizei m_numSamples;
|
|
|
|
//! The common image for depth and stencil attachments.
|
|
GLuint m_depthStencilImage;
|
|
GLenum m_depthStencilType;
|
|
};
|
|
|
|
void ES3Checker::check (GLenum attPoint, const Attachment& att, const Image* image)
|
|
{
|
|
GLsizei imgSamples = imageNumSamples(*image);
|
|
|
|
if (m_numSamples == -1)
|
|
{
|
|
m_numSamples = imgSamples;
|
|
}
|
|
else
|
|
{
|
|
// GLES3: "The value of RENDERBUFFER_SAMPLES is the same for all attached
|
|
// renderbuffers and, if the attached images are a mix of renderbuffers
|
|
// and textures, the value of RENDERBUFFER_SAMPLES is zero."
|
|
//
|
|
// On creating a renderbuffer: "If _samples_ is zero, then
|
|
// RENDERBUFFER_SAMPLES is set to zero. Otherwise [...] the resulting
|
|
// value for RENDERBUFFER_SAMPLES is guaranteed to be greater than or
|
|
// equal to _samples_ and no more than the next larger sample count
|
|
// supported by the implementation."
|
|
|
|
// Either all attachments are zero-sample renderbuffers and/or
|
|
// textures, or none of them are.
|
|
if ((m_numSamples == 0) != (imgSamples == 0))
|
|
addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Mixed multi- and single-sampled attachments");
|
|
|
|
// If the attachments requested a different number of samples, the
|
|
// implementation is allowed to report this as incomplete. However, it
|
|
// is also possible that despite the different requests, the
|
|
// implementation allocated the same number of samples to both. Hence
|
|
// reporting the framebuffer as complete is also legal.
|
|
if (m_numSamples != imgSamples)
|
|
addPotentialFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Number of samples differ");
|
|
}
|
|
|
|
// "Depth and stencil attachments, if present, are the same image."
|
|
if (attPoint == GL_DEPTH_ATTACHMENT || attPoint == GL_STENCIL_ATTACHMENT)
|
|
{
|
|
if (m_depthStencilImage == 0)
|
|
{
|
|
m_depthStencilImage = att.imageName;
|
|
m_depthStencilType = attachmentType(att);
|
|
}
|
|
else
|
|
{
|
|
if (m_depthStencilImage != att.imageName || m_depthStencilType != attachmentType(att))
|
|
addFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Depth and stencil attachments are not the same image");
|
|
}
|
|
}
|
|
}
|
|
|
|
struct NumLayersParams
|
|
{
|
|
GLenum textureKind; //< GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY
|
|
GLsizei numLayers; //< Number of layers in texture
|
|
GLsizei attachmentLayer; //< Layer referenced by attachment
|
|
|
|
static string getName (const NumLayersParams& params);
|
|
static string getDescription (const NumLayersParams& params);
|
|
};
|
|
|
|
string NumLayersParams::getName (const NumLayersParams& params)
|
|
{
|
|
ostringstream os;
|
|
const string kindStr = params.textureKind == GL_TEXTURE_3D ? "3d" : "2darr";
|
|
os << kindStr << "_" << params.numLayers << "_" << params.attachmentLayer;
|
|
return os.str();
|
|
}
|
|
|
|
string NumLayersParams::getDescription (const NumLayersParams& params)
|
|
{
|
|
ostringstream os;
|
|
const string kindStr = (params.textureKind == GL_TEXTURE_3D
|
|
? "3D Texture"
|
|
: "2D Array Texture");
|
|
os << kindStr + ", "
|
|
<< params.numLayers << " layers, "
|
|
<< "attached layer " << params.attachmentLayer << ".";
|
|
return os.str();
|
|
}
|
|
|
|
class NumLayersTest : public fboc::ParamTest<NumLayersParams>
|
|
{
|
|
public:
|
|
NumLayersTest (fboc::Context& ctx, NumLayersParams param)
|
|
: fboc::ParamTest<NumLayersParams> (ctx, param) {}
|
|
|
|
IterateResult build (FboBuilder& builder);
|
|
};
|
|
|
|
IterateResult NumLayersTest::build (FboBuilder& builder)
|
|
{
|
|
TextureLayered* texCfg = DE_NULL;
|
|
const GLenum target = GL_COLOR_ATTACHMENT0;
|
|
|
|
switch (m_params.textureKind)
|
|
{
|
|
case GL_TEXTURE_3D:
|
|
texCfg = &builder.makeConfig<Texture3D>();
|
|
break;
|
|
case GL_TEXTURE_2D_ARRAY:
|
|
texCfg = &builder.makeConfig<Texture2DArray>();
|
|
break;
|
|
default:
|
|
DE_FATAL("Impossible case");
|
|
}
|
|
texCfg->internalFormat = getDefaultFormat(target, GL_TEXTURE);
|
|
texCfg->width = 64;
|
|
texCfg->height = 64;
|
|
texCfg->numLayers = m_params.numLayers;
|
|
const GLuint tex = builder.glCreateTexture(*texCfg);
|
|
|
|
TextureLayerAttachment* att = &builder.makeConfig<TextureLayerAttachment>();
|
|
att->layer = m_params.attachmentLayer;
|
|
att->imageName = tex;
|
|
|
|
builder.glAttach(target, att);
|
|
|
|
return STOP;
|
|
}
|
|
|
|
enum
|
|
{
|
|
SAMPLES_NONE = -2,
|
|
SAMPLES_TEXTURE = -1
|
|
};
|
|
struct NumSamplesParams
|
|
{
|
|
// >= 0: renderbuffer with N samples, -1: texture, -2: no attachment
|
|
GLsizei numSamples[3];
|
|
|
|
static string getName (const NumSamplesParams& params);
|
|
static string getDescription (const NumSamplesParams& params);
|
|
};
|
|
|
|
string NumSamplesParams::getName (const NumSamplesParams& params)
|
|
{
|
|
ostringstream os;
|
|
bool first = true;
|
|
for (const GLsizei* ns = DE_ARRAY_BEGIN(params.numSamples);
|
|
ns != DE_ARRAY_END(params.numSamples);
|
|
ns++)
|
|
{
|
|
if (first)
|
|
first = false;
|
|
else
|
|
os << "_";
|
|
|
|
if (*ns == SAMPLES_NONE)
|
|
os << "none";
|
|
else if (*ns == SAMPLES_TEXTURE)
|
|
os << "tex";
|
|
else
|
|
os << "rbo" << *ns;
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
string NumSamplesParams::getDescription (const NumSamplesParams& params)
|
|
{
|
|
ostringstream os;
|
|
bool first = true;
|
|
static const char* const s_names[] = { "color", "depth", "stencil" };
|
|
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == DE_LENGTH_OF_ARRAY(params.numSamples));
|
|
|
|
for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_names); i++)
|
|
{
|
|
GLsizei ns = params.numSamples[i];
|
|
|
|
if (ns == SAMPLES_NONE)
|
|
continue;
|
|
|
|
if (first)
|
|
first = false;
|
|
else
|
|
os << ", ";
|
|
|
|
if (ns == SAMPLES_TEXTURE)
|
|
os << "texture " << s_names[i] << " attachment";
|
|
else
|
|
os << ns << "-sample renderbuffer " << s_names[i] << " attachment";
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
class NumSamplesTest : public fboc::ParamTest<NumSamplesParams>
|
|
{
|
|
public:
|
|
NumSamplesTest (fboc::Context& ctx, NumSamplesParams param)
|
|
: fboc::ParamTest<NumSamplesParams> (ctx, param) {}
|
|
|
|
IterateResult build (FboBuilder& builder);
|
|
};
|
|
|
|
IterateResult NumSamplesTest::build (FboBuilder& builder)
|
|
{
|
|
static const GLenum s_targets[] =
|
|
{
|
|
GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_DEPTH_ATTACHMENT,
|
|
};
|
|
// Non-integer formats for each attachment type.
|
|
// \todo [2013-12-17 lauri] Add fixed/floating/integer metadata for formats so
|
|
// we can pick one smartly or maybe try several.
|
|
static const GLenum s_formats[] =
|
|
{
|
|
GL_RGBA8, GL_RGB565, GL_DEPTH_COMPONENT24,
|
|
};
|
|
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_targets) == DE_LENGTH_OF_ARRAY(m_params.numSamples));
|
|
|
|
for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_targets); i++)
|
|
{
|
|
const GLenum target = s_targets[i];
|
|
const ImageFormat fmt = { s_formats[i], GL_NONE };
|
|
|
|
const GLsizei ns = m_params.numSamples[i];
|
|
if (ns == -2)
|
|
continue;
|
|
|
|
if (ns == -1)
|
|
{
|
|
attachTargetToNew(target, GL_TEXTURE, fmt, 64, 64, builder);
|
|
}
|
|
else
|
|
{
|
|
Renderbuffer& rboCfg = builder.makeConfig<Renderbuffer>();
|
|
rboCfg.internalFormat = fmt;
|
|
rboCfg.width = rboCfg.height = 64;
|
|
rboCfg.numSamples = ns;
|
|
|
|
const GLuint rbo = builder.glCreateRbo(rboCfg);
|
|
// Implementations do not necessarily support sample sizes greater than 1.
|
|
TCU_CHECK_AND_THROW(NotSupportedError,
|
|
builder.getError() != GL_INVALID_OPERATION,
|
|
"Unsupported number of samples");
|
|
RenderbufferAttachment& att = builder.makeConfig<RenderbufferAttachment>();
|
|
att.imageName = rbo;
|
|
builder.glAttach(target, &att);
|
|
}
|
|
}
|
|
|
|
return STOP;
|
|
}
|
|
|
|
class ES3CheckerFactory : public CheckerFactory
|
|
{
|
|
public:
|
|
Checker* createChecker (const glu::RenderContext& ctx) { return new ES3Checker(ctx); }
|
|
};
|
|
|
|
class TestGroup : public TestCaseGroup
|
|
{
|
|
public:
|
|
TestGroup (Context& context);
|
|
void init (void);
|
|
private:
|
|
ES3CheckerFactory m_checkerFactory;
|
|
fboc::Context m_fboc;
|
|
};
|
|
|
|
void TestGroup::init (void)
|
|
{
|
|
addChild(m_fboc.createRenderableTests());
|
|
addChild(m_fboc.createAttachmentTests());
|
|
addChild(m_fboc.createSizeTests());
|
|
|
|
TestCaseGroup* layerTests = new TestCaseGroup(
|
|
getContext(), "layer", "Tests for layer attachments");
|
|
|
|
static const NumLayersParams s_layersParams[] =
|
|
{ // textureKind numLayers attachmentKind
|
|
{ GL_TEXTURE_2D_ARRAY, 1, 0 },
|
|
{ GL_TEXTURE_2D_ARRAY, 1, 3 },
|
|
{ GL_TEXTURE_2D_ARRAY, 4, 3 },
|
|
{ GL_TEXTURE_2D_ARRAY, 4, 15 },
|
|
{ GL_TEXTURE_3D, 1, 0 },
|
|
{ GL_TEXTURE_3D, 1, 15 },
|
|
{ GL_TEXTURE_3D, 4, 15 },
|
|
{ GL_TEXTURE_3D, 64, 15 },
|
|
};
|
|
|
|
for (const NumLayersParams* lp = DE_ARRAY_BEGIN(s_layersParams);
|
|
lp != DE_ARRAY_END(s_layersParams);
|
|
++lp)
|
|
layerTests->addChild(new NumLayersTest(m_fboc, *lp));
|
|
|
|
addChild(layerTests);
|
|
|
|
TestCaseGroup* sampleTests = new TestCaseGroup(
|
|
getContext(), "samples", "Tests for multisample attachments");
|
|
|
|
static const NumSamplesParams s_samplesParams[] =
|
|
{
|
|
{ { 0, SAMPLES_NONE, SAMPLES_NONE } },
|
|
{ { 1, SAMPLES_NONE, SAMPLES_NONE } },
|
|
{ { 2, SAMPLES_NONE, SAMPLES_NONE } },
|
|
{ { 0, SAMPLES_TEXTURE, SAMPLES_NONE } },
|
|
{ { 1, SAMPLES_TEXTURE, SAMPLES_NONE } },
|
|
{ { 2, SAMPLES_TEXTURE, SAMPLES_NONE } },
|
|
{ { 2, 1, SAMPLES_NONE } },
|
|
{ { 2, 2, SAMPLES_NONE } },
|
|
{ { 0, 0, SAMPLES_TEXTURE } },
|
|
{ { 1, 2, 0 } },
|
|
{ { 2, 2, 0 } },
|
|
{ { 1, 1, 1 } },
|
|
{ { 1, 2, 4 } },
|
|
};
|
|
|
|
for (const NumSamplesParams* lp = DE_ARRAY_BEGIN(s_samplesParams);
|
|
lp != DE_ARRAY_END(s_samplesParams);
|
|
++lp)
|
|
sampleTests->addChild(new NumSamplesTest(m_fboc, *lp));
|
|
|
|
addChild(sampleTests);
|
|
}
|
|
|
|
TestGroup::TestGroup (Context& ctx)
|
|
: TestCaseGroup (ctx, "completeness", "Completeness tests")
|
|
, m_checkerFactory ()
|
|
, m_fboc (ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory)
|
|
{
|
|
const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es3Formats);
|
|
const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es3ExtFormats);
|
|
|
|
m_fboc.addFormats(stdRange);
|
|
m_fboc.addExtFormats(extRange);
|
|
m_fboc.setHaveMulticolorAtts(true); // Vanilla ES3 has multiple color attachments
|
|
}
|
|
|
|
tcu::TestCaseGroup* createFboCompletenessTests (Context& context)
|
|
{
|
|
return new TestGroup(context);
|
|
}
|
|
|
|
} // Functional
|
|
} // gles3
|
|
} // deqp
|