1/*------------------------------------------------------------------------- 2 * drawElements Quality Program Random Shader Generator 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 Shader generator. 22 *//*--------------------------------------------------------------------*/ 23 24#include "rsgShaderGenerator.hpp" 25#include "rsgFunctionGenerator.hpp" 26#include "rsgToken.hpp" 27#include "rsgPrettyPrinter.hpp" 28#include "rsgUtils.hpp" 29#include "deString.h" 30 31#include <iterator> 32 33using std::string; 34using std::vector; 35 36namespace rsg 37{ 38 39ShaderGenerator::ShaderGenerator (GeneratorState& state) 40 : m_state (state) 41 , m_varManager (state.getNameAllocator()) 42{ 43 state.setVariableManager(m_varManager); 44} 45 46ShaderGenerator::~ShaderGenerator (void) 47{ 48} 49 50namespace 51{ 52 53const char* getFragColorName (const GeneratorState& state) 54{ 55 switch (state.getProgramParameters().version) 56 { 57 case VERSION_100: return "gl_FragColor"; 58 case VERSION_300: return "dEQP_FragColor"; 59 default: 60 DE_ASSERT(DE_FALSE); 61 return DE_NULL; 62 } 63} 64 65void createAssignment (BlockStatement& block, const Variable* dstVar, const Variable* srcVar) 66{ 67 VariableRead* varRead = new VariableRead(srcVar); 68 try 69 { 70 block.addChild(new AssignStatement( dstVar, varRead)); 71 } 72 catch (const std::exception&) 73 { 74 delete varRead; 75 throw; 76 } 77} 78 79const ValueEntry* findByName (VariableManager& varManager, const char* name) 80{ 81 AnyEntry::Iterator iter = varManager.getBegin<AnyEntry>(); 82 AnyEntry::Iterator end = varManager.getEnd<AnyEntry>(); 83 for (; iter != end; iter++) 84 { 85 const ValueEntry* entry = *iter; 86 if (deStringEqual(entry->getVariable()->getName(), name)) 87 return entry; 88 } 89 return DE_NULL; 90} 91 92void genVertexPassthrough (GeneratorState& state, Shader& shader) 93{ 94 // Create copies from shader inputs to outputs 95 vector<const ValueEntry*> entries; 96 std::copy(state.getVariableManager().getBegin<AnyEntry>(), state.getVariableManager().getEnd<AnyEntry>(), std::inserter(entries, entries.begin())); 97 98 for (vector<const ValueEntry*>::const_iterator i = entries.begin(); i != entries.end(); i++) 99 { 100 const ValueEntry* entry = *i; 101 const Variable* outVar = entry->getVariable(); 102 std::string inVarName; 103 104 if (outVar->getStorage() != Variable::STORAGE_SHADER_OUT) 105 continue; 106 107 // Name: a_[name], remove v_ -prefix if such exists 108 inVarName = "a_"; 109 if (deStringBeginsWith(outVar->getName(), "v_")) 110 inVarName += (outVar->getName()+2); 111 else 112 inVarName += outVar->getName(); 113 114 Variable* inVar = state.getVariableManager().allocate(outVar->getType(), Variable::STORAGE_SHADER_IN, inVarName.c_str()); 115 116 // Update value range. This will be stored into shader input info. 117 state.getVariableManager().setValue(inVar, entry->getValueRange()); 118 119 // Add assignment from input to output into main() body 120 createAssignment(shader.getMain().getBody(), entry->getVariable(), inVar); 121 } 122} 123 124void genFragmentPassthrough (GeneratorState& state, Shader& shader) 125{ 126 // Add simple gl_FragColor = v_color; assignment 127 const ValueEntry* fragColorEntry = findByName(state.getVariableManager(), getFragColorName(state)); 128 TCU_CHECK(fragColorEntry); 129 130 Variable* inColorVariable = state.getVariableManager().allocate(fragColorEntry->getVariable()->getType(), Variable::STORAGE_SHADER_IN, "v_color"); 131 132 state.getVariableManager().setValue(inColorVariable, fragColorEntry->getValueRange()); 133 createAssignment(shader.getMain().getBody(), fragColorEntry->getVariable(), inColorVariable); 134} 135 136// Sets undefined (-inf..inf) components to some meaningful values. Used for sanitizing final shader input value ranges. 137void fillUndefinedComponents (ValueRangeAccess valueRange) 138{ 139 VariableType::Type baseType = valueRange.getType().getBaseType(); 140 TCU_CHECK(baseType == VariableType::TYPE_FLOAT || 141 baseType == VariableType::TYPE_INT || 142 baseType == VariableType::TYPE_BOOL); 143 144 for (int elemNdx = 0; elemNdx < valueRange.getType().getNumElements(); elemNdx++) 145 { 146 if (isUndefinedValueRange(valueRange.component(elemNdx))) 147 { 148 ValueAccess min = valueRange.component(elemNdx).getMin(); 149 ValueAccess max = valueRange.component(elemNdx).getMax(); 150 151 switch (baseType) 152 { 153 case VariableType::TYPE_FLOAT: min = 0.0f; max = 1.0f; break; 154 case VariableType::TYPE_INT: min = 0; max = 1; break; 155 case VariableType::TYPE_BOOL: min = false; max = true; break; 156 default: DE_ASSERT(DE_FALSE); 157 } 158 } 159 } 160} 161 162void fillUndefinedShaderInputs (vector<ShaderInput*>& inputs) 163{ 164 for (vector<ShaderInput*>::iterator i = inputs.begin(); i != inputs.end(); i++) 165 { 166 if (!(*i)->getVariable()->getType().isSampler()) // Samplers are assigned at program-level. 167 fillUndefinedComponents((*i)->getValueRange()); 168 } 169} 170 171} // anonymous 172 173void ShaderGenerator::generate (const ShaderParameters& shaderParams, Shader& shader, const vector<ShaderInput*>& outputs) 174{ 175 // Global scopes 176 VariableScope& globalVariableScope = shader.getGlobalScope(); 177 ValueScope globalValueScope; 178 179 // Init state 180 m_state.setShader(shaderParams, shader); 181 DE_ASSERT(m_state.getExpressionFlags() == 0); 182 183 // Reserve some scalars for gl_Position & dEQP_Position 184 ReservedScalars reservedScalars; 185 if (shader.getType() == Shader::TYPE_VERTEX) 186 m_state.getVariableManager().reserve(reservedScalars, 4*2); 187 188 // Push global scopes 189 m_varManager.pushVariableScope(globalVariableScope); 190 m_varManager.pushValueScope(globalValueScope); 191 192 // Init shader outputs. 193 { 194 for (vector<ShaderInput*>::const_iterator i = outputs.begin(); i != outputs.end(); i++) 195 { 196 const ShaderInput* input = *i; 197 Variable* variable = m_state.getVariableManager().allocate(input->getVariable()->getType(), Variable::STORAGE_SHADER_OUT, input->getVariable()->getName()); 198 199 m_state.getVariableManager().setValue(variable, input->getValueRange()); 200 } 201 202 if (shader.getType() == Shader::TYPE_FRAGMENT) 203 { 204 // gl_FragColor 205 // \todo [2011-11-22 pyry] Multiple outputs from fragment shader! 206 Variable* fragColorVar = m_state.getVariableManager().allocate(VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_OUT, getFragColorName(m_state)); 207 ValueRange valueRange(fragColorVar->getType()); 208 209 valueRange.getMin() = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); 210 valueRange.getMax() = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); 211 212 fragColorVar->setLayoutLocation(0); // Bind color output to location 0 (applies to GLSL ES 3.0 onwards). 213 214 m_state.getVariableManager().setValue(fragColorVar, valueRange.asAccess()); 215 } 216 } 217 218 // Construct shader code. 219 { 220 Function& main = shader.getMain(); 221 main.setReturnType(VariableType(VariableType::TYPE_VOID)); 222 223 if (shaderParams.randomize) 224 { 225 FunctionGenerator funcGen(m_state, main); 226 227 // Mandate assignment into to all shader outputs in main() 228 const vector<Variable*>& liveVars = globalVariableScope.getLiveVariables(); 229 for (vector<Variable*>::const_iterator i = liveVars.begin(); i != liveVars.end(); i++) 230 { 231 Variable* variable = *i; 232 if (variable->getStorage() == Variable::STORAGE_SHADER_OUT) 233 funcGen.requireAssignment(variable); 234 } 235 236 funcGen.generate(); 237 } 238 else 239 { 240 if (shader.getType() == Shader::TYPE_VERTEX) 241 genVertexPassthrough(m_state, shader); 242 else 243 { 244 DE_ASSERT(shader.getType() == Shader::TYPE_FRAGMENT); 245 genFragmentPassthrough(m_state, shader); 246 } 247 } 248 249 if (shader.getType() == Shader::TYPE_VERTEX) 250 { 251 // Add gl_Position = dEQP_Position; 252 m_state.getVariableManager().release(reservedScalars); 253 254 Variable* glPosVariable = m_state.getVariableManager().allocate(VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_OUT, "gl_Position"); 255 Variable* qpPosVariable = m_state.getVariableManager().allocate(VariableType(VariableType::TYPE_FLOAT, 4), Variable::STORAGE_SHADER_IN, "dEQP_Position"); 256 257 ValueRange valueRange(glPosVariable->getType()); 258 259 valueRange.getMin() = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f); 260 valueRange.getMax() = tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f); 261 262 m_state.getVariableManager().setValue(qpPosVariable, valueRange.asAccess()); // \todo [2011-05-24 pyry] No expression should be able to use gl_Position or dEQP_Position.. 263 264 createAssignment(main.getBody(), glPosVariable, qpPosVariable); 265 } 266 } 267 268 // Declare live global variables. 269 { 270 vector<Variable*> liveVariables; 271 std::copy(globalVariableScope.getLiveVariables().begin(), globalVariableScope.getLiveVariables().end(), std::inserter(liveVariables, liveVariables.begin())); 272 273 vector<Variable*> createDeclarationStatementVars; 274 275 for (vector<Variable*>::iterator i = liveVariables.begin(); i != liveVariables.end(); i++) 276 { 277 Variable* variable = *i; 278 const char* name = variable->getName(); 279 bool declare = !deStringBeginsWith(name, "gl_"); // Do not declare built-in types. 280 281 // Create input entries (store value range) if necessary 282 vector<ShaderInput*>& inputs = shader.getInputs(); 283 vector<ShaderInput*>& uniforms = shader.getUniforms(); 284 285 switch (variable->getStorage()) 286 { 287 case Variable::STORAGE_SHADER_IN: 288 { 289 const ValueEntry* value = m_state.getVariableManager().getValue(variable); 290 291 inputs.reserve(inputs.size()+1); 292 inputs.push_back(new ShaderInput(variable, value->getValueRange())); 293 break; 294 } 295 296 case Variable::STORAGE_UNIFORM: 297 { 298 const ValueEntry* value = m_state.getVariableManager().getValue(variable); 299 300 uniforms.reserve(uniforms.size()+1); 301 uniforms.push_back(new ShaderInput(variable, value->getValueRange())); 302 break; 303 } 304 305 default: 306 break; 307 } 308 309 if (declare) 310 createDeclarationStatementVars.push_back(variable); 311 else 312 { 313 // Just move to global scope without declaration statement. 314 m_state.getVariableManager().declareVariable(variable); 315 } 316 } 317 318 // All global initializers must be constant expressions, no variable allocation is allowed 319 DE_ASSERT(m_state.getExpressionFlags() == 0); 320 m_state.pushExpressionFlags(CONST_EXPR|NO_VAR_ALLOCATION); 321 322 // Create declaration statements 323 for (vector<Variable*>::iterator i = createDeclarationStatementVars.begin(); i != createDeclarationStatementVars.end(); i++) 324 { 325 shader.getGlobalStatements().reserve(shader.getGlobalStatements().size()); 326 shader.getGlobalStatements().push_back(new DeclarationStatement(m_state, *i)); 327 } 328 329 m_state.popExpressionFlags(); 330 } 331 332 // Pop global scopes 333 m_varManager.popVariableScope(); 334 m_varManager.popValueScope(); 335 336 // Fill undefined (unused) components in inputs with dummy values 337 fillUndefinedShaderInputs(shader.getInputs()); 338 fillUndefinedShaderInputs(shader.getUniforms()); 339 340 // Tokenize shader and write source 341 { 342 TokenStream tokenStr; 343 shader.tokenize(m_state, tokenStr); 344 345 std::ostringstream str; 346 PrettyPrinter printer(str); 347 348 // Append #version if necessary. 349 if (m_state.getProgramParameters().version == VERSION_300) 350 str << "#version 300 es\n"; 351 352 printer.append(tokenStr); 353 shader.setSource(str.str().c_str()); 354 } 355} 356 357} // rsg 358