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.
319 lines
10 KiB
319 lines
10 KiB
/*------------------------------------------------------------------------- |
|
* drawElements Quality Program OpenGL ES 3.0 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 FBO multisample tests. |
|
*//*--------------------------------------------------------------------*/ |
|
|
|
#include "es3fFboMultisampleTests.hpp" |
|
#include "es3fFboTestCase.hpp" |
|
#include "es3fFboTestUtil.hpp" |
|
#include "gluTextureUtil.hpp" |
|
#include "tcuImageCompare.hpp" |
|
#include "tcuTextureUtil.hpp" |
|
#include "tcuTestLog.hpp" |
|
#include "deStringUtil.hpp" |
|
#include "deRandom.hpp" |
|
#include "sglrContextUtil.hpp" |
|
#include "glwEnums.hpp" |
|
|
|
namespace deqp |
|
{ |
|
namespace gles3 |
|
{ |
|
namespace Functional |
|
{ |
|
|
|
using std::string; |
|
using tcu::TestLog; |
|
using tcu::Vec2; |
|
using tcu::Vec3; |
|
using tcu::Vec4; |
|
using tcu::IVec2; |
|
using tcu::IVec3; |
|
using tcu::IVec4; |
|
using tcu::UVec4; |
|
using namespace FboTestUtil; |
|
|
|
class BasicFboMultisampleCase : public FboTestCase |
|
{ |
|
public: |
|
BasicFboMultisampleCase (Context& context, const char* name, const char* desc, deUint32 colorFormat, deUint32 depthStencilFormat, const IVec2& size, int numSamples) |
|
: FboTestCase (context, name, desc) |
|
, m_colorFormat (colorFormat) |
|
, m_depthStencilFormat (depthStencilFormat) |
|
, m_size (size) |
|
, m_numSamples (numSamples) |
|
{ |
|
} |
|
|
|
protected: |
|
void preCheck (void) |
|
{ |
|
checkFormatSupport (m_colorFormat); |
|
checkSampleCount (m_colorFormat, m_numSamples); |
|
|
|
if (m_depthStencilFormat != GL_NONE) |
|
{ |
|
checkFormatSupport (m_depthStencilFormat); |
|
checkSampleCount (m_depthStencilFormat, m_numSamples); |
|
} |
|
} |
|
|
|
void render (tcu::Surface& dst) |
|
{ |
|
tcu::TextureFormat colorFmt = glu::mapGLInternalFormat(m_colorFormat); |
|
tcu::TextureFormat depthStencilFmt = m_depthStencilFormat != GL_NONE ? glu::mapGLInternalFormat(m_depthStencilFormat) : tcu::TextureFormat(); |
|
tcu::TextureFormatInfo colorFmtInfo = tcu::getTextureFormatInfo(colorFmt); |
|
bool depth = depthStencilFmt.order == tcu::TextureFormat::D || depthStencilFmt.order == tcu::TextureFormat::DS; |
|
bool stencil = depthStencilFmt.order == tcu::TextureFormat::S || depthStencilFmt.order == tcu::TextureFormat::DS; |
|
GradientShader gradShader (getFragmentOutputType(colorFmt)); |
|
FlatColorShader flatShader (getFragmentOutputType(colorFmt)); |
|
deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); |
|
deUint32 flatShaderID = getCurrentContext()->createProgram(&flatShader); |
|
deUint32 msaaFbo = 0; |
|
deUint32 resolveFbo = 0; |
|
deUint32 msaaColorRbo = 0; |
|
deUint32 resolveColorRbo = 0; |
|
deUint32 msaaDepthStencilRbo = 0; |
|
deUint32 resolveDepthStencilRbo = 0; |
|
|
|
// Create framebuffers. |
|
for (int ndx = 0; ndx < 2; ndx++) |
|
{ |
|
deUint32& fbo = ndx ? resolveFbo : msaaFbo; |
|
deUint32& colorRbo = ndx ? resolveColorRbo : msaaColorRbo; |
|
deUint32& depthStencilRbo = ndx ? resolveDepthStencilRbo : msaaDepthStencilRbo; |
|
int samples = ndx ? 0 : m_numSamples; |
|
|
|
glGenRenderbuffers(1, &colorRbo); |
|
glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); |
|
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, m_colorFormat, m_size.x(), m_size.y()); |
|
|
|
if (depth || stencil) |
|
{ |
|
glGenRenderbuffers(1, &depthStencilRbo); |
|
glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo); |
|
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, m_depthStencilFormat, m_size.x(), m_size.y()); |
|
} |
|
|
|
glGenFramebuffers(1, &fbo); |
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); |
|
if (depth) |
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); |
|
if (stencil) |
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo); |
|
|
|
checkError(); |
|
checkFramebufferStatus(GL_FRAMEBUFFER); |
|
} |
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, msaaFbo); |
|
glViewport(0, 0, m_size.x(), m_size.y()); |
|
|
|
// Clear depth and stencil buffers. |
|
glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); |
|
|
|
// Fill MSAA fbo with gradient, depth = [-1..1] |
|
glEnable(GL_DEPTH_TEST); |
|
gradShader.setGradient(*getCurrentContext(), gradShaderID, colorFmtInfo.valueMin, colorFmtInfo.valueMax); |
|
sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); |
|
|
|
// Render random-colored quads. |
|
{ |
|
const int numQuads = 8; |
|
de::Random rnd (9); |
|
|
|
glDepthFunc(GL_ALWAYS); |
|
glEnable(GL_STENCIL_TEST); |
|
glStencilFunc(GL_ALWAYS, 0, 0xffu); |
|
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); |
|
|
|
for (int ndx = 0; ndx < numQuads; ndx++) |
|
{ |
|
float r = rnd.getFloat(); |
|
float g = rnd.getFloat(); |
|
float b = rnd.getFloat(); |
|
float a = rnd.getFloat(); |
|
float x0 = rnd.getFloat(-1.0f, 1.0f); |
|
float y0 = rnd.getFloat(-1.0f, 1.0f); |
|
float z0 = rnd.getFloat(-1.0f, 1.0f); |
|
float x1 = rnd.getFloat(-1.0f, 1.0f); |
|
float y1 = rnd.getFloat(-1.0f, 1.0f); |
|
float z1 = rnd.getFloat(-1.0f, 1.0f); |
|
|
|
flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(r,g,b,a) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin); |
|
sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(x0, y0, z0), Vec3(x1, y1, z1)); |
|
} |
|
} |
|
|
|
glDisable(GL_DEPTH_TEST); |
|
glDisable(GL_STENCIL_TEST); |
|
checkError(); |
|
|
|
// Resolve using glBlitFramebuffer(). |
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFbo); |
|
glBlitFramebuffer(0, 0, m_size.x(), m_size.y(), 0, 0, m_size.x(), m_size.y(), GL_COLOR_BUFFER_BIT | (depth ? GL_DEPTH_BUFFER_BIT : 0) | (stencil ? GL_STENCIL_BUFFER_BIT : 0), GL_NEAREST); |
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFbo); |
|
|
|
if (depth) |
|
{ |
|
// Visualize depth. |
|
const int numSteps = 8; |
|
const float step = 2.0f / (float)numSteps; |
|
|
|
glEnable(GL_DEPTH_TEST); |
|
glDepthFunc(GL_LESS); |
|
glDepthMask(GL_FALSE); |
|
glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); |
|
|
|
for (int ndx = 0; ndx < numSteps; ndx++) |
|
{ |
|
float d = -1.0f + step*(float)ndx; |
|
float c = (float)ndx / (float)(numSteps-1); |
|
|
|
flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, c, 1.0f) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin); |
|
sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, d), Vec3(1.0f, 1.0f, d)); |
|
} |
|
|
|
glDisable(GL_DEPTH_TEST); |
|
} |
|
|
|
if (stencil) |
|
{ |
|
// Visualize stencil. |
|
const int numSteps = 4; |
|
const int step = 1; |
|
|
|
glEnable(GL_STENCIL_TEST); |
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); |
|
glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE); |
|
|
|
for (int ndx = 0; ndx < numSteps; ndx++) |
|
{ |
|
int s = step*ndx; |
|
float c = (float)ndx / (float)(numSteps-1); |
|
|
|
glStencilFunc(GL_EQUAL, s, 0xffu); |
|
|
|
flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, c, 0.0f, 1.0f) * (colorFmtInfo.valueMax-colorFmtInfo.valueMin) + colorFmtInfo.valueMin); |
|
sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
|
} |
|
|
|
glDisable(GL_STENCIL_TEST); |
|
} |
|
|
|
readPixels(dst, 0, 0, m_size.x(), m_size.y(), colorFmt, colorFmtInfo.lookupScale, colorFmtInfo.lookupBias); |
|
} |
|
|
|
bool colorCompare (const tcu::Surface& reference, const tcu::Surface& result) |
|
{ |
|
const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_colorFormat), tcu::RGBA(12, 12, 12, 12))); |
|
|
|
return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT); |
|
} |
|
|
|
bool compare (const tcu::Surface& reference, const tcu::Surface& result) |
|
{ |
|
if (m_depthStencilFormat != GL_NONE) |
|
return FboTestCase::compare(reference, result); |
|
else |
|
return colorCompare(reference, result); |
|
} |
|
|
|
private: |
|
deUint32 m_colorFormat; |
|
deUint32 m_depthStencilFormat; |
|
IVec2 m_size; |
|
int m_numSamples; |
|
}; |
|
|
|
FboMultisampleTests::FboMultisampleTests (Context& context) |
|
: TestCaseGroup(context, "msaa", "Multisample FBO tests") |
|
{ |
|
} |
|
|
|
FboMultisampleTests::~FboMultisampleTests (void) |
|
{ |
|
} |
|
|
|
void FboMultisampleTests::init (void) |
|
{ |
|
static const deUint32 colorFormats[] = |
|
{ |
|
// RGBA formats |
|
GL_RGBA8, |
|
GL_SRGB8_ALPHA8, |
|
GL_RGB10_A2, |
|
GL_RGBA4, |
|
GL_RGB5_A1, |
|
|
|
// RGB formats |
|
GL_RGB8, |
|
GL_RGB565, |
|
|
|
// RG formats |
|
GL_RG8, |
|
|
|
// R formats |
|
GL_R8, |
|
|
|
// GL_EXT_color_buffer_float |
|
GL_RGBA32F, |
|
GL_RGBA16F, |
|
GL_R11F_G11F_B10F, |
|
GL_RG32F, |
|
GL_RG16F, |
|
GL_R32F, |
|
GL_R16F |
|
}; |
|
|
|
static const deUint32 depthStencilFormats[] = |
|
{ |
|
GL_DEPTH_COMPONENT32F, |
|
GL_DEPTH_COMPONENT24, |
|
GL_DEPTH_COMPONENT16, |
|
GL_DEPTH32F_STENCIL8, |
|
GL_DEPTH24_STENCIL8, |
|
GL_STENCIL_INDEX8 |
|
}; |
|
|
|
static const int sampleCounts[] = { 2, 4, 8 }; |
|
|
|
for (int sampleCntNdx = 0; sampleCntNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCntNdx++) |
|
{ |
|
int samples = sampleCounts[sampleCntNdx]; |
|
tcu::TestCaseGroup* sampleCountGroup = new tcu::TestCaseGroup(m_testCtx, (de::toString(samples) + "_samples").c_str(), ""); |
|
addChild(sampleCountGroup); |
|
|
|
// Color formats. |
|
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
|
sampleCountGroup->addChild(new BasicFboMultisampleCase(m_context, getFormatName(colorFormats[fmtNdx]), "", colorFormats[fmtNdx], GL_NONE, IVec2(119, 131), samples)); |
|
|
|
// Depth/stencil formats. |
|
for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++) |
|
sampleCountGroup->addChild(new BasicFboMultisampleCase(m_context, getFormatName(depthStencilFormats[fmtNdx]), "", GL_RGBA8, depthStencilFormats[fmtNdx], IVec2(119, 131), samples)); |
|
} |
|
} |
|
|
|
} // Functional |
|
} // gles3 |
|
} // deqp
|
|
|