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