1 // 2 // Copyright (c) 2002-2012 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/InitializeDll.h" 15 #include "compiler/preprocessor/length_limits.h" 16 #include "compiler/ShHandle.h" 17 #include "compiler/TranslatorHLSL.h" 18 #include "compiler/VariablePacker.h" 19 20 // 21 // This is the platform independent interface between an OGL driver 22 // and the shading language compiler. 23 // 24 25 static bool checkVariableMaxLengths(const ShHandle handle, 26 size_t expectedValue) 27 { 28 size_t activeUniformLimit = 0; 29 ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); 30 size_t activeAttribLimit = 0; 31 ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); 32 size_t varyingLimit = 0; 33 ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit); 34 return (expectedValue == activeUniformLimit && 35 expectedValue == activeAttribLimit && 36 expectedValue == varyingLimit); 37 } 38 39 static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) 40 { 41 size_t mappedNameMaxLength = 0; 42 ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); 43 return (expectedValue == mappedNameMaxLength); 44 } 45 46 // 47 // Driver must call this first, once, before doing any other compiler operations. 48 // Subsequent calls to this function are no-op. 49 // 50 int ShInitialize() 51 { 52 static const bool kInitialized = InitProcess(); 53 return kInitialized ? 1 : 0; 54 } 55 56 // 57 // Cleanup symbol tables 58 // 59 int ShFinalize() 60 { 61 DetachProcess(); 62 return 1; 63 } 64 65 // 66 // Initialize built-in resources with minimum expected values. 67 // 68 void ShInitBuiltInResources(ShBuiltInResources* resources) 69 { 70 // Constants. 71 resources->MaxVertexAttribs = 8; 72 resources->MaxVertexUniformVectors = 128; 73 resources->MaxVaryingVectors = 8; 74 resources->MaxVertexTextureImageUnits = 0; 75 resources->MaxCombinedTextureImageUnits = 8; 76 resources->MaxTextureImageUnits = 8; 77 resources->MaxFragmentUniformVectors = 16; 78 resources->MaxDrawBuffers = 1; 79 80 // Extensions. 81 resources->OES_standard_derivatives = 0; 82 resources->OES_EGL_image_external = 0; 83 resources->ARB_texture_rectangle = 0; 84 resources->EXT_draw_buffers = 0; 85 resources->EXT_frag_depth = 0; 86 87 // Disable highp precision in fragment shader by default. 88 resources->FragmentPrecisionHigh = 0; 89 90 // Disable name hashing by default. 91 resources->HashFunction = NULL; 92 93 resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; 94 } 95 96 // 97 // Driver calls these to create and destroy compiler objects. 98 // 99 ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, 100 ShShaderOutput output, 101 const ShBuiltInResources* resources) 102 { 103 TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output)); 104 TCompiler* compiler = base->getAsCompiler(); 105 if (compiler == 0) 106 return 0; 107 108 // Generate built-in symbol table. 109 if (!compiler->Init(*resources)) { 110 ShDestruct(base); 111 return 0; 112 } 113 114 return reinterpret_cast<void*>(base); 115 } 116 117 void ShDestruct(ShHandle handle) 118 { 119 if (handle == 0) 120 return; 121 122 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 123 124 if (base->getAsCompiler()) 125 DeleteCompiler(base->getAsCompiler()); 126 } 127 128 // 129 // Do an actual compile on the given strings. The result is left 130 // in the given compile object. 131 // 132 // Return: The return value of ShCompile is really boolean, indicating 133 // success or failure. 134 // 135 int ShCompile( 136 const ShHandle handle, 137 const char* const shaderStrings[], 138 size_t numStrings, 139 int compileOptions) 140 { 141 if (handle == 0) 142 return 0; 143 144 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); 145 TCompiler* compiler = base->getAsCompiler(); 146 if (compiler == 0) 147 return 0; 148 149 bool success = compiler->compile(shaderStrings, numStrings, compileOptions); 150 return success ? 1 : 0; 151 } 152 153 void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) 154 { 155 if (!handle || !params) 156 return; 157 158 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 159 TCompiler* compiler = base->getAsCompiler(); 160 if (!compiler) return; 161 162 switch(pname) 163 { 164 case SH_INFO_LOG_LENGTH: 165 *params = compiler->getInfoSink().info.size() + 1; 166 break; 167 case SH_OBJECT_CODE_LENGTH: 168 *params = compiler->getInfoSink().obj.size() + 1; 169 break; 170 case SH_ACTIVE_UNIFORMS: 171 *params = compiler->getUniforms().size(); 172 break; 173 case SH_ACTIVE_UNIFORM_MAX_LENGTH: 174 *params = 1 + MAX_SYMBOL_NAME_LEN; 175 break; 176 case SH_ACTIVE_ATTRIBUTES: 177 *params = compiler->getAttribs().size(); 178 break; 179 case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: 180 *params = 1 + MAX_SYMBOL_NAME_LEN; 181 break; 182 case SH_VARYINGS: 183 *params = compiler->getVaryings().size(); 184 break; 185 case SH_VARYING_MAX_LENGTH: 186 *params = 1 + MAX_SYMBOL_NAME_LEN; 187 break; 188 case SH_MAPPED_NAME_MAX_LENGTH: 189 // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to 190 // handle array and struct dereferences. 191 *params = 1 + MAX_SYMBOL_NAME_LEN; 192 break; 193 case SH_NAME_MAX_LENGTH: 194 *params = 1 + MAX_SYMBOL_NAME_LEN; 195 break; 196 case SH_HASHED_NAME_MAX_LENGTH: 197 if (compiler->getHashFunction() == NULL) { 198 *params = 0; 199 } else { 200 // 64 bits hashing output requires 16 bytes for hex 201 // representation. 202 const char HashedNamePrefix[] = HASHED_NAME_PREFIX; 203 *params = 16 + sizeof(HashedNamePrefix); 204 } 205 break; 206 case SH_HASHED_NAMES_COUNT: 207 *params = compiler->getNameMap().size(); 208 break; 209 default: UNREACHABLE(); 210 } 211 } 212 213 // 214 // Return any compiler log of messages for the application. 215 // 216 void ShGetInfoLog(const ShHandle handle, char* infoLog) 217 { 218 if (!handle || !infoLog) 219 return; 220 221 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 222 TCompiler* compiler = base->getAsCompiler(); 223 if (!compiler) return; 224 225 TInfoSink& infoSink = compiler->getInfoSink(); 226 strcpy(infoLog, infoSink.info.c_str()); 227 } 228 229 // 230 // Return any object code. 231 // 232 void ShGetObjectCode(const ShHandle handle, char* objCode) 233 { 234 if (!handle || !objCode) 235 return; 236 237 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 238 TCompiler* compiler = base->getAsCompiler(); 239 if (!compiler) return; 240 241 TInfoSink& infoSink = compiler->getInfoSink(); 242 strcpy(objCode, infoSink.obj.c_str()); 243 } 244 245 void ShGetVariableInfo(const ShHandle handle, 246 ShShaderInfo varType, 247 int index, 248 size_t* length, 249 int* size, 250 ShDataType* type, 251 ShPrecisionType* precision, 252 int* staticUse, 253 char* name, 254 char* mappedName) 255 { 256 if (!handle || !size || !type || !precision || !staticUse || !name) 257 return; 258 ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || 259 (varType == SH_ACTIVE_UNIFORMS) || 260 (varType == SH_VARYINGS)); 261 262 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); 263 TCompiler* compiler = base->getAsCompiler(); 264 if (compiler == 0) 265 return; 266 267 const TVariableInfoList& varList = 268 varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : 269 (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() : 270 compiler->getVaryings()); 271 if (index < 0 || index >= static_cast<int>(varList.size())) 272 return; 273 274 const TVariableInfo& varInfo = varList[index]; 275 if (length) *length = varInfo.name.size(); 276 *size = varInfo.size; 277 *type = varInfo.type; 278 switch (varInfo.precision) { 279 case EbpLow: 280 *precision = SH_PRECISION_LOWP; 281 break; 282 case EbpMedium: 283 *precision = SH_PRECISION_MEDIUMP; 284 break; 285 case EbpHigh: 286 *precision = SH_PRECISION_HIGHP; 287 break; 288 default: 289 // Some types does not support precision, for example, boolean. 290 *precision = SH_PRECISION_UNDEFINED; 291 break; 292 } 293 *staticUse = varInfo.staticUse ? 1 : 0; 294 295 // This size must match that queried by 296 // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH 297 // in ShGetInfo, below. 298 size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN; 299 ASSERT(checkVariableMaxLengths(handle, variableLength)); 300 strncpy(name, varInfo.name.c_str(), variableLength); 301 name[variableLength - 1] = 0; 302 if (mappedName) { 303 // This size must match that queried by 304 // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. 305 size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; 306 ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); 307 strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); 308 mappedName[maxMappedNameLength - 1] = 0; 309 } 310 } 311 312 void ShGetNameHashingEntry(const ShHandle handle, 313 int index, 314 char* name, 315 char* hashedName) 316 { 317 if (!handle || !name || !hashedName || index < 0) 318 return; 319 320 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 321 TCompiler* compiler = base->getAsCompiler(); 322 if (!compiler) return; 323 324 const NameMap& nameMap = compiler->getNameMap(); 325 if (index >= static_cast<int>(nameMap.size())) 326 return; 327 328 NameMap::const_iterator it = nameMap.begin(); 329 for (int i = 0; i < index; ++i) 330 ++it; 331 332 size_t len = it->first.length() + 1; 333 size_t max_len = 0; 334 ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len); 335 if (len > max_len) { 336 ASSERT(false); 337 len = max_len; 338 } 339 strncpy(name, it->first.c_str(), len); 340 // To be on the safe side in case the source is longer than expected. 341 name[len - 1] = '\0'; 342 343 len = it->second.length() + 1; 344 max_len = 0; 345 ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len); 346 if (len > max_len) { 347 ASSERT(false); 348 len = max_len; 349 } 350 strncpy(hashedName, it->second.c_str(), len); 351 // To be on the safe side in case the source is longer than expected. 352 hashedName[len - 1] = '\0'; 353 } 354 355 void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) 356 { 357 if (!handle || !params) 358 return; 359 360 TShHandleBase* base = static_cast<TShHandleBase*>(handle); 361 TranslatorHLSL* translator = base->getAsTranslatorHLSL(); 362 if (!translator) return; 363 364 switch(pname) 365 { 366 case SH_ACTIVE_UNIFORMS_ARRAY: 367 *params = (void*)&translator->getUniforms(); 368 break; 369 default: UNREACHABLE(); 370 } 371 } 372 373 int ShCheckVariablesWithinPackingLimits( 374 int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize) 375 { 376 if (varInfoArraySize == 0) 377 return 1; 378 ASSERT(varInfoArray); 379 TVariableInfoList variables; 380 for (size_t ii = 0; ii < varInfoArraySize; ++ii) 381 { 382 TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size); 383 variables.push_back(var); 384 } 385 VariablePacker packer; 386 return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; 387 } 388