1 #include "precompiled.h" 2 // 3 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // 7 8 // Shader.cpp: Implements the gl::Shader class and its derived classes 9 // VertexShader and FragmentShader. Implements GL shader objects and related 10 // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. 11 12 #include "libGLESv2/Shader.h" 13 14 #include "GLSLANG/ShaderLang.h" 15 #include "libGLESv2/utilities.h" 16 #include "libGLESv2/renderer/Renderer.h" 17 #include "libGLESv2/Constants.h" 18 #include "libGLESv2/ResourceManager.h" 19 20 namespace gl 21 { 22 void *Shader::mFragmentCompiler = NULL; 23 void *Shader::mVertexCompiler = NULL; 24 25 Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) 26 : mHandle(handle), mRenderer(renderer), mResourceManager(manager) 27 { 28 mSource = NULL; 29 mHlsl = NULL; 30 mInfoLog = NULL; 31 32 uncompile(); 33 initializeCompiler(); 34 35 mRefCount = 0; 36 mDeleteStatus = false; 37 } 38 39 Shader::~Shader() 40 { 41 delete[] mSource; 42 delete[] mHlsl; 43 delete[] mInfoLog; 44 } 45 46 GLuint Shader::getHandle() const 47 { 48 return mHandle; 49 } 50 51 void Shader::setSource(GLsizei count, const char **string, const GLint *length) 52 { 53 delete[] mSource; 54 int totalLength = 0; 55 56 for (int i = 0; i < count; i++) 57 { 58 if (length && length[i] >= 0) 59 { 60 totalLength += length[i]; 61 } 62 else 63 { 64 totalLength += (int)strlen(string[i]); 65 } 66 } 67 68 mSource = new char[totalLength + 1]; 69 char *code = mSource; 70 71 for (int i = 0; i < count; i++) 72 { 73 int stringLength; 74 75 if (length && length[i] >= 0) 76 { 77 stringLength = length[i]; 78 } 79 else 80 { 81 stringLength = (int)strlen(string[i]); 82 } 83 84 strncpy(code, string[i], stringLength); 85 code += stringLength; 86 } 87 88 mSource[totalLength] = '\0'; 89 } 90 91 int Shader::getInfoLogLength() const 92 { 93 if (!mInfoLog) 94 { 95 return 0; 96 } 97 else 98 { 99 return strlen(mInfoLog) + 1; 100 } 101 } 102 103 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) 104 { 105 int index = 0; 106 107 if (bufSize > 0) 108 { 109 if (mInfoLog) 110 { 111 index = std::min(bufSize - 1, (int)strlen(mInfoLog)); 112 memcpy(infoLog, mInfoLog, index); 113 } 114 115 infoLog[index] = '\0'; 116 } 117 118 if (length) 119 { 120 *length = index; 121 } 122 } 123 124 int Shader::getSourceLength() const 125 { 126 if (!mSource) 127 { 128 return 0; 129 } 130 else 131 { 132 return strlen(mSource) + 1; 133 } 134 } 135 136 int Shader::getTranslatedSourceLength() const 137 { 138 if (!mHlsl) 139 { 140 return 0; 141 } 142 else 143 { 144 return strlen(mHlsl) + 1; 145 } 146 } 147 148 void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer) 149 { 150 int index = 0; 151 152 if (bufSize > 0) 153 { 154 if (source) 155 { 156 index = std::min(bufSize - 1, (int)strlen(source)); 157 memcpy(buffer, source, index); 158 } 159 160 buffer[index] = '\0'; 161 } 162 163 if (length) 164 { 165 *length = index; 166 } 167 } 168 169 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) 170 { 171 getSourceImpl(mSource, bufSize, length, buffer); 172 } 173 174 void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) 175 { 176 getSourceImpl(mHlsl, bufSize, length, buffer); 177 } 178 179 const sh::ActiveUniforms &Shader::getUniforms() 180 { 181 return mActiveUniforms; 182 } 183 184 bool Shader::isCompiled() 185 { 186 return mHlsl != NULL; 187 } 188 189 const char *Shader::getHLSL() 190 { 191 return mHlsl; 192 } 193 194 void Shader::addRef() 195 { 196 mRefCount++; 197 } 198 199 void Shader::release() 200 { 201 mRefCount--; 202 203 if (mRefCount == 0 && mDeleteStatus) 204 { 205 mResourceManager->deleteShader(mHandle); 206 } 207 } 208 209 unsigned int Shader::getRefCount() const 210 { 211 return mRefCount; 212 } 213 214 bool Shader::isFlaggedForDeletion() const 215 { 216 return mDeleteStatus; 217 } 218 219 void Shader::flagForDeletion() 220 { 221 mDeleteStatus = true; 222 } 223 224 // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) 225 void Shader::initializeCompiler() 226 { 227 if (!mFragmentCompiler) 228 { 229 int result = ShInitialize(); 230 231 if (result) 232 { 233 ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; 234 235 ShBuiltInResources resources; 236 ShInitBuiltInResources(&resources); 237 238 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; 239 resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors(); 240 resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors(); 241 resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits(); 242 resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); 243 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; 244 resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); 245 resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets(); 246 resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport(); 247 resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1; 248 // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. 249 resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp 250 resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output 251 252 mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); 253 mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); 254 } 255 } 256 } 257 258 void Shader::releaseCompiler() 259 { 260 ShDestruct(mFragmentCompiler); 261 ShDestruct(mVertexCompiler); 262 263 mFragmentCompiler = NULL; 264 mVertexCompiler = NULL; 265 266 ShFinalize(); 267 } 268 269 void Shader::parseVaryings() 270 { 271 if (mHlsl) 272 { 273 const char *input = strstr(mHlsl, "// Varyings") + 12; 274 275 while(true) 276 { 277 char varyingType[256]; 278 char varyingName[256]; 279 280 int matches = sscanf(input, "static %255s %255s", varyingType, varyingName); 281 282 if (matches != 2) 283 { 284 break; 285 } 286 287 char *array = strstr(varyingName, "["); 288 int size = 1; 289 290 if (array) 291 { 292 size = atoi(array + 1); 293 *array = '\0'; 294 } 295 296 mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL)); 297 298 input = strstr(input, ";") + 2; 299 } 300 301 mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL; 302 mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL; 303 mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL; 304 mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL; 305 mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL; 306 mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL; 307 mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL; 308 mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL; 309 mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL; 310 mUsesDiscardRewriting = strstr(mHlsl, "ANGLE_USES_DISCARD_REWRITING") != NULL; 311 } 312 } 313 314 void Shader::resetVaryingsRegisterAssignment() 315 { 316 for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++) 317 { 318 var->reg = -1; 319 var->col = -1; 320 } 321 } 322 323 // initialize/clean up previous state 324 void Shader::uncompile() 325 { 326 // set by compileToHLSL 327 delete[] mHlsl; 328 mHlsl = NULL; 329 delete[] mInfoLog; 330 mInfoLog = NULL; 331 332 // set by parseVaryings 333 mVaryings.clear(); 334 335 mUsesMultipleRenderTargets = false; 336 mUsesFragColor = false; 337 mUsesFragData = false; 338 mUsesFragCoord = false; 339 mUsesFrontFacing = false; 340 mUsesPointSize = false; 341 mUsesPointCoord = false; 342 mUsesDepthRange = false; 343 mUsesFragDepth = false; 344 mUsesDiscardRewriting = false; 345 346 mActiveUniforms.clear(); 347 } 348 349 void Shader::compileToHLSL(void *compiler) 350 { 351 // ensure we don't pass a NULL source to the compiler 352 const char *source = "\0"; 353 if (mSource) 354 { 355 source = mSource; 356 } 357 358 // ensure the compiler is loaded 359 initializeCompiler(); 360 361 int compileOptions = SH_OBJECT_CODE; 362 std::string sourcePath; 363 if (perfActive()) 364 { 365 sourcePath = getTempPath(); 366 writeFile(sourcePath.c_str(), source, strlen(source)); 367 compileOptions |= SH_LINE_DIRECTIVES; 368 } 369 370 int result; 371 if (sourcePath.empty()) 372 { 373 result = ShCompile(compiler, &source, 1, compileOptions); 374 } 375 else 376 { 377 const char* sourceStrings[2] = 378 { 379 sourcePath.c_str(), 380 source 381 }; 382 383 result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH); 384 } 385 386 if (result) 387 { 388 size_t objCodeLen = 0; 389 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); 390 mHlsl = new char[objCodeLen]; 391 ShGetObjectCode(compiler, mHlsl); 392 393 void *activeUniforms; 394 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); 395 mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms; 396 } 397 else 398 { 399 size_t infoLogLen = 0; 400 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); 401 mInfoLog = new char[infoLogLen]; 402 ShGetInfoLog(compiler, mInfoLog); 403 404 TRACE("\n%s", mInfoLog); 405 } 406 } 407 408 GLenum Shader::parseType(const std::string &type) 409 { 410 if (type == "float") 411 { 412 return GL_FLOAT; 413 } 414 else if (type == "float2") 415 { 416 return GL_FLOAT_VEC2; 417 } 418 else if (type == "float3") 419 { 420 return GL_FLOAT_VEC3; 421 } 422 else if (type == "float4") 423 { 424 return GL_FLOAT_VEC4; 425 } 426 else if (type == "float2x2") 427 { 428 return GL_FLOAT_MAT2; 429 } 430 else if (type == "float3x3") 431 { 432 return GL_FLOAT_MAT3; 433 } 434 else if (type == "float4x4") 435 { 436 return GL_FLOAT_MAT4; 437 } 438 else UNREACHABLE(); 439 440 return GL_NONE; 441 } 442 443 // true if varying x has a higher priority in packing than y 444 bool Shader::compareVarying(const Varying &x, const Varying &y) 445 { 446 if(x.type == y.type) 447 { 448 return x.size > y.size; 449 } 450 451 switch (x.type) 452 { 453 case GL_FLOAT_MAT4: return true; 454 case GL_FLOAT_MAT2: 455 switch(y.type) 456 { 457 case GL_FLOAT_MAT4: return false; 458 case GL_FLOAT_MAT2: return true; 459 case GL_FLOAT_VEC4: return true; 460 case GL_FLOAT_MAT3: return true; 461 case GL_FLOAT_VEC3: return true; 462 case GL_FLOAT_VEC2: return true; 463 case GL_FLOAT: return true; 464 default: UNREACHABLE(); 465 } 466 break; 467 case GL_FLOAT_VEC4: 468 switch(y.type) 469 { 470 case GL_FLOAT_MAT4: return false; 471 case GL_FLOAT_MAT2: return false; 472 case GL_FLOAT_VEC4: return true; 473 case GL_FLOAT_MAT3: return true; 474 case GL_FLOAT_VEC3: return true; 475 case GL_FLOAT_VEC2: return true; 476 case GL_FLOAT: return true; 477 default: UNREACHABLE(); 478 } 479 break; 480 case GL_FLOAT_MAT3: 481 switch(y.type) 482 { 483 case GL_FLOAT_MAT4: return false; 484 case GL_FLOAT_MAT2: return false; 485 case GL_FLOAT_VEC4: return false; 486 case GL_FLOAT_MAT3: return true; 487 case GL_FLOAT_VEC3: return true; 488 case GL_FLOAT_VEC2: return true; 489 case GL_FLOAT: return true; 490 default: UNREACHABLE(); 491 } 492 break; 493 case GL_FLOAT_VEC3: 494 switch(y.type) 495 { 496 case GL_FLOAT_MAT4: return false; 497 case GL_FLOAT_MAT2: return false; 498 case GL_FLOAT_VEC4: return false; 499 case GL_FLOAT_MAT3: return false; 500 case GL_FLOAT_VEC3: return true; 501 case GL_FLOAT_VEC2: return true; 502 case GL_FLOAT: return true; 503 default: UNREACHABLE(); 504 } 505 break; 506 case GL_FLOAT_VEC2: 507 switch(y.type) 508 { 509 case GL_FLOAT_MAT4: return false; 510 case GL_FLOAT_MAT2: return false; 511 case GL_FLOAT_VEC4: return false; 512 case GL_FLOAT_MAT3: return false; 513 case GL_FLOAT_VEC3: return false; 514 case GL_FLOAT_VEC2: return true; 515 case GL_FLOAT: return true; 516 default: UNREACHABLE(); 517 } 518 break; 519 case GL_FLOAT: return false; 520 default: UNREACHABLE(); 521 } 522 523 return false; 524 } 525 526 VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) 527 : Shader(manager, renderer, handle) 528 { 529 } 530 531 VertexShader::~VertexShader() 532 { 533 } 534 535 GLenum VertexShader::getType() 536 { 537 return GL_VERTEX_SHADER; 538 } 539 540 void VertexShader::uncompile() 541 { 542 Shader::uncompile(); 543 544 // set by ParseAttributes 545 mAttributes.clear(); 546 } 547 548 void VertexShader::compile() 549 { 550 uncompile(); 551 552 compileToHLSL(mVertexCompiler); 553 parseAttributes(); 554 parseVaryings(); 555 } 556 557 int VertexShader::getSemanticIndex(const std::string &attributeName) 558 { 559 if (!attributeName.empty()) 560 { 561 int semanticIndex = 0; 562 for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++) 563 { 564 if (attribute->name == attributeName) 565 { 566 return semanticIndex; 567 } 568 569 semanticIndex += VariableRowCount(attribute->type); 570 } 571 } 572 573 return -1; 574 } 575 576 void VertexShader::parseAttributes() 577 { 578 const char *hlsl = getHLSL(); 579 if (hlsl) 580 { 581 const char *input = strstr(hlsl, "// Attributes") + 14; 582 583 while(true) 584 { 585 char attributeType[256]; 586 char attributeName[256]; 587 588 int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName); 589 590 if (matches != 2) 591 { 592 break; 593 } 594 595 mAttributes.push_back(Attribute(parseType(attributeType), attributeName)); 596 597 input = strstr(input, ";") + 2; 598 } 599 } 600 } 601 602 FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) 603 : Shader(manager, renderer, handle) 604 { 605 } 606 607 FragmentShader::~FragmentShader() 608 { 609 } 610 611 GLenum FragmentShader::getType() 612 { 613 return GL_FRAGMENT_SHADER; 614 } 615 616 void FragmentShader::compile() 617 { 618 uncompile(); 619 620 compileToHLSL(mFragmentCompiler); 621 parseVaryings(); 622 mVaryings.sort(compareVarying); 623 } 624 } 625