/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 3.1 Module * ------------------------------------------------- * * Copyright 2018 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 Built-in function tests for uniform constants. *//*--------------------------------------------------------------------*/ #include "es31fShaderUniformIntegerFunctionTests.hpp" #include "glsShaderExecUtil.hpp" #include "glwFunctions.hpp" #include "tcuTestLog.hpp" #include namespace deqp { namespace gles31 { namespace Functional { using std::vector; using std::string; using tcu::TestLog; using namespace gls::ShaderExecUtil; class UniformIntegerFunctionCase : public TestCase { public: UniformIntegerFunctionCase (Context& context, const char* description, int inputValue, glu::Precision precision, glu::ShaderType shaderType); ~UniformIntegerFunctionCase (void); void init (void); void deinit (void); IterateResult iterate (void); virtual const char* getFunctionName() = 0; virtual int computeExpectedResult(deInt32 value) = 0; protected: UniformIntegerFunctionCase (const UniformIntegerFunctionCase& other); UniformIntegerFunctionCase& operator= (const UniformIntegerFunctionCase& other); private: ShaderSpec m_spec; glu::ShaderType m_shaderType; int m_input; int m_value; ShaderExecutor* m_executor; }; static std::string getCaseName (glu::Precision precision, glu::ShaderType shaderType); UniformIntegerFunctionCase::UniformIntegerFunctionCase(Context& context, const char* description, int inputValue, glu::Precision precision, glu::ShaderType shaderType) : TestCase(context, getCaseName(precision, shaderType).c_str(), description) , m_shaderType(shaderType) , m_input(inputValue) , m_value(0) , m_executor(DE_NULL) { m_spec.version = glu::GLSL_VERSION_310_ES; std::ostringstream oss; glu::VarType varType(glu::TYPE_INT, precision); oss << "uniform " << glu::declare(varType, "value", 0) << ";\n"; m_spec.globalDeclarations = oss.str(); m_spec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_INT, glu::PRECISION_LOWP))); m_spec.outputs.push_back(Symbol("comparison", glu::VarType(glu::TYPE_BOOL, glu::PRECISION_LAST))); } UniformIntegerFunctionCase::~UniformIntegerFunctionCase(void) { UniformIntegerFunctionCase::deinit(); } void UniformIntegerFunctionCase::deinit(void) { delete m_executor; m_executor = DE_NULL; } void UniformIntegerFunctionCase::init(void) { std::ostringstream oss; oss << "result = " << getFunctionName() << "(value);\n" "comparison = (" << getFunctionName() << "(value) == " << computeExpectedResult(m_input) << ");\n"; m_spec.source = oss.str(); DE_ASSERT(!m_executor); m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec); m_testCtx.getLog() << m_executor; if (!m_executor->isOk()) throw tcu::TestError("Compile failed"); m_value = m_context.getRenderContext().getFunctions().getUniformLocation(m_executor->getProgram(), "value"); } tcu::TestNode::IterateResult UniformIntegerFunctionCase::iterate(void) { deInt32 result; deBool comparison; vector outputPointers (2); outputPointers[0]= &result; outputPointers[1] = &comparison; m_executor->useProgram(); m_context.getRenderContext().getFunctions().uniform1i(m_value, m_input); m_executor->execute(1, DE_NULL, &outputPointers[0]); int expectedResult = computeExpectedResult(m_input); if (result != expectedResult) { m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for " << getFunctionName() << "(" << m_input << ") == " << expectedResult << TestLog::EndMessage; m_testCtx.getLog() << TestLog::Message << "input: " << m_input << TestLog::EndMessage; m_testCtx.getLog() << TestLog::Message << "result: " << result << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed"); return STOP; } else if (!comparison) { m_testCtx.getLog() << TestLog::Message << "ERROR: result is as expected, but not when use in condition statement (" << getFunctionName() << "(" << m_input << ") == " << expectedResult << ") == true" << TestLog::EndMessage; m_testCtx.getLog() << TestLog::Message << "input:" << m_input << TestLog::EndMessage; m_testCtx.getLog() << TestLog::Message << "result: " << result << TestLog::EndMessage; m_testCtx.getLog() << TestLog::Message << "comparison: " << comparison << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed"); return STOP; } m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } static const char* getPrecisionPostfix (glu::Precision precision) { static const char* s_postfix[] = { "lowp", "mediump", "highp" }; DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST); DE_ASSERT(de::inBounds(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix))); return s_postfix[precision]; } static const char* getShaderTypePostfix (glu::ShaderType shaderType) { static const char* s_postfix[] = { "_vertex", "_fragment", "_geometry", "_tess_control", "_tess_eval", "_compute" }; DE_ASSERT(de::inBounds(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix))); return s_postfix[shaderType]; } static std::string getCaseName (glu::Precision precision, glu::ShaderType shaderType) { return string(getPrecisionPostfix(precision)) + getShaderTypePostfix(shaderType); } static int findMSB (deInt32 value) { if (value > 0) return 31 - deClz32((deUint32)value); else if (value < 0) return 31 - deClz32(~(deUint32)value); else return -1; } class FindMSBEdgeCase : public UniformIntegerFunctionCase { public: FindMSBEdgeCase(Context& context, int inputValue, glu::Precision precision, glu::ShaderType shaderType) : UniformIntegerFunctionCase(context, "findMSB", inputValue, precision, shaderType) { } protected: const char* getFunctionName() { return "findMSB"; } int computeExpectedResult(deInt32 input) { return findMSB(input); } }; static int findLSB (deUint32 value) { for (int i = 0; i < 32; i++) { if (value & (1u< static void addFunctionCases (TestCaseGroup* parent, const char* functionName, int input) { tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName); parent->addChild(group); for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++) { for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++) { group->addChild(new TestClass(parent->getContext(), input, glu::Precision(prec), glu::ShaderType(shaderTypeNdx))); } } } ShaderUniformIntegerFunctionTests::ShaderUniformIntegerFunctionTests(Context& context) : TestCaseGroup(context, "uniform", "Function on uniform") { } ShaderUniformIntegerFunctionTests::~ShaderUniformIntegerFunctionTests() { } void ShaderUniformIntegerFunctionTests::init() { addFunctionCases(this, "findMSBZero", 0); addFunctionCases(this, "findMSBMinusOne", -1); addFunctionCases(this, "findLSBZero", 0); addFunctionCases(this, "findLSBMinusOne", -1); } } } }