1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL Shared Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Shared shader constant expression test components 22 *//*--------------------------------------------------------------------*/ 23 24#include "glsShaderConstExprTests.hpp" 25#include "glsShaderLibrary.hpp" 26#include "glsShaderLibraryCase.hpp" 27 28#include "tcuStringTemplate.hpp" 29 30#include "deStringUtil.hpp" 31#include "deMath.h" 32 33namespace deqp 34{ 35namespace gls 36{ 37namespace ShaderConstExpr 38{ 39 40std::vector<tcu::TestNode*> createTests (tcu::TestContext& testContext, 41 glu::RenderContext& renderContext, 42 const glu::ContextInfo& contextInfo, 43 const TestParams* cases, 44 int numCases, 45 glu::GLSLVersion version, 46 TestShaderStage testStage) 47{ 48 using std::string; 49 using std::vector; 50 using gls::sl::ShaderCase; 51 52 // Needed for autogenerating shader code for increased component counts 53 DE_STATIC_ASSERT(glu::TYPE_FLOAT+1 == glu::TYPE_FLOAT_VEC2); 54 DE_STATIC_ASSERT(glu::TYPE_FLOAT+2 == glu::TYPE_FLOAT_VEC3); 55 DE_STATIC_ASSERT(glu::TYPE_FLOAT+3 == glu::TYPE_FLOAT_VEC4); 56 57 DE_STATIC_ASSERT(glu::TYPE_INT+1 == glu::TYPE_INT_VEC2); 58 DE_STATIC_ASSERT(glu::TYPE_INT+2 == glu::TYPE_INT_VEC3); 59 DE_STATIC_ASSERT(glu::TYPE_INT+3 == glu::TYPE_INT_VEC4); 60 61 DE_STATIC_ASSERT(glu::TYPE_UINT+1 == glu::TYPE_UINT_VEC2); 62 DE_STATIC_ASSERT(glu::TYPE_UINT+2 == glu::TYPE_UINT_VEC3); 63 DE_STATIC_ASSERT(glu::TYPE_UINT+3 == glu::TYPE_UINT_VEC4); 64 65 DE_STATIC_ASSERT(glu::TYPE_BOOL+1 == glu::TYPE_BOOL_VEC2); 66 DE_STATIC_ASSERT(glu::TYPE_BOOL+2 == glu::TYPE_BOOL_VEC3); 67 DE_STATIC_ASSERT(glu::TYPE_BOOL+3 == glu::TYPE_BOOL_VEC4); 68 69 DE_ASSERT(testStage); 70 71 const char* shaderTemplateSrc = 72 "#version ${GLES_VERSION}\n" 73 "precision highp float;\n" 74 "precision highp int;\n" 75 "${DECLARATIONS}\n" 76 "void main()\n" 77 "{\n" 78 " const ${CASE_BASE_TYPE} cval = ${CASE_EXPRESSION};\n" 79 " out0 = cval;\n" 80 " ${OUTPUT}\n" 81 "}\n"; 82 83 const tcu::StringTemplate shaderTemplate (shaderTemplateSrc); 84 vector<tcu::TestNode*> ret; 85 vector<ShaderCase::ValueBlock> shaderOutput (1); 86 87 shaderOutput[0].arrayLength = 1; 88 shaderOutput[0].values.push_back(ShaderCase::Value()); 89 shaderOutput[0].values[0].storageType = ShaderCase::Value::STORAGE_OUTPUT; 90 shaderOutput[0].values[0].valueName = "out0"; 91 shaderOutput[0].values[0].dataType = glu::TYPE_FLOAT; 92 shaderOutput[0].values[0].arrayLength = 1; 93 shaderOutput[0].values[0].elements.push_back(ShaderCase::Value::Element()); 94 95 for (int caseNdx = 0; caseNdx < numCases; caseNdx++) 96 { 97 std::map<string, string> shaderTemplateParams; 98 const int minComponents = cases[caseNdx].minComponents; 99 const int maxComponents = cases[caseNdx].maxComponents; 100 const DataType inType = cases[caseNdx].inType; 101 const DataType outType = cases[caseNdx].outType; 102 const string expression = cases[caseNdx].expression; 103 // Check for presence of func(vec, scalar) style specialization, use as gatekeeper for applying said specialization 104 const bool alwaysScalar = expression.find("${MT}")!=string::npos; 105 ShaderCase::Value& expected = shaderOutput[0].values[0]; 106 107 switch (outType) 108 { 109 case glu::TYPE_INT: 110 expected.elements[0].int32 = (int)cases[caseNdx].output; 111 break; 112 113 case glu::TYPE_UINT: 114 expected.elements[0].int32 = (unsigned int)cases[caseNdx].output; 115 break; 116 117 case glu::TYPE_BOOL: 118 expected.elements[0].bool32 = cases[caseNdx].output!=0.0f; 119 break; 120 121 case glu::TYPE_FLOAT: 122 expected.elements[0].float32 = cases[caseNdx].output; 123 break; 124 125 default: 126 DE_ASSERT(false); 127 } 128 129 expected.dataType = outType; 130 131 shaderTemplateParams["GLES_VERSION"] = version == glu::GLSL_VERSION_300_ES ? "300 es" : "100"; 132 shaderTemplateParams["CASE_BASE_TYPE"] = glu::getDataTypeName(outType); 133 shaderTemplateParams["DECLARATIONS"] = "${DECLARATIONS}"; 134 shaderTemplateParams["OUTPUT"] = "${OUTPUT}"; 135 136 for (int compCount = minComponents-1; compCount < maxComponents; compCount++) 137 { 138 vector<tcu::TestNode*> children; 139 std::map<string, string> expressionTemplateParams; 140 string typeName = glu::getDataTypeName((glu::DataType)(inType + compCount)); // results in float, vec2, vec3, vec4 progression (same for other primitive types) 141 const char* componentAccess[] = {"", ".y", ".z", ".w"}; 142 const tcu::StringTemplate expressionTemplate (expression); 143 // Add type to case name if we are generating multiple versions 144 const string caseName = string(cases[caseNdx].name) + (minComponents==maxComponents ? "" : ("_" + typeName)); 145 146 // ${T} => final type, ${MT} => final type but with scalar version usable even when T is a vector 147 expressionTemplateParams["T"] = typeName; 148 expressionTemplateParams["MT"] = typeName; 149 150 shaderTemplateParams["CASE_EXPRESSION"] = expressionTemplate.specialize(expressionTemplateParams) + componentAccess[compCount]; // Add vector access to expression as needed 151 152 { 153 const string mapped = shaderTemplate.specialize(shaderTemplateParams); 154 155 if (testStage & SHADER_VERTEX) 156 ret.push_back(new ShaderCase(testContext, 157 renderContext, 158 contextInfo, 159 (caseName + "_vertex").c_str(), 160 "", 161 ShaderCase::ShaderCaseSpecification::generateSharedSourceVertexCase(ShaderCase::EXPECT_PASS, 162 version, 163 shaderOutput, 164 mapped))); 165 166 if (testStage & SHADER_FRAGMENT) 167 ret.push_back(new ShaderCase(testContext, 168 renderContext, 169 contextInfo, 170 (caseName + "_fragment").c_str(), 171 "", 172 ShaderCase::ShaderCaseSpecification::generateSharedSourceFragmentCase(ShaderCase::EXPECT_PASS, 173 version, 174 shaderOutput, 175 mapped))); 176 } 177 178 // Deal with functions that allways accept one ore more scalar parameters even when others are vectors 179 if (alwaysScalar && compCount > 0) 180 { 181 const string scalarCaseName = string(cases[caseNdx].name) + "_" + typeName + "_" + glu::getDataTypeName(inType); 182 183 expressionTemplateParams["MT"] = glu::getDataTypeName(inType); 184 shaderTemplateParams["CASE_EXPRESSION"] = expressionTemplate.specialize(expressionTemplateParams) + componentAccess[compCount]; 185 186 { 187 const string mapped = shaderTemplate.specialize(shaderTemplateParams); 188 189 if (testStage & SHADER_VERTEX) 190 ret.push_back(new ShaderCase(testContext, 191 renderContext, 192 contextInfo, 193 (scalarCaseName + "_vertex").c_str(), 194 "", 195 ShaderCase::ShaderCaseSpecification::generateSharedSourceVertexCase(ShaderCase::EXPECT_PASS, 196 version, 197 shaderOutput, 198 mapped))); 199 200 if (testStage & SHADER_FRAGMENT) 201 ret.push_back(new ShaderCase(testContext, 202 renderContext, 203 contextInfo, 204 (scalarCaseName + "_fragment").c_str(), 205 "", 206 ShaderCase::ShaderCaseSpecification::generateSharedSourceFragmentCase(ShaderCase::EXPECT_PASS, 207 version, 208 shaderOutput, 209 mapped))); 210 } 211 } 212 } 213 } 214 215 return ret; 216} 217 218} // ShaderConstExpr 219} // gls 220} // deqp 221