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 40static void addOutputVar (glu::sl::ValueBlock* dst, glu::DataType type, float output) 41{ 42 dst->outputs.push_back(glu::sl::Value()); 43 44 { 45 glu::sl::Value& value = dst->outputs.back(); 46 47 value.name = "out0"; 48 value.type = glu::VarType(type, glu::PRECISION_LAST); 49 value.elements.resize(1); 50 51 switch (type) 52 { 53 case glu::TYPE_INT: 54 value.elements[0].int32 = (int)output; 55 break; 56 57 case glu::TYPE_UINT: 58 value.elements[0].int32 = (unsigned int)output; 59 break; 60 61 case glu::TYPE_BOOL: 62 value.elements[0].bool32 = output!=0.0f; 63 break; 64 65 case glu::TYPE_FLOAT: 66 value.elements[0].float32 = output; 67 break; 68 69 default: 70 DE_ASSERT(false); 71 } 72 } 73} 74 75std::vector<tcu::TestNode*> createTests (tcu::TestContext& testContext, 76 glu::RenderContext& renderContext, 77 const glu::ContextInfo& contextInfo, 78 const TestParams* cases, 79 int numCases, 80 glu::GLSLVersion version, 81 TestShaderStage testStage) 82{ 83 using std::string; 84 using std::vector; 85 using gls::ShaderLibraryCase; 86 87 // Needed for autogenerating shader code for increased component counts 88 DE_STATIC_ASSERT(glu::TYPE_FLOAT+1 == glu::TYPE_FLOAT_VEC2); 89 DE_STATIC_ASSERT(glu::TYPE_FLOAT+2 == glu::TYPE_FLOAT_VEC3); 90 DE_STATIC_ASSERT(glu::TYPE_FLOAT+3 == glu::TYPE_FLOAT_VEC4); 91 92 DE_STATIC_ASSERT(glu::TYPE_INT+1 == glu::TYPE_INT_VEC2); 93 DE_STATIC_ASSERT(glu::TYPE_INT+2 == glu::TYPE_INT_VEC3); 94 DE_STATIC_ASSERT(glu::TYPE_INT+3 == glu::TYPE_INT_VEC4); 95 96 DE_STATIC_ASSERT(glu::TYPE_UINT+1 == glu::TYPE_UINT_VEC2); 97 DE_STATIC_ASSERT(glu::TYPE_UINT+2 == glu::TYPE_UINT_VEC3); 98 DE_STATIC_ASSERT(glu::TYPE_UINT+3 == glu::TYPE_UINT_VEC4); 99 100 DE_STATIC_ASSERT(glu::TYPE_BOOL+1 == glu::TYPE_BOOL_VEC2); 101 DE_STATIC_ASSERT(glu::TYPE_BOOL+2 == glu::TYPE_BOOL_VEC3); 102 DE_STATIC_ASSERT(glu::TYPE_BOOL+3 == glu::TYPE_BOOL_VEC4); 103 104 DE_ASSERT(testStage); 105 106 const char* shaderTemplateSrc = 107 "#version ${GLES_VERSION}\n" 108 "precision highp float;\n" 109 "precision highp int;\n" 110 "${DECLARATIONS}\n" 111 "void main()\n" 112 "{\n" 113 " const ${CASE_BASE_TYPE} cval = ${CASE_EXPRESSION};\n" 114 " out0 = cval;\n" 115 " ${OUTPUT}\n" 116 "}\n"; 117 118 const tcu::StringTemplate shaderTemplate (shaderTemplateSrc); 119 vector<tcu::TestNode*> ret; 120 121 for (int caseNdx = 0; caseNdx < numCases; caseNdx++) 122 { 123 std::map<string, string> shaderTemplateParams; 124 const int minComponents = cases[caseNdx].minComponents; 125 const int maxComponents = cases[caseNdx].maxComponents; 126 const DataType inType = cases[caseNdx].inType; 127 const DataType outType = cases[caseNdx].outType; 128 const string expression = cases[caseNdx].expression; 129 // Check for presence of func(vec, scalar) style specialization, use as gatekeeper for applying said specialization 130 const bool alwaysScalar = expression.find("${MT}")!=string::npos; 131 132 shaderTemplateParams["GLES_VERSION"] = version == glu::GLSL_VERSION_300_ES ? "300 es" : "100"; 133 shaderTemplateParams["CASE_BASE_TYPE"] = glu::getDataTypeName(outType); 134 shaderTemplateParams["DECLARATIONS"] = "${DECLARATIONS}"; 135 shaderTemplateParams["OUTPUT"] = "${OUTPUT}"; 136 137 for (int compCount = minComponents-1; compCount < maxComponents; compCount++) 138 { 139 vector<tcu::TestNode*> children; 140 std::map<string, string> expressionTemplateParams; 141 string typeName = glu::getDataTypeName((glu::DataType)(inType + compCount)); // results in float, vec2, vec3, vec4 progression (same for other primitive types) 142 const char* componentAccess[] = {"", ".y", ".z", ".w"}; 143 const tcu::StringTemplate expressionTemplate (expression); 144 // Add type to case name if we are generating multiple versions 145 const string caseName = string(cases[caseNdx].name) + (minComponents==maxComponents ? "" : ("_" + typeName)); 146 147 // ${T} => final type, ${MT} => final type but with scalar version usable even when T is a vector 148 expressionTemplateParams["T"] = typeName; 149 expressionTemplateParams["MT"] = typeName; 150 151 shaderTemplateParams["CASE_EXPRESSION"] = expressionTemplate.specialize(expressionTemplateParams) + componentAccess[compCount]; // Add vector access to expression as needed 152 153 { 154 const string mapped = shaderTemplate.specialize(shaderTemplateParams); 155 156 if (testStage & SHADER_VERTEX) 157 { 158 glu::sl::ShaderCaseSpecification spec; 159 160 spec.targetVersion = version; 161 spec.expectResult = glu::sl::EXPECT_PASS; 162 spec.caseType = glu::sl::CASETYPE_VERTEX_ONLY; 163 spec.programs.resize(1); 164 165 spec.programs[0].sources << glu::VertexSource(mapped); 166 167 addOutputVar(&spec.values, outType, cases[caseNdx].output); 168 169 ret.push_back(new ShaderLibraryCase(testContext, 170 renderContext, 171 contextInfo, 172 (caseName + "_vertex").c_str(), 173 "", 174 spec)); 175 } 176 177 if (testStage & SHADER_FRAGMENT) 178 { 179 glu::sl::ShaderCaseSpecification spec; 180 181 spec.targetVersion = version; 182 spec.expectResult = glu::sl::EXPECT_PASS; 183 spec.caseType = glu::sl::CASETYPE_FRAGMENT_ONLY; 184 spec.programs.resize(1); 185 186 spec.programs[0].sources << glu::FragmentSource(mapped); 187 188 addOutputVar(&spec.values, outType, cases[caseNdx].output); 189 190 ret.push_back(new ShaderLibraryCase(testContext, 191 renderContext, 192 contextInfo, 193 (caseName + "_fragment").c_str(), 194 "", 195 spec)); 196 } 197 } 198 199 // Deal with functions that allways accept one ore more scalar parameters even when others are vectors 200 if (alwaysScalar && compCount > 0) 201 { 202 const string scalarCaseName = string(cases[caseNdx].name) + "_" + typeName + "_" + glu::getDataTypeName(inType); 203 204 expressionTemplateParams["MT"] = glu::getDataTypeName(inType); 205 shaderTemplateParams["CASE_EXPRESSION"] = expressionTemplate.specialize(expressionTemplateParams) + componentAccess[compCount]; 206 207 { 208 const string mapped = shaderTemplate.specialize(shaderTemplateParams); 209 210 if (testStage & SHADER_VERTEX) 211 { 212 glu::sl::ShaderCaseSpecification spec; 213 214 spec.targetVersion = version; 215 spec.expectResult = glu::sl::EXPECT_PASS; 216 spec.caseType = glu::sl::CASETYPE_VERTEX_ONLY; 217 spec.programs.resize(1); 218 219 spec.programs[0].sources << glu::VertexSource(mapped); 220 221 addOutputVar(&spec.values, outType, cases[caseNdx].output); 222 223 ret.push_back(new ShaderLibraryCase(testContext, 224 renderContext, 225 contextInfo, 226 (scalarCaseName + "_vertex").c_str(), 227 "", 228 spec)); 229 } 230 231 if (testStage & SHADER_FRAGMENT) 232 { 233 glu::sl::ShaderCaseSpecification spec; 234 235 spec.targetVersion = version; 236 spec.expectResult = glu::sl::EXPECT_PASS; 237 spec.caseType = glu::sl::CASETYPE_FRAGMENT_ONLY; 238 spec.programs.resize(1); 239 240 spec.programs[0].sources << glu::FragmentSource(mapped); 241 242 addOutputVar(&spec.values, outType, cases[caseNdx].output); 243 244 ret.push_back(new ShaderLibraryCase(testContext, 245 renderContext, 246 contextInfo, 247 (scalarCaseName + "_fragment").c_str(), 248 "", 249 spec)); 250 } 251 } 252 } 253 } 254 } 255 256 return ret; 257} 258 259} // ShaderConstExpr 260} // gls 261} // deqp 262