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.
1999 lines
64 KiB
1999 lines
64 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 3.1 Module
|
|
* -------------------------------------------------
|
|
*
|
|
* Copyright 2017 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 Texture format tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es31fSRGBDecodeTests.hpp"
|
|
#include "gluContextInfo.hpp"
|
|
#include "gluCallLogWrapper.hpp"
|
|
#include "gluRenderContext.hpp"
|
|
#include "gluTexture.hpp"
|
|
#include "glsTextureTestUtil.hpp"
|
|
#include "tcuPixelFormat.hpp"
|
|
#include "tcuTestContext.hpp"
|
|
#include "tcuRenderTarget.hpp"
|
|
#include "gluTextureUtil.hpp"
|
|
#include "tcuTextureUtil.hpp"
|
|
#include "glwFunctions.hpp"
|
|
#include "gluDefs.hpp"
|
|
#include "glwEnums.hpp"
|
|
#include "deUniquePtr.hpp"
|
|
#include "gluPixelTransfer.hpp"
|
|
#include "tcuDefs.hpp"
|
|
#include "tcuVectorUtil.hpp"
|
|
#include "gluObjectWrapper.hpp"
|
|
#include "gluStrUtil.hpp"
|
|
#include "tcuTestLog.hpp"
|
|
#include "deStringUtil.hpp"
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles31
|
|
{
|
|
namespace Functional
|
|
{
|
|
namespace
|
|
{
|
|
|
|
using glu::TextureTestUtil::TEXTURETYPE_2D;
|
|
|
|
enum SRGBDecode
|
|
{
|
|
SRGBDECODE_SKIP_DECODE = 0,
|
|
SRGBDECODE_DECODE,
|
|
SRGBDECODE_DECODE_DEFAULT
|
|
};
|
|
|
|
enum ShaderOutputs
|
|
{
|
|
SHADEROUTPUTS_ONE = 1,
|
|
SHADEROUTPUTS_TWO,
|
|
};
|
|
|
|
enum ShaderUniforms
|
|
{
|
|
SHADERUNIFORMS_ONE = 1,
|
|
SHADERUNIFORMS_TWO,
|
|
};
|
|
|
|
enum ShaderSamplingGroup
|
|
{
|
|
SHADERSAMPLINGGROUP_TEXTURE = 0,
|
|
SHADERSAMPLINGGROUP_TEXEL_FETCH
|
|
};
|
|
|
|
enum ShaderSamplingType
|
|
{
|
|
TEXTURESAMPLING_TEXTURE = 0,
|
|
TEXTURESAMPLING_TEXTURE_LOD,
|
|
TEXTURESAMPLING_TEXTURE_GRAD,
|
|
TEXTURESAMPLING_TEXTURE_OFFSET,
|
|
TEXTURESAMPLING_TEXTURE_PROJ,
|
|
TEXTURESAMPLING_TEXELFETCH,
|
|
TEXTURESAMPLING_TEXELFETCH_OFFSET,
|
|
|
|
// ranges required for looping mechanism in a case nodes iteration function
|
|
TEXTURESAMPLING_TEXTURE_START = TEXTURESAMPLING_TEXTURE,
|
|
TEXTURESAMPLING_TEXTURE_END = TEXTURESAMPLING_TEXTURE_PROJ + 1,
|
|
TEXTURESAMPLING_TEXELFETCH_START = TEXTURESAMPLING_TEXELFETCH,
|
|
TEXTURESAMPLING_TEXELFETCH_END = TEXTURESAMPLING_TEXELFETCH_OFFSET + 1
|
|
};
|
|
|
|
enum FunctionParameters
|
|
{
|
|
FUNCTIONPARAMETERS_ONE = 1,
|
|
FUNCTIONPARAMETERS_TWO
|
|
};
|
|
|
|
enum Blending
|
|
{
|
|
BLENDING_REQUIRED = 0,
|
|
BLENDING_NOT_REQUIRED
|
|
};
|
|
|
|
enum Toggling
|
|
{
|
|
TOGGLING_REQUIRED = 0,
|
|
TOGGLING_NOT_REQUIRED
|
|
};
|
|
|
|
tcu::Vec4 getColorReferenceLinear (void)
|
|
{
|
|
return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
|
|
}
|
|
|
|
tcu::Vec4 getColorReferenceSRGB (void)
|
|
{
|
|
return tcu::linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
|
|
}
|
|
|
|
tcu::Vec4 getColorGreenPass (void)
|
|
{
|
|
return tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
|
|
}
|
|
|
|
namespace TestDimensions
|
|
{
|
|
const int WIDTH = 128;
|
|
const int HEIGHT = 128;
|
|
} // global test texture dimensions
|
|
|
|
namespace TestSamplingPositions
|
|
{
|
|
const int X_POS = 0;
|
|
const int Y_POS = 0;
|
|
} // global test sampling positions
|
|
|
|
const char* getFunctionDefinitionSRGBToLinearCheck (void)
|
|
{
|
|
static const char* functionDefinition =
|
|
"mediump vec4 srgbToLinearCheck(in mediump vec4 texelSRGBA, in mediump vec4 texelLinear) \n"
|
|
"{ \n"
|
|
" const int NUM_CHANNELS = 4;"
|
|
" mediump vec4 texelSRGBAConverted; \n"
|
|
" mediump vec4 epsilonErr = vec4(0.005); \n"
|
|
" mediump vec4 testResult; \n"
|
|
" for (int idx = 0; idx < NUM_CHANNELS; idx++) \n"
|
|
" { \n"
|
|
" texelSRGBAConverted[idx] = pow( (texelSRGBA[idx] + 0.055) / 1.055, 1.0 / 0.4116); \n"
|
|
" } \n"
|
|
" if ( all(lessThan(abs(texelSRGBAConverted - texelLinear), epsilonErr)) || all(equal(texelSRGBAConverted, texelLinear)) ) \n"
|
|
" { \n"
|
|
" return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
|
|
" } \n"
|
|
" else \n"
|
|
" { \n"
|
|
" return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
|
|
" } \n"
|
|
"} \n";
|
|
|
|
return functionDefinition;
|
|
}
|
|
|
|
const char* getFunctionDefinitionEqualCheck (void)
|
|
{
|
|
static const char* functionDefinition =
|
|
"mediump vec4 colorsEqualCheck(in mediump vec4 colorA, in mediump vec4 colorB) \n"
|
|
"{ \n"
|
|
" mediump vec4 epsilonErr = vec4(0.005); \n"
|
|
" mediump vec4 testResult; \n"
|
|
" if ( all(lessThan(abs(colorA - colorB), epsilonErr)) || all(equal(colorA, colorB)) ) \n"
|
|
" { \n"
|
|
" return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
|
|
" } \n"
|
|
" else \n"
|
|
" { \n"
|
|
" return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
|
|
" } \n"
|
|
"} \n";
|
|
|
|
return functionDefinition;
|
|
}
|
|
|
|
namespace EpsilonError
|
|
{
|
|
const float CPU = 0.005f;
|
|
}
|
|
|
|
struct TestGroupConfig
|
|
{
|
|
TestGroupConfig (const char* groupName, const char* groupDescription, const tcu::TextureFormat groupInternalFormat)
|
|
: name (groupName)
|
|
, description (groupDescription)
|
|
, internalFormat (groupInternalFormat) {}
|
|
|
|
~TestGroupConfig (void) {};
|
|
|
|
const char* name;
|
|
const char* description;
|
|
const tcu::TextureFormat internalFormat;
|
|
};
|
|
|
|
struct UniformData
|
|
{
|
|
UniformData (glw::GLuint uniformLocation, const std::string& uniformName)
|
|
: location (uniformLocation)
|
|
, name (uniformName)
|
|
, toggleDecode (false) {}
|
|
|
|
~UniformData (void) {}
|
|
|
|
glw::GLuint location;
|
|
std::string name;
|
|
bool toggleDecode;
|
|
};
|
|
|
|
struct UniformToToggle
|
|
{
|
|
UniformToToggle (const int uniformProgramIdx, const std::string& uniformName)
|
|
: programIdx (uniformProgramIdx)
|
|
, name (uniformName) {}
|
|
|
|
~UniformToToggle (void) {}
|
|
|
|
int programIdx;
|
|
std::string name;
|
|
};
|
|
|
|
struct ComparisonFunction
|
|
{
|
|
ComparisonFunction (const std::string& funcName, const FunctionParameters funcParameters, const std::string& funcImplementation)
|
|
: name (funcName)
|
|
, parameters (funcParameters)
|
|
, implementation (funcImplementation) {}
|
|
|
|
~ComparisonFunction (void) {}
|
|
|
|
std::string name;
|
|
FunctionParameters parameters;
|
|
std::string implementation;
|
|
};
|
|
|
|
struct FragmentShaderParameters
|
|
{
|
|
FragmentShaderParameters (const ShaderOutputs outputTotal,
|
|
const ShaderUniforms uniformTotal,
|
|
ComparisonFunction* comparisonFunction,
|
|
Blending blendRequired,
|
|
Toggling toggleRequired);
|
|
|
|
~FragmentShaderParameters (void);
|
|
|
|
ShaderOutputs outputTotal;
|
|
ShaderUniforms uniformTotal;
|
|
ShaderSamplingType samplingType;
|
|
std::string functionName;
|
|
FunctionParameters functionParameters;
|
|
std::string functionImplementation;
|
|
bool hasFunction;
|
|
Blending blendRequired;
|
|
Toggling toggleRequired;
|
|
std::vector<std::string> uniformsToToggle;
|
|
};
|
|
|
|
FragmentShaderParameters::FragmentShaderParameters (const ShaderOutputs paramsOutputTotal,
|
|
const ShaderUniforms paramsUniformTotal,
|
|
ComparisonFunction* paramsComparisonFunction,
|
|
Blending paramsBlendRequired,
|
|
Toggling paramsToggleRequired)
|
|
: outputTotal (paramsOutputTotal)
|
|
, uniformTotal (paramsUniformTotal)
|
|
, blendRequired (paramsBlendRequired)
|
|
, toggleRequired (paramsToggleRequired)
|
|
{
|
|
if (paramsComparisonFunction != DE_NULL)
|
|
{
|
|
functionName = paramsComparisonFunction->name;
|
|
functionParameters = paramsComparisonFunction->parameters;
|
|
functionImplementation = paramsComparisonFunction->implementation;
|
|
|
|
hasFunction = true;
|
|
}
|
|
else
|
|
{
|
|
hasFunction = false;
|
|
}
|
|
}
|
|
|
|
FragmentShaderParameters::~FragmentShaderParameters (void)
|
|
{
|
|
}
|
|
|
|
class SRGBTestSampler
|
|
{
|
|
public:
|
|
SRGBTestSampler (Context& context,
|
|
const tcu::Sampler::WrapMode wrapS,
|
|
const tcu::Sampler::WrapMode wrapT,
|
|
const tcu::Sampler::FilterMode minFilter,
|
|
const tcu::Sampler::FilterMode magFilter,
|
|
const SRGBDecode decoding);
|
|
~SRGBTestSampler (void);
|
|
|
|
void setDecode (const SRGBDecode decoding);
|
|
void setTextureUnit (const deUint32 textureUnit);
|
|
void setIsActive (const bool isActive);
|
|
|
|
bool getIsActive (void) const;
|
|
|
|
void bindToTexture (void);
|
|
|
|
private:
|
|
const glw::Functions* m_gl;
|
|
deUint32 m_samplerHandle;
|
|
tcu::Sampler::WrapMode m_wrapS;
|
|
tcu::Sampler::WrapMode m_wrapT;
|
|
tcu::Sampler::FilterMode m_minFilter;
|
|
tcu::Sampler::FilterMode m_magFilter;
|
|
SRGBDecode m_decoding;
|
|
deUint32 m_textureUnit;
|
|
bool m_isActive;
|
|
};
|
|
|
|
SRGBTestSampler::SRGBTestSampler (Context& context,
|
|
const tcu::Sampler::WrapMode wrapS,
|
|
const tcu::Sampler::WrapMode wrapT,
|
|
const tcu::Sampler::FilterMode minFilter,
|
|
const tcu::Sampler::FilterMode magFilter,
|
|
const SRGBDecode decoding)
|
|
: m_gl (&context.getRenderContext().getFunctions())
|
|
, m_wrapS (wrapS)
|
|
, m_wrapT (wrapT)
|
|
, m_minFilter (minFilter)
|
|
, m_magFilter (magFilter)
|
|
, m_isActive (false)
|
|
{
|
|
m_gl->genSamplers(1, &m_samplerHandle);
|
|
|
|
m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
|
|
m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
|
|
m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
|
|
m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
|
|
|
|
this->setDecode(decoding);
|
|
}
|
|
|
|
SRGBTestSampler::~SRGBTestSampler (void)
|
|
{
|
|
m_gl->deleteSamplers(1, &m_samplerHandle);
|
|
}
|
|
|
|
void SRGBTestSampler::setDecode (const SRGBDecode decoding)
|
|
{
|
|
if (decoding == SRGBDECODE_SKIP_DECODE)
|
|
{
|
|
m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
|
|
GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
|
|
}
|
|
else if (decoding == SRGBDECODE_DECODE)
|
|
{
|
|
m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
|
|
GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
|
|
}
|
|
else
|
|
{
|
|
DE_FATAL("sRGB texture sampler must have either GL_SKIP_DECODE_EXT or GL_DECODE_EXT settings");
|
|
}
|
|
|
|
m_decoding = decoding;
|
|
}
|
|
|
|
void SRGBTestSampler::setTextureUnit (const deUint32 textureUnit)
|
|
{
|
|
m_textureUnit = textureUnit;
|
|
}
|
|
|
|
void SRGBTestSampler::setIsActive (const bool isActive)
|
|
{
|
|
m_isActive = isActive;
|
|
}
|
|
|
|
bool SRGBTestSampler::getIsActive (void) const
|
|
{
|
|
return m_isActive;
|
|
}
|
|
|
|
void SRGBTestSampler::bindToTexture (void)
|
|
{
|
|
m_gl->bindSampler(m_textureUnit, m_samplerHandle);
|
|
}
|
|
|
|
class SRGBTestTexture
|
|
{
|
|
public:
|
|
SRGBTestTexture (Context& context,
|
|
const glu::TextureTestUtil::TextureType targetType,
|
|
const tcu::TextureFormat internalFormat,
|
|
const int width,
|
|
const int height,
|
|
const tcu::Vec4 color,
|
|
const tcu::Sampler::WrapMode wrapS,
|
|
const tcu::Sampler::WrapMode wrapT,
|
|
const tcu::Sampler::FilterMode minFilter,
|
|
const tcu::Sampler::FilterMode magFilter,
|
|
const SRGBDecode decoding);
|
|
~SRGBTestTexture (void);
|
|
|
|
void setParameters (void);
|
|
void setDecode (const SRGBDecode decoding);
|
|
void setHasSampler (const bool hasSampler);
|
|
|
|
deUint32 getHandle (void) const;
|
|
deUint32 getGLTargetType (void) const;
|
|
SRGBDecode getDecode (void) const;
|
|
|
|
void upload (void);
|
|
|
|
private:
|
|
void setColor (void);
|
|
|
|
Context& m_context;
|
|
glu::Texture2D m_source;
|
|
glu::TextureTestUtil::TextureType m_targetType;
|
|
const tcu::TextureFormat m_internalFormat;
|
|
const int m_width;
|
|
const int m_height;
|
|
tcu::Vec4 m_color;
|
|
tcu::Sampler::WrapMode m_wrapS;
|
|
tcu::Sampler::WrapMode m_wrapT;
|
|
tcu::Sampler::FilterMode m_minFilter;
|
|
tcu::Sampler::FilterMode m_magFilter;
|
|
SRGBDecode m_decoding;
|
|
bool m_hasSampler;
|
|
};
|
|
|
|
SRGBTestTexture::SRGBTestTexture (Context& context,
|
|
const glu::TextureTestUtil::TextureType targetType,
|
|
const tcu::TextureFormat internalFormat,
|
|
const int width,
|
|
const int height,
|
|
const tcu::Vec4 color,
|
|
const tcu::Sampler::WrapMode wrapS,
|
|
const tcu::Sampler::WrapMode wrapT,
|
|
const tcu::Sampler::FilterMode minFilter,
|
|
const tcu::Sampler::FilterMode magFilter,
|
|
SRGBDecode decoding)
|
|
: m_context (context)
|
|
, m_source (context.getRenderContext(), glu::getInternalFormat(internalFormat), width, height)
|
|
, m_targetType (targetType)
|
|
, m_internalFormat (internalFormat)
|
|
, m_width (width)
|
|
, m_height (height)
|
|
, m_color (color)
|
|
, m_wrapS (wrapS)
|
|
, m_wrapT (wrapT)
|
|
, m_minFilter (minFilter)
|
|
, m_magFilter (magFilter)
|
|
, m_decoding (decoding)
|
|
, m_hasSampler (false)
|
|
{
|
|
this->setColor();
|
|
}
|
|
|
|
SRGBTestTexture::~SRGBTestTexture (void)
|
|
{
|
|
}
|
|
|
|
void SRGBTestTexture::setParameters (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
gl.bindTexture(this->getGLTargetType(), this->getHandle());
|
|
|
|
gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
|
|
gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
|
|
gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
|
|
gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
|
|
|
|
gl.bindTexture(this->getGLTargetType(), 0);
|
|
|
|
setDecode(m_decoding);
|
|
}
|
|
|
|
void SRGBTestTexture::setDecode (const SRGBDecode decoding)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
gl.bindTexture(this->getGLTargetType(), this->getHandle());
|
|
|
|
switch (decoding)
|
|
{
|
|
case SRGBDECODE_SKIP_DECODE:
|
|
{
|
|
gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
|
|
break;
|
|
}
|
|
case SRGBDECODE_DECODE:
|
|
{
|
|
gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
|
|
break;
|
|
}
|
|
case SRGBDECODE_DECODE_DEFAULT:
|
|
{
|
|
// do not use srgb decode options. Set to default
|
|
break;
|
|
}
|
|
default:
|
|
DE_FATAL("Error: Decoding option not recognised");
|
|
}
|
|
|
|
gl.bindTexture(this->getGLTargetType(), 0);
|
|
|
|
m_decoding = decoding;
|
|
}
|
|
|
|
void SRGBTestTexture::setHasSampler (const bool hasSampler)
|
|
{
|
|
m_hasSampler = hasSampler;
|
|
}
|
|
|
|
deUint32 SRGBTestTexture::getHandle (void) const
|
|
{
|
|
return m_source.getGLTexture();
|
|
}
|
|
|
|
deUint32 SRGBTestTexture::getGLTargetType (void) const
|
|
{
|
|
switch (m_targetType)
|
|
{
|
|
case TEXTURETYPE_2D:
|
|
{
|
|
return GL_TEXTURE_2D;
|
|
}
|
|
default:
|
|
{
|
|
DE_FATAL("Error: Target type not recognised");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
SRGBDecode SRGBTestTexture::getDecode (void) const
|
|
{
|
|
return m_decoding;
|
|
}
|
|
|
|
void SRGBTestTexture::upload (void)
|
|
{
|
|
m_source.upload();
|
|
}
|
|
|
|
void SRGBTestTexture::setColor (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
gl.bindTexture(this->getGLTargetType(), this->getHandle());
|
|
|
|
m_source.getRefTexture().allocLevel(0);
|
|
|
|
for (int py = 0; py < m_height; py++)
|
|
{
|
|
for (int px = 0; px < m_width; px++)
|
|
{
|
|
m_source.getRefTexture().getLevel(0).setPixel(m_color, px, py);
|
|
}
|
|
}
|
|
|
|
gl.bindTexture(this->getGLTargetType(), 0);
|
|
}
|
|
|
|
class SRGBTestProgram
|
|
{
|
|
public:
|
|
SRGBTestProgram (Context& context, const FragmentShaderParameters& shaderParameters);
|
|
~SRGBTestProgram (void);
|
|
|
|
void setBlendRequired (bool blendRequired);
|
|
void setToggleRequired (bool toggleRequired);
|
|
void setUniformToggle (int location, bool toggleDecodeValue);
|
|
|
|
const std::vector<UniformData>& getUniformDataList (void) const;
|
|
int getUniformLocation (const std::string& name);
|
|
deUint32 getHandle (void) const;
|
|
bool getBlendRequired (void) const;
|
|
|
|
private:
|
|
std::string genFunctionCall (ShaderSamplingType samplingType, const int uniformIdx);
|
|
void genFragmentShader (void);
|
|
|
|
Context& m_context;
|
|
de::MovePtr<glu::ShaderProgram> m_program;
|
|
FragmentShaderParameters m_shaderFragmentParameters;
|
|
std::string m_shaderVertex;
|
|
std::string m_shaderFragment;
|
|
std::vector<UniformData> m_uniformDataList;
|
|
bool m_blendRequired;
|
|
bool m_toggleRequired;
|
|
};
|
|
|
|
SRGBTestProgram::SRGBTestProgram (Context& context, const FragmentShaderParameters& shaderParameters)
|
|
: m_context (context)
|
|
, m_shaderFragmentParameters (shaderParameters)
|
|
, m_blendRequired (false)
|
|
, m_toggleRequired (false)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
glu::ShaderProgramInfo buildInfo;
|
|
const int totalShaderStages = 2;
|
|
|
|
// default vertex shader used in all tests
|
|
std::string ver(glu::isContextTypeGLCore(m_context.getRenderContext().getType()) ? "#version 450\n" : "#version 310 es\n");
|
|
m_shaderVertex = ver +
|
|
"layout (location = 0) in mediump vec3 aPosition; \n"
|
|
"layout (location = 1) in mediump vec2 aTexCoord; \n"
|
|
"out mediump vec2 vs_aTexCoord; \n"
|
|
"void main () \n"
|
|
"{ \n"
|
|
" gl_Position = vec4(aPosition, 1.0); \n"
|
|
" vs_aTexCoord = aTexCoord; \n"
|
|
"} \n";
|
|
|
|
this->genFragmentShader();
|
|
|
|
m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(m_shaderVertex, m_shaderFragment)));
|
|
|
|
if (!m_program->isOk())
|
|
{
|
|
TCU_FAIL("Failed to compile shaders and link program");
|
|
}
|
|
|
|
glw::GLint activeUniforms, maxLen;
|
|
glw::GLint size, location;
|
|
glw::GLenum type;
|
|
|
|
gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
|
|
gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORMS, &activeUniforms);
|
|
|
|
std::vector<glw::GLchar> uniformName(static_cast<int>(maxLen));
|
|
for (int idx = 0; idx < activeUniforms; idx++)
|
|
{
|
|
gl.getActiveUniform(this->getHandle(), idx, maxLen, NULL, &size, &type, &uniformName[0]);
|
|
location = gl.getUniformLocation(this->getHandle(), &uniformName[0]);
|
|
|
|
UniformData uniformData(location, std::string(&uniformName[0], strlen(&uniformName[0])));
|
|
m_uniformDataList.push_back(uniformData);
|
|
}
|
|
|
|
// log shader program info. Only vertex and fragment shaders included
|
|
buildInfo.program = m_program->getProgramInfo();
|
|
for (int shaderIdx = 0; shaderIdx < totalShaderStages; shaderIdx++)
|
|
{
|
|
glu::ShaderInfo shaderInfo = m_program->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
|
|
buildInfo.shaders.push_back(shaderInfo);
|
|
}
|
|
|
|
log << buildInfo;
|
|
}
|
|
|
|
SRGBTestProgram::~SRGBTestProgram (void)
|
|
{
|
|
m_program = de::MovePtr<glu::ShaderProgram>(DE_NULL);
|
|
}
|
|
|
|
void SRGBTestProgram::setBlendRequired (bool blendRequired)
|
|
{
|
|
m_blendRequired = blendRequired;
|
|
}
|
|
|
|
void SRGBTestProgram::setToggleRequired (bool toggleRequired)
|
|
{
|
|
m_toggleRequired = toggleRequired;
|
|
}
|
|
|
|
void SRGBTestProgram::setUniformToggle (int location, bool toggleDecodeValue)
|
|
{
|
|
if ( (m_uniformDataList.empty() == false) && (location >= 0) && (location <= (int)m_uniformDataList.size()) )
|
|
{
|
|
m_uniformDataList[location].toggleDecode = toggleDecodeValue;
|
|
}
|
|
else
|
|
{
|
|
TCU_THROW(TestError, "Error: Uniform location not found. glGetActiveUniforms returned uniforms incorrectly ");
|
|
}
|
|
}
|
|
|
|
const std::vector<UniformData>& SRGBTestProgram::getUniformDataList (void) const
|
|
{
|
|
return m_uniformDataList;
|
|
}
|
|
|
|
int SRGBTestProgram::getUniformLocation (const std::string& name)
|
|
{
|
|
for (std::size_t idx = 0; idx < m_uniformDataList.size(); idx++)
|
|
{
|
|
if (m_uniformDataList[idx].name == name)
|
|
{
|
|
return m_uniformDataList[idx].location;
|
|
}
|
|
}
|
|
|
|
TCU_THROW(TestError, "Error: If name correctly requested then glGetActiveUniforms() returned active uniform data incorrectly");
|
|
return -1;
|
|
}
|
|
|
|
glw::GLuint SRGBTestProgram::getHandle (void) const
|
|
{
|
|
return m_program->getProgram();
|
|
}
|
|
|
|
bool SRGBTestProgram::getBlendRequired (void) const
|
|
{
|
|
return m_blendRequired;
|
|
}
|
|
|
|
std::string SRGBTestProgram::genFunctionCall (ShaderSamplingType samplingType, const int uniformIdx)
|
|
{
|
|
std::ostringstream functionCall;
|
|
|
|
functionCall << " mediump vec4 texelColor" << uniformIdx << " = ";
|
|
|
|
switch (samplingType)
|
|
{
|
|
case TEXTURESAMPLING_TEXTURE:
|
|
{
|
|
functionCall << "texture(uTexture" << uniformIdx << ", vs_aTexCoord); \n";
|
|
break;
|
|
}
|
|
case TEXTURESAMPLING_TEXTURE_LOD:
|
|
{
|
|
functionCall << "textureLod(uTexture" << uniformIdx << ", vs_aTexCoord, 0.0); \n";
|
|
break;
|
|
}
|
|
case TEXTURESAMPLING_TEXTURE_GRAD:
|
|
{
|
|
functionCall << "textureGrad(uTexture" << uniformIdx << ", vs_aTexCoord, vec2(0.0, 0.0), vec2(0.0, 0.0)); \n";
|
|
break;
|
|
}
|
|
case TEXTURESAMPLING_TEXTURE_OFFSET:
|
|
{
|
|
functionCall << "textureOffset(uTexture" << uniformIdx << ", vs_aTexCoord, ivec2(0.0, 0.0)); \n";
|
|
break;
|
|
}
|
|
case TEXTURESAMPLING_TEXTURE_PROJ:
|
|
{
|
|
functionCall << "textureProj(uTexture" << uniformIdx << ", vec3(vs_aTexCoord, 1.0)); \n";
|
|
break;
|
|
}
|
|
case TEXTURESAMPLING_TEXELFETCH:
|
|
{
|
|
functionCall << "texelFetch(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0); \n";
|
|
break;
|
|
}
|
|
case TEXTURESAMPLING_TEXELFETCH_OFFSET:
|
|
{
|
|
functionCall << "texelFetchOffset(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0, ivec2(0.0, 0.0)); \n";
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
DE_FATAL("Error: Sampling type not recognised");
|
|
}
|
|
}
|
|
|
|
return functionCall.str();
|
|
}
|
|
|
|
void SRGBTestProgram::genFragmentShader (void)
|
|
{
|
|
std::ostringstream source;
|
|
std::ostringstream sampleTexture;
|
|
std::ostringstream functionParameters;
|
|
std::ostringstream shaderOutputs;
|
|
|
|
// if comparison function is present resulting shader requires precisely one output
|
|
DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.outputTotal) != static_cast<int>(SHADEROUTPUTS_ONE))) );
|
|
|
|
// function parameters must equal the number of uniforms i.e. textures passed into the function
|
|
DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.uniformTotal) != static_cast<int>(m_shaderFragmentParameters.functionParameters))) );
|
|
|
|
// fragment shader cannot contain more outputs than the number of texture uniforms
|
|
DE_ASSERT( !(static_cast<int>(m_shaderFragmentParameters.outputTotal) > static_cast<int>(m_shaderFragmentParameters.uniformTotal)) ) ;
|
|
|
|
source << (glu::isContextTypeGLCore(m_context.getRenderContext().getType()) ? "#version 450\n" : "#version 310 es\n")
|
|
<< "in mediump vec2 vs_aTexCoord; \n";
|
|
|
|
for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
|
|
{
|
|
source << "layout (location = " << output << ") out mediump vec4 fs_aColor" << output << "; \n";
|
|
}
|
|
|
|
for (int uniform = 0; uniform < m_shaderFragmentParameters.uniformTotal; uniform++)
|
|
{
|
|
source << "uniform sampler2D uTexture" << uniform << "; \n";
|
|
}
|
|
|
|
if (m_shaderFragmentParameters.hasFunction == true)
|
|
{
|
|
source << m_shaderFragmentParameters.functionImplementation;
|
|
}
|
|
|
|
source << "void main () \n"
|
|
<< "{ \n";
|
|
|
|
for (int uniformIdx = 0; uniformIdx < m_shaderFragmentParameters.uniformTotal; uniformIdx++)
|
|
{
|
|
source << this->genFunctionCall(m_shaderFragmentParameters.samplingType, uniformIdx);
|
|
}
|
|
|
|
if (m_shaderFragmentParameters.hasFunction == true)
|
|
{
|
|
switch ( static_cast<FunctionParameters>(m_shaderFragmentParameters.functionParameters) )
|
|
{
|
|
case FUNCTIONPARAMETERS_ONE:
|
|
{
|
|
functionParameters << "(texelColor0)";
|
|
break;
|
|
}
|
|
case FUNCTIONPARAMETERS_TWO:
|
|
{
|
|
functionParameters << "(texelColor0, texelColor1)";
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
DE_FATAL("Error: Number of comparison function parameters invalid");
|
|
}
|
|
}
|
|
|
|
shaderOutputs << " fs_aColor0 = " << m_shaderFragmentParameters.functionName << functionParameters.str() << "; \n";
|
|
}
|
|
else
|
|
{
|
|
for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
|
|
{
|
|
shaderOutputs << " fs_aColor" << output << " = texelColor" << output << "; \n";
|
|
}
|
|
}
|
|
|
|
source << shaderOutputs.str();
|
|
source << "} \n";
|
|
|
|
m_shaderFragment = source.str();
|
|
}
|
|
|
|
class SRGBTestCase : public TestCase
|
|
{
|
|
public:
|
|
SRGBTestCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat);
|
|
~SRGBTestCase (void);
|
|
|
|
void init (void);
|
|
void deinit (void);
|
|
virtual IterateResult iterate (void);
|
|
|
|
void setSamplingGroup (const ShaderSamplingGroup samplingGroup);
|
|
void setSamplingLocations (const int px, const int py);
|
|
void setUniformToggle (const int programIdx, const std::string& uniformName, bool toggleDecode);
|
|
|
|
void addTexture (const glu::TextureTestUtil::TextureType targetType,
|
|
const int width,
|
|
const int height,
|
|
const tcu::Vec4 color,
|
|
const tcu::Sampler::WrapMode wrapS,
|
|
const tcu::Sampler::WrapMode wrapT,
|
|
const tcu::Sampler::FilterMode minFilter,
|
|
const tcu::Sampler::FilterMode magFilter,
|
|
const SRGBDecode decoding);
|
|
void addSampler (const tcu::Sampler::WrapMode wrapS,
|
|
const tcu::Sampler::WrapMode wrapT,
|
|
const tcu::Sampler::FilterMode minFilter,
|
|
const tcu::Sampler::FilterMode magFilter,
|
|
const SRGBDecode decoding);
|
|
void addShaderProgram (const FragmentShaderParameters& shaderParameters);
|
|
|
|
void genShaderPrograms (ShaderSamplingType samplingType);
|
|
void deleteShaderPrograms (void);
|
|
|
|
void readResultTextures (void);
|
|
void storeResultPixels (std::vector<tcu::Vec4>& resultPixelData);
|
|
|
|
void toggleDecode (const std::vector<UniformData>& uniformDataList);
|
|
void bindSamplerToTexture (const int samplerIdx, const int textureIdx, const deUint32 textureUnit);
|
|
void activateSampler (const int samplerIdx, const bool active);
|
|
void logColor (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const;
|
|
tcu::Vec4 formatReferenceColor (tcu::Vec4 referenceColor);
|
|
|
|
// render function has a default implentation. Can be overriden for special cases
|
|
virtual void render (void);
|
|
|
|
// following functions must be overidden to perform individual test cases
|
|
virtual void setupTest (void) = 0;
|
|
virtual bool verifyResult (void) = 0;
|
|
|
|
protected:
|
|
de::MovePtr<glu::Framebuffer> m_framebuffer;
|
|
std::vector<SRGBTestTexture*> m_textureSourceList;
|
|
std::vector<SRGBTestSampler*> m_samplerList;
|
|
std::vector<glw::GLuint> m_renderBufferList;
|
|
const tcu::Vec4 m_epsilonError;
|
|
std::vector<tcu::TextureLevel> m_textureResultList;
|
|
int m_resultOutputTotal;
|
|
tcu::TextureFormat m_resultTextureFormat;
|
|
glw::GLuint m_vaoID;
|
|
glw::GLuint m_vertexDataID;
|
|
std::vector<FragmentShaderParameters> m_shaderParametersList;
|
|
std::vector<SRGBTestProgram*> m_shaderProgramList;
|
|
ShaderSamplingGroup m_samplingGroup;
|
|
int m_px;
|
|
int m_py;
|
|
const tcu::TextureFormat m_internalFormat;
|
|
|
|
private:
|
|
void uploadTextures (void);
|
|
void initFrameBuffer (void);
|
|
void initVertexData (void);
|
|
|
|
SRGBTestCase (const SRGBTestCase&);
|
|
SRGBTestCase& operator= (const SRGBTestCase&);
|
|
};
|
|
|
|
SRGBTestCase::SRGBTestCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
|
|
: TestCase (context, name, description)
|
|
, m_epsilonError (EpsilonError::CPU)
|
|
, m_resultTextureFormat (tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8))
|
|
, m_vaoID (0)
|
|
, m_vertexDataID (0)
|
|
, m_samplingGroup (SHADERSAMPLINGGROUP_TEXTURE)
|
|
, m_internalFormat (internalFormat)
|
|
{
|
|
}
|
|
|
|
SRGBTestCase::~SRGBTestCase (void)
|
|
{
|
|
deinit();
|
|
}
|
|
|
|
void SRGBTestCase::init (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
// extension requirements for test
|
|
if ( (glu::getInternalFormat(m_internalFormat) == GL_SRGB8_ALPHA8) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode") )
|
|
{
|
|
throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_decode extension");
|
|
}
|
|
|
|
if ( (glu::getInternalFormat(m_internalFormat) == GL_SR8_EXT) && !(m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_R8")) )
|
|
{
|
|
throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_R8 extension");
|
|
}
|
|
|
|
m_framebuffer = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
|
|
|
|
if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
|
|
{
|
|
gl.enable(GL_FRAMEBUFFER_SRGB);
|
|
}
|
|
}
|
|
|
|
void SRGBTestCase::deinit (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
m_framebuffer = de::MovePtr<glu::Framebuffer>(DE_NULL);
|
|
|
|
for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
|
|
{
|
|
gl.deleteRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
|
|
}
|
|
m_renderBufferList.clear();
|
|
|
|
if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
|
|
{
|
|
gl.disable(GL_FRAMEBUFFER_SRGB);
|
|
}
|
|
|
|
for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
|
|
{
|
|
delete m_textureSourceList[textureSourceIdx];
|
|
}
|
|
m_textureSourceList.clear();
|
|
|
|
for (std::size_t samplerIdx = 0; samplerIdx < m_samplerList.size(); samplerIdx++)
|
|
{
|
|
delete m_samplerList[samplerIdx];
|
|
}
|
|
m_samplerList.clear();
|
|
|
|
if (m_vaoID != 0)
|
|
{
|
|
gl.deleteVertexArrays(1, &m_vaoID);
|
|
m_vaoID = 0;
|
|
}
|
|
|
|
if (m_vertexDataID != 0)
|
|
{
|
|
gl.deleteBuffers(1, &m_vertexDataID);
|
|
m_vertexDataID = 0;
|
|
}
|
|
}
|
|
|
|
SRGBTestCase::IterateResult SRGBTestCase::iterate (void)
|
|
{
|
|
bool result;
|
|
int startIdx = -1;
|
|
int endIdx = -1;
|
|
|
|
this->setupTest();
|
|
|
|
if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXTURE)
|
|
{
|
|
startIdx = static_cast<int>(TEXTURESAMPLING_TEXTURE_START);
|
|
endIdx = static_cast<int>(TEXTURESAMPLING_TEXTURE_END);
|
|
}
|
|
else if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXEL_FETCH)
|
|
{
|
|
startIdx = static_cast<int>(TEXTURESAMPLING_TEXELFETCH_START);
|
|
endIdx = static_cast<int>(TEXTURESAMPLING_TEXELFETCH_END);
|
|
}
|
|
else
|
|
{
|
|
DE_FATAL("Error: Sampling group not defined");
|
|
}
|
|
|
|
this->initVertexData();
|
|
this->initFrameBuffer();
|
|
|
|
// loop through all sampling types in the required sampling group, performing individual tests for each
|
|
for (int samplingTypeIdx = startIdx; samplingTypeIdx < endIdx; samplingTypeIdx++)
|
|
{
|
|
this->genShaderPrograms(static_cast<ShaderSamplingType>(samplingTypeIdx));
|
|
this->uploadTextures();
|
|
this->render();
|
|
|
|
result = this->verifyResult();
|
|
|
|
this->deleteShaderPrograms();
|
|
|
|
if (result == true)
|
|
{
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
|
|
}
|
|
else
|
|
{
|
|
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
|
|
return STOP;
|
|
}
|
|
}
|
|
|
|
return STOP;
|
|
}
|
|
|
|
void SRGBTestCase::setSamplingGroup (const ShaderSamplingGroup samplingGroup)
|
|
{
|
|
m_samplingGroup = samplingGroup;
|
|
}
|
|
|
|
void SRGBTestCase::setSamplingLocations (const int px, const int py)
|
|
{
|
|
m_px = px;
|
|
m_py = py;
|
|
}
|
|
|
|
void SRGBTestCase::addTexture ( const glu::TextureTestUtil::TextureType targetType,
|
|
const int width,
|
|
const int height,
|
|
const tcu::Vec4 color,
|
|
const tcu::Sampler::WrapMode wrapS,
|
|
const tcu::Sampler::WrapMode wrapT,
|
|
const tcu::Sampler::FilterMode minFilter,
|
|
const tcu::Sampler::FilterMode magFilter,
|
|
const SRGBDecode decoding)
|
|
{
|
|
SRGBTestTexture* texture = new SRGBTestTexture(m_context, targetType, m_internalFormat, width, height, color, wrapS, wrapT, minFilter, magFilter, decoding);
|
|
m_textureSourceList.push_back(texture);
|
|
}
|
|
|
|
void SRGBTestCase::addSampler ( const tcu::Sampler::WrapMode wrapS,
|
|
const tcu::Sampler::WrapMode wrapT,
|
|
const tcu::Sampler::FilterMode minFilter,
|
|
const tcu::Sampler::FilterMode magFilter,
|
|
const SRGBDecode decoding)
|
|
{
|
|
SRGBTestSampler *sampler = new SRGBTestSampler(m_context, wrapS, wrapT, minFilter, magFilter, decoding);
|
|
m_samplerList.push_back(sampler);
|
|
}
|
|
|
|
void SRGBTestCase::addShaderProgram (const FragmentShaderParameters& shaderParameters)
|
|
{
|
|
m_shaderParametersList.push_back(shaderParameters);
|
|
m_resultOutputTotal = shaderParameters.outputTotal;
|
|
}
|
|
|
|
void SRGBTestCase::genShaderPrograms (ShaderSamplingType samplingType)
|
|
{
|
|
for (int shaderParamsIdx = 0; shaderParamsIdx < (int)m_shaderParametersList.size(); shaderParamsIdx++)
|
|
{
|
|
m_shaderParametersList[shaderParamsIdx].samplingType = samplingType;
|
|
SRGBTestProgram* shaderProgram = new SRGBTestProgram(m_context, m_shaderParametersList[shaderParamsIdx]);
|
|
|
|
if (m_shaderParametersList[shaderParamsIdx].blendRequired == BLENDING_REQUIRED)
|
|
{
|
|
shaderProgram->setBlendRequired(true);
|
|
}
|
|
|
|
if (m_shaderParametersList[shaderParamsIdx].toggleRequired == TOGGLING_REQUIRED)
|
|
{
|
|
shaderProgram->setToggleRequired(true);
|
|
std::vector<std::string> uniformsToToggle = m_shaderParametersList[shaderParamsIdx].uniformsToToggle;
|
|
|
|
for (int uniformNameIdx = 0; uniformNameIdx < (int)uniformsToToggle.size(); uniformNameIdx++)
|
|
{
|
|
shaderProgram->setUniformToggle(shaderProgram->getUniformLocation(uniformsToToggle[uniformNameIdx]), true);
|
|
}
|
|
}
|
|
|
|
m_shaderProgramList.push_back(shaderProgram);
|
|
}
|
|
}
|
|
|
|
void SRGBTestCase::deleteShaderPrograms (void)
|
|
{
|
|
for (std::size_t idx = 0; idx < m_shaderProgramList.size(); idx++)
|
|
{
|
|
delete m_shaderProgramList[idx];
|
|
}
|
|
m_shaderProgramList.clear();
|
|
}
|
|
|
|
void SRGBTestCase::readResultTextures (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
int width = m_context.getRenderContext().getRenderTarget().getWidth();
|
|
int height = m_context.getRenderContext().getRenderTarget().getHeight();
|
|
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
|
|
|
|
m_textureResultList.resize(m_renderBufferList.size());
|
|
|
|
for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
|
|
{
|
|
gl.readBuffer(GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx);
|
|
m_textureResultList[renderBufferIdx].setStorage(m_resultTextureFormat, width, height);
|
|
glu::readPixels(m_context.getRenderContext(), 0, 0, m_textureResultList[renderBufferIdx].getAccess());
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
|
|
}
|
|
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void SRGBTestCase::storeResultPixels (std::vector<tcu::Vec4>& resultPixelData)
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
std::ostringstream message;
|
|
int width = m_context.getRenderContext().getRenderTarget().getWidth();
|
|
int height = m_context.getRenderContext().getRenderTarget().getHeight();
|
|
|
|
// ensure result sampling coordinates are within range of the result color attachment
|
|
DE_ASSERT((m_px >= 0) && (m_px < width));
|
|
DE_ASSERT((m_py >= 0) && (m_py < height));
|
|
DE_UNREF(width && height);
|
|
|
|
for (int idx = 0; idx < (int)m_textureResultList.size(); idx++)
|
|
{
|
|
resultPixelData.push_back(m_textureResultList[idx].getAccess().getPixel(m_px, m_py));
|
|
this->logColor(std::string("Result color: "), idx, resultPixelData[idx]);
|
|
}
|
|
|
|
// log error rate (threshold)
|
|
message << m_epsilonError;
|
|
log << tcu::TestLog::Message << std::string("Epsilon error: ") << message.str() << tcu::TestLog::EndMessage;
|
|
}
|
|
|
|
void SRGBTestCase::toggleDecode (const std::vector<UniformData>& uniformDataList)
|
|
{
|
|
DE_ASSERT( uniformDataList.size() <= m_textureSourceList.size() );
|
|
|
|
for (int uniformIdx = 0; uniformIdx < (int)uniformDataList.size(); uniformIdx++)
|
|
{
|
|
if (uniformDataList[uniformIdx].toggleDecode == true)
|
|
{
|
|
if (m_textureSourceList[uniformIdx]->getDecode() == SRGBDECODE_DECODE_DEFAULT)
|
|
{
|
|
// cannot toggle default
|
|
continue;
|
|
}
|
|
|
|
// toggle sRGB decode values (ignoring value if set to default)
|
|
m_textureSourceList[uniformIdx]->setDecode((SRGBDecode)((m_textureSourceList[uniformIdx]->getDecode() + 1) % SRGBDECODE_DECODE_DEFAULT));
|
|
}
|
|
}
|
|
}
|
|
|
|
void SRGBTestCase::bindSamplerToTexture (const int samplerIdx, const int textureIdx, const deUint32 textureUnit)
|
|
{
|
|
deUint32 enumConversion = textureUnit - GL_TEXTURE0;
|
|
m_textureSourceList[textureIdx]->setHasSampler(true);
|
|
m_samplerList[samplerIdx]->setTextureUnit(enumConversion);
|
|
}
|
|
|
|
void SRGBTestCase::activateSampler (const int samplerIdx, const bool active)
|
|
{
|
|
m_samplerList[samplerIdx]->setIsActive(active);
|
|
}
|
|
|
|
void SRGBTestCase::logColor (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
std::ostringstream message;
|
|
|
|
message << colorLogMessage << colorIdx << " = (" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
|
|
log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
|
|
}
|
|
|
|
tcu::Vec4 SRGBTestCase::formatReferenceColor (tcu::Vec4 referenceColor)
|
|
{
|
|
switch (glu::getInternalFormat(m_internalFormat))
|
|
{
|
|
case GL_SRGB8_ALPHA8:
|
|
{
|
|
return referenceColor;
|
|
}
|
|
case GL_SR8_EXT:
|
|
{
|
|
// zero unwanted color channels
|
|
referenceColor.y() = 0;
|
|
referenceColor.z() = 0;
|
|
return referenceColor;
|
|
}
|
|
default:
|
|
{
|
|
DE_FATAL("Error: Internal format not recognised");
|
|
return referenceColor;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SRGBTestCase::render (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
// default rendering only uses one program
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
|
|
gl.bindVertexArray(m_vaoID);
|
|
|
|
gl.useProgram(m_shaderProgramList[0]->getHandle());
|
|
|
|
for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
|
|
{
|
|
gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
|
|
gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
|
|
glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[0]->getHandle(), (std::string("uTexture") + de::toString(textureSourceIdx)).c_str());
|
|
TCU_CHECK(samplerUniformLocationID != (glw::GLuint)-1);
|
|
gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
|
|
}
|
|
|
|
for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
|
|
{
|
|
if (m_samplerList[samplerIdx]->getIsActive() == true)
|
|
{
|
|
m_samplerList[samplerIdx]->bindToTexture();
|
|
}
|
|
}
|
|
|
|
gl.drawArrays(GL_TRIANGLES, 0, 6);
|
|
|
|
for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
|
|
{
|
|
gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
|
|
}
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
gl.bindVertexArray(0);
|
|
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
void SRGBTestCase::uploadTextures (void)
|
|
{
|
|
for (std::size_t idx = 0; idx < m_textureSourceList.size(); idx++)
|
|
{
|
|
m_textureSourceList[idx]->upload();
|
|
m_textureSourceList[idx]->setParameters();
|
|
}
|
|
}
|
|
|
|
void SRGBTestCase::initFrameBuffer (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
int width = m_context.getRenderContext().getRenderTarget().getWidth();
|
|
int height = m_context.getRenderContext().getRenderTarget().getHeight();
|
|
|
|
if (m_resultOutputTotal == 0)
|
|
{
|
|
throw std::invalid_argument("SRGBTestExecutor must have at least 1 rendered result");
|
|
}
|
|
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
|
|
|
|
DE_ASSERT(m_renderBufferList.empty());
|
|
for (int outputIdx = 0; outputIdx < m_resultOutputTotal; outputIdx++)
|
|
{
|
|
glw::GLuint renderBuffer = -1;
|
|
m_renderBufferList.push_back(renderBuffer);
|
|
}
|
|
|
|
for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
|
|
{
|
|
gl.genRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
|
|
gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
|
|
gl.renderbufferStorage(GL_RENDERBUFFER, glu::getInternalFormat(m_resultTextureFormat), width, height);
|
|
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx, GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "Create and setup renderbuffer object");
|
|
}
|
|
TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
|
|
|
std::vector<glw::GLenum> renderBufferTargets(m_renderBufferList.size());
|
|
for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
|
|
{
|
|
renderBufferTargets[renderBufferIdx] = GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx;
|
|
}
|
|
gl.drawBuffers((glw::GLsizei)renderBufferTargets.size(), &renderBufferTargets[0]);
|
|
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer()");
|
|
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void SRGBTestCase::initVertexData (void)
|
|
{
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
static const glw::GLfloat squareVertexData[] =
|
|
{
|
|
// position // texcoord
|
|
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left corner
|
|
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right corner
|
|
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner
|
|
|
|
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top left corner
|
|
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top right corner
|
|
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f // bottom left corner
|
|
};
|
|
|
|
DE_ASSERT(m_vaoID == 0);
|
|
gl.genVertexArrays(1, &m_vaoID);
|
|
gl.bindVertexArray(m_vaoID);
|
|
|
|
gl.genBuffers(1, &m_vertexDataID);
|
|
gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexDataID);
|
|
gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);
|
|
|
|
gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
|
|
gl.enableVertexAttribArray(0);
|
|
gl.vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
|
|
gl.enableVertexAttribArray(1);
|
|
|
|
gl.bindVertexArray(0);
|
|
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
class TextureDecodeSkippedCase : public SRGBTestCase
|
|
{
|
|
public:
|
|
TextureDecodeSkippedCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
|
|
: SRGBTestCase (context, name, description, internalFormat) {}
|
|
|
|
~TextureDecodeSkippedCase (void) {}
|
|
|
|
void setupTest (void);
|
|
bool verifyResult (void);
|
|
};
|
|
|
|
void TextureDecodeSkippedCase::setupTest (void)
|
|
{
|
|
// TEST STEPS:
|
|
// - create and set texture to DECODE_SKIP_EXT
|
|
// - store texture on GPU
|
|
// - in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
|
|
// - on the host, read back the pixel values into a tcu::TextureLevel
|
|
// - analyse the texel values, expecting them in sRGB format i.e. linear space decoding was skipped
|
|
|
|
FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_SKIP_DECODE);
|
|
|
|
this->addShaderProgram(shaderParameters);
|
|
this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
|
|
|
|
this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
|
|
}
|
|
|
|
bool TextureDecodeSkippedCase::verifyResult (void)
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
const int resultColorIdx = 0;
|
|
std::vector<tcu::Vec4> pixelResultList;
|
|
tcu::Vec4 pixelConverted;
|
|
tcu::Vec4 pixelReference;
|
|
tcu::Vec4 pixelExpected;
|
|
|
|
this->readResultTextures();
|
|
this->storeResultPixels(pixelResultList);
|
|
|
|
pixelConverted = tcu::sRGBToLinear(pixelResultList[resultColorIdx]);
|
|
pixelReference = this->formatReferenceColor(getColorReferenceLinear());
|
|
pixelExpected = this->formatReferenceColor(getColorReferenceSRGB());
|
|
|
|
this->formatReferenceColor(pixelReference);
|
|
this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
|
|
|
|
// result color 0 should be sRGB. Compare with linear reference color
|
|
if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
|
|
{
|
|
log << tcu::TestLog::Message << std::string("sRGB as expected") << tcu::TestLog::EndMessage;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
log << tcu::TestLog::Message << std::string("not sRGB as expected") << tcu::TestLog::EndMessage;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
class TextureDecodeEnabledCase : public SRGBTestCase
|
|
{
|
|
public:
|
|
TextureDecodeEnabledCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
|
|
: SRGBTestCase (context, name, description, internalFormat) {}
|
|
|
|
~TextureDecodeEnabledCase (void) {}
|
|
|
|
void setupTest (void);
|
|
bool verifyResult (void);
|
|
};
|
|
|
|
void TextureDecodeEnabledCase::setupTest (void)
|
|
{
|
|
// TEST STEPS:
|
|
// - create and set texture to DECODE_EXT
|
|
// - store texture on GPU
|
|
// - in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
|
|
// - on the host, read back the pixel values into a tcu::TextureLevel
|
|
// - analyse the texel values, expecting them in lRGB format i.e. linear space decoding was enabled
|
|
|
|
FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_DECODE);
|
|
|
|
this->addShaderProgram(shaderParameters);
|
|
|
|
this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
|
|
|
|
this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
|
|
}
|
|
|
|
bool TextureDecodeEnabledCase::verifyResult (void)
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
const int resultColorIdx = 0;
|
|
std::vector<tcu::Vec4> pixelResultList;
|
|
tcu::Vec4 pixelConverted;
|
|
tcu::Vec4 pixelReference;
|
|
tcu::Vec4 pixelExpected;
|
|
|
|
this->readResultTextures();
|
|
this->storeResultPixels(pixelResultList);
|
|
|
|
pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
|
|
pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
|
|
pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
|
|
|
|
this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
|
|
|
|
// result color 0 should be SRGB. Compare with sRGB reference color
|
|
if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
|
|
{
|
|
log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
class TexelFetchDecodeSkippedcase : public SRGBTestCase
|
|
{
|
|
public:
|
|
TexelFetchDecodeSkippedcase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
|
|
: SRGBTestCase (context, name, description, internalFormat) {}
|
|
|
|
~TexelFetchDecodeSkippedcase (void) {}
|
|
|
|
void setupTest (void);
|
|
bool verifyResult (void);
|
|
};
|
|
|
|
void TexelFetchDecodeSkippedcase::setupTest (void)
|
|
{
|
|
// TEST STEPS:
|
|
// - create and set texture to DECODE_SKIP_EXT
|
|
// - store texture on GPU
|
|
// - in fragment shader, sample the texture using texelFetch*() and render texel values to a color attachment in the FBO
|
|
// - on the host, read back the pixel values into a tcu::TextureLevel
|
|
// - analyse the texel values, expecting them in lRGB format i.e. linear space decoding is always enabled with texelFetch*()
|
|
|
|
FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_SKIP_DECODE);
|
|
|
|
this->addShaderProgram(shaderParameters);
|
|
|
|
this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
|
|
|
|
this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXEL_FETCH);
|
|
}
|
|
|
|
bool TexelFetchDecodeSkippedcase::verifyResult (void)
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
const int resultColorIdx = 0;
|
|
std::vector<tcu::Vec4> pixelResultList;
|
|
tcu::Vec4 pixelReference;
|
|
tcu::Vec4 pixelExpected;
|
|
|
|
this->readResultTextures();
|
|
this->storeResultPixels(pixelResultList);
|
|
|
|
pixelReference = pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
|
|
|
|
this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
|
|
|
|
// result color 0 should be linear due to automatic conversion via texelFetch*(). Compare with linear reference color
|
|
if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelResultList[0] - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelResultList[0], pixelReference))) )
|
|
{
|
|
log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
class GPUConversionDecodeEnabledCase : public SRGBTestCase
|
|
{
|
|
public:
|
|
GPUConversionDecodeEnabledCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
|
|
: SRGBTestCase (context, name, description, internalFormat) {}
|
|
|
|
~GPUConversionDecodeEnabledCase (void) {}
|
|
|
|
void setupTest (void);
|
|
bool verifyResult (void);
|
|
};
|
|
|
|
void GPUConversionDecodeEnabledCase::setupTest (void)
|
|
{
|
|
// TEST STEPS:
|
|
// - create and set texture_a to DECODE_SKIP_EXT and texture_b to default
|
|
// - store textures on GPU
|
|
// - in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_b
|
|
// - in fragment shader, compare converted texture_b with texture_a
|
|
// - render green image for pass or red for fail
|
|
|
|
ComparisonFunction comparisonFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
|
|
|
|
FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &comparisonFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_SKIP_DECODE);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_DECODE_DEFAULT);
|
|
|
|
this->addShaderProgram(shaderParameters);
|
|
|
|
this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
|
|
|
|
this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
|
|
}
|
|
|
|
bool GPUConversionDecodeEnabledCase::verifyResult (void)
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
const int resultColorIdx = 0;
|
|
std::vector<tcu::Vec4> pixelResultList;
|
|
|
|
this->readResultTextures();
|
|
this->storeResultPixels(pixelResultList);
|
|
this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
|
|
|
|
// result color returned from GPU is either green (pass) or fail (red)
|
|
if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
|
|
{
|
|
log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
class DecodeToggledCase : public SRGBTestCase
|
|
{
|
|
public:
|
|
DecodeToggledCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
|
|
: SRGBTestCase (context, name, description, internalFormat) {}
|
|
|
|
~DecodeToggledCase (void) {}
|
|
|
|
void render (void);
|
|
void setupTest (void);
|
|
bool verifyResult (void);
|
|
};
|
|
|
|
void DecodeToggledCase::render (void)
|
|
{
|
|
// override the base SRGBTestCase render function with the purpose of switching between shader programs,
|
|
// toggling texture sRGB decode state between draw calls
|
|
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
|
|
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
|
|
gl.bindVertexArray(m_vaoID);
|
|
|
|
for (std::size_t programIdx = 0; programIdx < m_shaderProgramList.size(); programIdx++)
|
|
{
|
|
gl.useProgram(m_shaderProgramList[programIdx]->getHandle());
|
|
|
|
this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
|
|
|
|
for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
|
|
{
|
|
gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
|
|
gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
|
|
glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[programIdx]->getHandle(), (std::string("uTexture") + de::toString(textureSourceIdx)).c_str());
|
|
TCU_CHECK(samplerUniformLocationID != (glw::GLuint) - 1);
|
|
gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
|
|
}
|
|
|
|
for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
|
|
{
|
|
if (m_samplerList[samplerIdx]->getIsActive() == true)
|
|
{
|
|
m_samplerList[samplerIdx]->bindToTexture();
|
|
}
|
|
}
|
|
|
|
if (m_shaderProgramList[programIdx]->getBlendRequired() == true)
|
|
{
|
|
gl.enable(GL_BLEND);
|
|
gl.blendEquation(GL_MAX);
|
|
gl.blendFunc(GL_ONE, GL_ONE);
|
|
}
|
|
else
|
|
{
|
|
gl.disable(GL_BLEND);
|
|
}
|
|
|
|
gl.drawArrays(GL_TRIANGLES, 0, 6);
|
|
|
|
// reset sRGB decode state on textures
|
|
this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
|
|
}
|
|
|
|
for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
|
|
{
|
|
gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
|
|
}
|
|
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
gl.bindVertexArray(0);
|
|
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
void DecodeToggledCase::setupTest (void)
|
|
{
|
|
// TEST STEPS:
|
|
// - create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
|
|
// - create and use two seperate shader programs, program_a and program_b, each using different fragment shaders
|
|
// - store texture_a and texture_b on GPU
|
|
// FIRST PASS:
|
|
// - use program_a
|
|
// - in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_a
|
|
// - in fragment shader, test converted texture_a value with texture_b
|
|
// - render green image for pass or red for fail
|
|
// - store result in a color attachement 0
|
|
// TOGGLE STAGE
|
|
// - during rendering, toggle texture_a from DECODE_SKIP_EXT to DECODE_EXT
|
|
// SECOND PASS:
|
|
// - use program_b
|
|
// - in fragment shader, sample both textures using texture*() and manually perform equality check. Both should be linear
|
|
// - blend first pass result with second pass. Anything but a green result equals fail
|
|
|
|
ComparisonFunction srgbToLinearFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
|
|
ComparisonFunction colorsEqualFunction("colorsEqualCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionEqualCheck());
|
|
|
|
FragmentShaderParameters shaderParametersA(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &srgbToLinearFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
|
|
FragmentShaderParameters shaderParametersB(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &colorsEqualFunction, BLENDING_REQUIRED, TOGGLING_REQUIRED);
|
|
|
|
// need to specify which texture uniform to toggle DECODE_EXT/SKIP_DECODE_EXT
|
|
shaderParametersB.uniformsToToggle.push_back("uTexture0");
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_SKIP_DECODE);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_DECODE);
|
|
|
|
this->addShaderProgram(shaderParametersA);
|
|
this->addShaderProgram(shaderParametersB);
|
|
|
|
this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
|
|
this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
|
|
}
|
|
|
|
bool DecodeToggledCase::verifyResult (void)
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
const int resultColorIdx = 0;
|
|
std::vector<tcu::Vec4> pixelResultList;
|
|
|
|
this->readResultTextures();
|
|
this->storeResultPixels(pixelResultList);
|
|
this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
|
|
|
|
// result color is either green (pass) or fail (red)
|
|
if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
|
|
{
|
|
log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
class DecodeMultipleTexturesCase : public SRGBTestCase
|
|
{
|
|
public:
|
|
DecodeMultipleTexturesCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
|
|
: SRGBTestCase (context, name, description, internalFormat) {}
|
|
|
|
~DecodeMultipleTexturesCase (void) {}
|
|
|
|
void setupTest (void);
|
|
bool verifyResult (void);
|
|
};
|
|
|
|
void DecodeMultipleTexturesCase::setupTest (void)
|
|
{
|
|
// TEST STEPS:
|
|
// - create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
|
|
// - upload textures to the GPU and bind to seperate uniform variables
|
|
// - sample both textures using texture*()
|
|
// - read texel values back to the CPU
|
|
// - compare the texel values, both should be different from each other
|
|
|
|
FragmentShaderParameters shaderParameters(SHADEROUTPUTS_TWO, SHADERUNIFORMS_TWO, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_SKIP_DECODE);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_DECODE);
|
|
|
|
this->addShaderProgram(shaderParameters);
|
|
|
|
this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
|
|
this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
|
|
}
|
|
|
|
bool DecodeMultipleTexturesCase::verifyResult (void)
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
const int resultColorIdx = 0;
|
|
std::vector<tcu::Vec4> pixelResultList;
|
|
tcu::Vec4 pixelExpected0;
|
|
tcu::Vec4 pixelExpected1;
|
|
|
|
this->readResultTextures();
|
|
this->storeResultPixels(pixelResultList);
|
|
|
|
pixelExpected0 = this->formatReferenceColor(getColorReferenceSRGB());
|
|
pixelExpected1 = this->formatReferenceColor(getColorReferenceLinear());
|
|
|
|
this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected0);
|
|
this->logColor(std::string("Expected color: "), resultColorIdx +1, pixelExpected1);
|
|
|
|
// check if the two textures have different values i.e. uTexture0 = sRGB and uTexture1 = linear
|
|
if ( !(tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], pixelResultList[resultColorIdx +1]))) )
|
|
{
|
|
log << tcu::TestLog::Message << std::string("texel values are different") << tcu::TestLog::EndMessage;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
log << tcu::TestLog::Message << std::string("texel values are equal") << tcu::TestLog::EndMessage;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
class DecodeSamplerCase : public SRGBTestCase
|
|
{
|
|
public:
|
|
DecodeSamplerCase (Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
|
|
: SRGBTestCase (context, name, description, internalFormat) {}
|
|
|
|
~DecodeSamplerCase (void) {}
|
|
|
|
void setupTest (void);
|
|
bool verifyResult (void);
|
|
};
|
|
|
|
void DecodeSamplerCase::setupTest (void)
|
|
{
|
|
// TEST STEPS:
|
|
// - create and set texture_a to DECODE_SKIP_EXT
|
|
// - upload texture to the GPU and bind to sampler
|
|
// - sample texture using texture*()
|
|
// - read texel values back to the CPU
|
|
// - compare the texel values, should be in sampler format (linear)
|
|
|
|
FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
|
|
|
|
this->addTexture( TEXTURETYPE_2D,
|
|
TestDimensions::WIDTH,
|
|
TestDimensions::HEIGHT,
|
|
getColorReferenceLinear(),
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_SKIP_DECODE);
|
|
|
|
this->addSampler( tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::MIRRORED_REPEAT_GL,
|
|
tcu::Sampler::LINEAR,
|
|
tcu::Sampler::LINEAR,
|
|
SRGBDECODE_DECODE);
|
|
|
|
this->addShaderProgram(shaderParameters);
|
|
|
|
this->bindSamplerToTexture(0, 0, GL_TEXTURE0);
|
|
this->activateSampler(0, true);
|
|
|
|
this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
|
|
this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
|
|
}
|
|
|
|
bool DecodeSamplerCase::verifyResult (void)
|
|
{
|
|
tcu::TestLog& log = m_context.getTestContext().getLog();
|
|
const int resultColorIdx = 0;
|
|
std::vector<tcu::Vec4> pixelResultList;
|
|
tcu::Vec4 pixelConverted;
|
|
tcu::Vec4 pixelReference;
|
|
tcu::Vec4 pixelExpected;
|
|
|
|
this->readResultTextures();
|
|
this->storeResultPixels(pixelResultList);
|
|
|
|
pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
|
|
pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
|
|
pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
|
|
|
|
this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
|
|
|
|
// texture was rendered using a sampler object with setting DECODE_EXT, therefore, results should be linear
|
|
if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
|
|
{
|
|
log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
} // anonymous
|
|
|
|
SRGBDecodeTests::SRGBDecodeTests (Context& context)
|
|
: TestCaseGroup (context, "skip_decode", "sRGB skip decode tests")
|
|
{
|
|
}
|
|
|
|
SRGBDecodeTests::~SRGBDecodeTests (void)
|
|
{
|
|
}
|
|
|
|
void SRGBDecodeTests::init (void)
|
|
{
|
|
const TestGroupConfig testGroupConfigList[] =
|
|
{
|
|
TestGroupConfig("srgba8", "srgb decode tests using srgba internal format", tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8)),
|
|
TestGroupConfig("sr8", "srgb decode tests using sr8 internal format", tcu::TextureFormat(tcu::TextureFormat::sR, tcu::TextureFormat::UNORM_INT8))
|
|
};
|
|
|
|
// create groups for all desired internal formats, adding test cases to each
|
|
for (std::size_t idx = 0; idx < DE_LENGTH_OF_ARRAY(testGroupConfigList); idx++)
|
|
{
|
|
tcu::TestCaseGroup* const testGroup = new tcu::TestCaseGroup(m_testCtx, testGroupConfigList[idx].name, testGroupConfigList[idx].description);
|
|
tcu::TestNode::addChild(testGroup);
|
|
|
|
testGroup->addChild(new TextureDecodeSkippedCase (m_context, "skipped", "testing for sRGB color values with sRGB texture decoding skipped", testGroupConfigList[idx].internalFormat));
|
|
testGroup->addChild(new TextureDecodeEnabledCase (m_context, "enabled", "testing for linear color values with sRGB texture decoding enabled", testGroupConfigList[idx].internalFormat));
|
|
testGroup->addChild(new TexelFetchDecodeSkippedcase (m_context, "texel_fetch", "testing for linear color values with sRGB texture decoding skipped", testGroupConfigList[idx].internalFormat));
|
|
testGroup->addChild(new GPUConversionDecodeEnabledCase (m_context, "conversion_gpu", "sampling linear values and performing conversion on the gpu", testGroupConfigList[idx].internalFormat));
|
|
testGroup->addChild(new DecodeToggledCase (m_context, "toggled", "toggle the sRGB decoding between draw calls", testGroupConfigList[idx].internalFormat));
|
|
testGroup->addChild(new DecodeMultipleTexturesCase (m_context, "multiple_textures","upload multiple textures with different sRGB decode values and sample",testGroupConfigList[idx].internalFormat));
|
|
testGroup->addChild(new DecodeSamplerCase (m_context, "using_sampler", "testing that sampler object takes priority over texture state", testGroupConfigList[idx].internalFormat));
|
|
}
|
|
}
|
|
|
|
} // Functional
|
|
} // gles31
|
|
} // deqp
|