1 // 2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // 8 // Implement the top-level of interface to the compiler, 9 // as defined in ShaderLang.h 10 // 11 12 #include "GLSLANG/ShaderLang.h" 13 14 #include "compiler/translator/Compiler.h" 15 #include "compiler/translator/InitializeDll.h" 16 #include "compiler/translator/length_limits.h" 17 #include "compiler/translator/TranslatorHLSL.h" 18 #include "compiler/translator/VariablePacker.h" 19 #include "angle_gl.h" 20 21 namespace 22 { 23 24 enum ShaderVariableType 25 { 26 SHADERVAR_UNIFORM, 27 SHADERVAR_VARYING, 28 SHADERVAR_ATTRIBUTE, 29 SHADERVAR_OUTPUTVARIABLE, 30 SHADERVAR_INTERFACEBLOCK 31 }; 32 33 bool isInitialized = false; 34 35 // 36 // This is the platform independent interface between an OGL driver 37 // and the shading language compiler. 38 // 39 40 static bool CheckVariableMaxLengths(const ShHandle handle, 41 size_t expectedValue) 42 { 43 size_t activeUniformLimit = 0; 44 ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); 45 size_t activeAttribLimit = 0; 46 ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); 47 size_t varyingLimit = 0; 48 ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit); 49 return (expectedValue == activeUniformLimit && 50 expectedValue == activeAttribLimit && 51 expectedValue == varyingLimit); 52 } 53 54 bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue) 55 { 56 size_t mappedNameMaxLength = 0; 57 ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); 58 return (expectedValue == mappedNameMaxLength); 59 } 60 61 template <typename VarT> 62 const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoList, int index) 63 { 64 if (index < 0 || static_cast<size_t>(index) >= infoList.size()) 65 { 66 return NULL; 67 } 68 69 return &infoList[index]; 70 } 71 72 const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) 73 { 74 switch (varType) 75 { 76 case SH_ACTIVE_ATTRIBUTES: 77 return ReturnVariable(compiler->getAttributes(), index); 78 case SH_ACTIVE_UNIFORMS: 79 return ReturnVariable(compiler->getExpandedUniforms(), index); 80 case SH_VARYINGS: 81 return ReturnVariable(compiler->getExpandedVaryings(), index); 82 default: 83 UNREACHABLE(); 84 return NULL; 85 } 86 } 87 88 ShPrecisionType ConvertPrecision(sh::GLenum precision) 89 { 90 switch (precision) 91 { 92 case GL_HIGH_FLOAT: 93 case GL_HIGH_INT: 94 return SH_PRECISION_HIGHP; 95 case GL_MEDIUM_FLOAT: 96 case GL_MEDIUM_INT: 97 return SH_PRECISION_MEDIUMP; 98 case GL_LOW_FLOAT: 99 case GL_LOW_INT: 100 return SH_PRECISION_LOWP; 101 default: 102 return SH_PRECISION_UNDEFINED; 103 } 104 } 105 106 template <typename VarT> 107 const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType); 108 109 template <> 110 const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler, ShaderVariableType) 111 { 112 return &compiler->getUniforms(); 113 } 114 115 template <> 116 const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler, ShaderVariableType) 117 { 118 return &compiler->getVaryings(); 119 } 120 121 template <> 122 const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType) 123 { 124 return (variableType == SHADERVAR_ATTRIBUTE ? 125 &compiler->getAttributes() : 126 &compiler->getOutputVariables()); 127 } 128 129 template <> 130 const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler, ShaderVariableType) 131 { 132 return &compiler->getInterfaceBlocks(); 133 } 134 135 template <typename VarT> 136 const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariableType variableType) 137 { 138 if (!handle) 139 { 140 return NULL; 141 } 142 143 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 144 TCompiler* compiler = base->getAsCompiler(); 145 if (!compiler) 146 { 147 return NULL; 148 } 149 150 return GetVariableList<VarT>(compiler, variableType); 151 } 152 153 } 154 155 // 156 // Driver must call this first, once, before doing any other compiler operations. 157 // Subsequent calls to this function are no-op. 158 // 159 int ShInitialize() 160 { 161 if (!isInitialized) 162 { 163 isInitialized = InitProcess(); 164 } 165 return isInitialized ? 1 : 0; 166 } 167 168 // 169 // Cleanup symbol tables 170 // 171 int ShFinalize() 172 { 173 if (isInitialized) 174 { 175 DetachProcess(); 176 isInitialized = false; 177 } 178 return 1; 179 } 180 181 // 182 // Initialize built-in resources with minimum expected values. 183 // 184 void ShInitBuiltInResources(ShBuiltInResources* resources) 185 { 186 // Constants. 187 resources->MaxVertexAttribs = 8; 188 resources->MaxVertexUniformVectors = 128; 189 resources->MaxVaryingVectors = 8; 190 resources->MaxVertexTextureImageUnits = 0; 191 resources->MaxCombinedTextureImageUnits = 8; 192 resources->MaxTextureImageUnits = 8; 193 resources->MaxFragmentUniformVectors = 16; 194 resources->MaxDrawBuffers = 1; 195 196 // Extensions. 197 resources->OES_standard_derivatives = 0; 198 resources->OES_EGL_image_external = 0; 199 resources->ARB_texture_rectangle = 0; 200 resources->EXT_draw_buffers = 0; 201 resources->EXT_frag_depth = 0; 202 resources->EXT_shader_texture_lod = 0; 203 204 // Disable highp precision in fragment shader by default. 205 resources->FragmentPrecisionHigh = 0; 206 207 // GLSL ES 3.0 constants. 208 resources->MaxVertexOutputVectors = 16; 209 resources->MaxFragmentInputVectors = 15; 210 resources->MinProgramTexelOffset = -8; 211 resources->MaxProgramTexelOffset = 7; 212 213 // Disable name hashing by default. 214 resources->HashFunction = NULL; 215 216 resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; 217 218 resources->MaxExpressionComplexity = 256; 219 resources->MaxCallStackDepth = 256; 220 } 221 222 // 223 // Driver calls these to create and destroy compiler objects. 224 // 225 ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec, 226 ShShaderOutput output, 227 const ShBuiltInResources* resources) 228 { 229 TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output)); 230 TCompiler* compiler = base->getAsCompiler(); 231 if (compiler == 0) 232 return 0; 233 234 // Generate built-in symbol table. 235 if (!compiler->Init(*resources)) { 236 ShDestruct(base); 237 return 0; 238 } 239 240 return reinterpret_cast<void*>(base); 241 } 242 243 void ShDestruct(ShHandle handle) 244 { 245 if (handle == 0) 246 return; 247 248 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 249 250 if (base->getAsCompiler()) 251 DeleteCompiler(base->getAsCompiler()); 252 } 253 254 void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outString) 255 { 256 if (!handle || !outString) 257 { 258 return; 259 } 260 261 TShHandleBase *base = static_cast<TShHandleBase*>(handle); 262 TCompiler *compiler = base->getAsCompiler(); 263 if (!compiler) 264 { 265 return; 266 } 267 268 strncpy(outString, compiler->getBuiltInResourcesString().c_str(), outStringLen); 269 outString[outStringLen - 1] = '\0'; 270 } 271 // 272 // Do an actual compile on the given strings. The result is left 273 // in the given compile object. 274 // 275 // Return: The return value of ShCompile is really boolean, indicating 276 // success or failure. 277 // 278 int ShCompile( 279 const ShHandle handle, 280 const char* const shaderStrings[], 281 size_t numStrings, 282 int compileOptions) 283 { 284 if (handle == 0) 285 return 0; 286 287 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); 288 TCompiler* compiler = base->getAsCompiler(); 289 if (compiler == 0) 290 return 0; 291 292 bool success = compiler->compile(shaderStrings, numStrings, compileOptions); 293 return success ? 1 : 0; 294 } 295 296 void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) 297 { 298 if (!handle || !params) 299 return; 300 301 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 302 TCompiler* compiler = base->getAsCompiler(); 303 if (!compiler) return; 304 305 switch(pname) 306 { 307 case SH_INFO_LOG_LENGTH: 308 *params = compiler->getInfoSink().info.size() + 1; 309 break; 310 case SH_OBJECT_CODE_LENGTH: 311 *params = compiler->getInfoSink().obj.size() + 1; 312 break; 313 case SH_ACTIVE_UNIFORMS: 314 *params = compiler->getExpandedUniforms().size(); 315 break; 316 case SH_ACTIVE_UNIFORM_MAX_LENGTH: 317 *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); 318 break; 319 case SH_ACTIVE_ATTRIBUTES: 320 *params = compiler->getAttributes().size(); 321 break; 322 case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: 323 *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); 324 break; 325 case SH_VARYINGS: 326 *params = compiler->getExpandedVaryings().size(); 327 break; 328 case SH_VARYING_MAX_LENGTH: 329 *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); 330 break; 331 case SH_MAPPED_NAME_MAX_LENGTH: 332 // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to 333 // handle array and struct dereferences. 334 *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); 335 break; 336 case SH_NAME_MAX_LENGTH: 337 *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); 338 break; 339 case SH_HASHED_NAME_MAX_LENGTH: 340 if (compiler->getHashFunction() == NULL) { 341 *params = 0; 342 } else { 343 // 64 bits hashing output requires 16 bytes for hex 344 // representation. 345 const char HashedNamePrefix[] = HASHED_NAME_PREFIX; 346 (void)HashedNamePrefix; 347 *params = 16 + sizeof(HashedNamePrefix); 348 } 349 break; 350 case SH_HASHED_NAMES_COUNT: 351 *params = compiler->getNameMap().size(); 352 break; 353 case SH_SHADER_VERSION: 354 *params = compiler->getShaderVersion(); 355 break; 356 case SH_RESOURCES_STRING_LENGTH: 357 *params = compiler->getBuiltInResourcesString().length() + 1; 358 break; 359 case SH_OUTPUT_TYPE: 360 *params = compiler->getOutputType(); 361 break; 362 default: UNREACHABLE(); 363 } 364 } 365 366 // 367 // Return any compiler log of messages for the application. 368 // 369 void ShGetInfoLog(const ShHandle handle, char* infoLog) 370 { 371 if (!handle || !infoLog) 372 return; 373 374 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 375 TCompiler* compiler = base->getAsCompiler(); 376 if (!compiler) return; 377 378 TInfoSink& infoSink = compiler->getInfoSink(); 379 strcpy(infoLog, infoSink.info.c_str()); 380 } 381 382 // 383 // Return any object code. 384 // 385 void ShGetObjectCode(const ShHandle handle, char* objCode) 386 { 387 if (!handle || !objCode) 388 return; 389 390 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 391 TCompiler* compiler = base->getAsCompiler(); 392 if (!compiler) return; 393 394 TInfoSink& infoSink = compiler->getInfoSink(); 395 strcpy(objCode, infoSink.obj.c_str()); 396 } 397 398 void ShGetVariableInfo(const ShHandle handle, 399 ShShaderInfo varType, 400 int index, 401 size_t* length, 402 int* size, 403 sh::GLenum* type, 404 ShPrecisionType* precision, 405 int* staticUse, 406 char* name, 407 char* mappedName) 408 { 409 if (!handle || !size || !type || !precision || !staticUse || !name) 410 return; 411 ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || 412 (varType == SH_ACTIVE_UNIFORMS) || 413 (varType == SH_VARYINGS)); 414 415 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); 416 TCompiler* compiler = base->getAsCompiler(); 417 if (compiler == 0) 418 return; 419 420 const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index); 421 if (!varInfo) 422 { 423 return; 424 } 425 426 if (length) *length = varInfo->name.size(); 427 *size = varInfo->elementCount(); 428 *type = varInfo->type; 429 *precision = ConvertPrecision(varInfo->precision); 430 *staticUse = varInfo->staticUse ? 1 : 0; 431 432 // This size must match that queried by 433 // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH 434 // in ShGetInfo, below. 435 size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); 436 ASSERT(CheckVariableMaxLengths(handle, variableLength)); 437 strncpy(name, varInfo->name.c_str(), variableLength); 438 name[variableLength - 1] = 0; 439 if (mappedName) 440 { 441 // This size must match that queried by 442 // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. 443 size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); 444 ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength)); 445 strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength); 446 mappedName[maxMappedNameLength - 1] = 0; 447 } 448 } 449 450 void ShGetNameHashingEntry(const ShHandle handle, 451 int index, 452 char* name, 453 char* hashedName) 454 { 455 if (!handle || !name || !hashedName || index < 0) 456 return; 457 458 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 459 TCompiler* compiler = base->getAsCompiler(); 460 if (!compiler) return; 461 462 const NameMap& nameMap = compiler->getNameMap(); 463 if (index >= static_cast<int>(nameMap.size())) 464 return; 465 466 NameMap::const_iterator it = nameMap.begin(); 467 for (int i = 0; i < index; ++i) 468 ++it; 469 470 size_t len = it->first.length() + 1; 471 size_t max_len = 0; 472 ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len); 473 if (len > max_len) { 474 ASSERT(false); 475 len = max_len; 476 } 477 strncpy(name, it->first.c_str(), len); 478 // To be on the safe side in case the source is longer than expected. 479 name[len - 1] = '\0'; 480 481 len = it->second.length() + 1; 482 max_len = 0; 483 ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len); 484 if (len > max_len) { 485 ASSERT(false); 486 len = max_len; 487 } 488 strncpy(hashedName, it->second.c_str(), len); 489 // To be on the safe side in case the source is longer than expected. 490 hashedName[len - 1] = '\0'; 491 } 492 493 const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle) 494 { 495 return GetShaderVariables<sh::Uniform>(handle, SHADERVAR_UNIFORM); 496 } 497 498 const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle) 499 { 500 return GetShaderVariables<sh::Varying>(handle, SHADERVAR_VARYING); 501 } 502 503 const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle) 504 { 505 return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_ATTRIBUTE); 506 } 507 508 const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle) 509 { 510 return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_OUTPUTVARIABLE); 511 } 512 513 const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle) 514 { 515 return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK); 516 } 517 518 int ShCheckVariablesWithinPackingLimits( 519 int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize) 520 { 521 if (varInfoArraySize == 0) 522 return 1; 523 ASSERT(varInfoArray); 524 std::vector<sh::ShaderVariable> variables; 525 for (size_t ii = 0; ii < varInfoArraySize; ++ii) 526 { 527 sh::ShaderVariable var(varInfoArray[ii].type, varInfoArray[ii].size); 528 variables.push_back(var); 529 } 530 VariablePacker packer; 531 return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; 532 } 533 534 bool ShGetInterfaceBlockRegister(const ShHandle handle, 535 const char *interfaceBlockName, 536 unsigned int *indexOut) 537 { 538 if (!handle || !interfaceBlockName || !indexOut) 539 { 540 return false; 541 } 542 543 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 544 TranslatorHLSL* translator = base->getAsTranslatorHLSL(); 545 if (!translator) 546 { 547 return false; 548 } 549 550 if (!translator->hasInterfaceBlock(interfaceBlockName)) 551 { 552 return false; 553 } 554 555 *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName); 556 return true; 557 } 558 559 bool ShGetUniformRegister(const ShHandle handle, 560 const char *uniformName, 561 unsigned int *indexOut) 562 { 563 if (!handle || !uniformName || !indexOut) 564 { 565 return false; 566 } 567 568 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 569 TranslatorHLSL* translator = base->getAsTranslatorHLSL(); 570 if (!translator) 571 { 572 return false; 573 } 574 575 if (!translator->hasUniform(uniformName)) 576 { 577 return false; 578 } 579 580 *indexOut = translator->getUniformRegister(uniformName); 581 return true; 582 } 583