| /*------------------------------------------------------------------------- |
| * 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 |
| m_shaderVertex = "#version 310 es \n" |
| "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 << "#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) |
| { |
| // 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())); |
| } |
| |
| 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(); |
| |
| 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 |