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 "common/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 uncompile(); 29 initializeCompiler(); 30 31 mRefCount = 0; 32 mDeleteStatus = false; 33 mShaderVersion = 100; 34 } 35 36 Shader::~Shader() 37 { 38 } 39 40 GLuint Shader::getHandle() const 41 { 42 return mHandle; 43 } 44 45 void Shader::setSource(GLsizei count, const char *const *string, const GLint *length) 46 { 47 std::ostringstream stream; 48 49 for (int i = 0; i < count; i++) 50 { 51 stream << string[i]; 52 } 53 54 mSource = stream.str(); 55 } 56 57 int Shader::getInfoLogLength() const 58 { 59 return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1); 60 } 61 62 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const 63 { 64 int index = 0; 65 66 if (bufSize > 0) 67 { 68 index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length())); 69 memcpy(infoLog, mInfoLog.c_str(), index); 70 71 infoLog[index] = '\0'; 72 } 73 74 if (length) 75 { 76 *length = index; 77 } 78 } 79 80 int Shader::getSourceLength() const 81 { 82 return mSource.empty() ? 0 : (mSource.length() + 1); 83 } 84 85 int Shader::getTranslatedSourceLength() const 86 { 87 return mHlsl.empty() ? 0 : (mHlsl.length() + 1); 88 } 89 90 void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const 91 { 92 int index = 0; 93 94 if (bufSize > 0) 95 { 96 index = std::min(bufSize - 1, static_cast<GLsizei>(source.length())); 97 memcpy(buffer, source.c_str(), index); 98 99 buffer[index] = '\0'; 100 } 101 102 if (length) 103 { 104 *length = index; 105 } 106 } 107 108 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const 109 { 110 getSourceImpl(mSource, bufSize, length, buffer); 111 } 112 113 void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const 114 { 115 getSourceImpl(mHlsl, bufSize, length, buffer); 116 } 117 118 const std::vector<Uniform> &Shader::getUniforms() const 119 { 120 return mActiveUniforms; 121 } 122 123 const std::vector<InterfaceBlock> &Shader::getInterfaceBlocks() const 124 { 125 return mActiveInterfaceBlocks; 126 } 127 128 std::vector<PackedVarying> &Shader::getVaryings() 129 { 130 return mVaryings; 131 } 132 133 bool Shader::isCompiled() const 134 { 135 return !mHlsl.empty(); 136 } 137 138 const std::string &Shader::getHLSL() const 139 { 140 return mHlsl; 141 } 142 143 void Shader::addRef() 144 { 145 mRefCount++; 146 } 147 148 void Shader::release() 149 { 150 mRefCount--; 151 152 if (mRefCount == 0 && mDeleteStatus) 153 { 154 mResourceManager->deleteShader(mHandle); 155 } 156 } 157 158 unsigned int Shader::getRefCount() const 159 { 160 return mRefCount; 161 } 162 163 bool Shader::isFlaggedForDeletion() const 164 { 165 return mDeleteStatus; 166 } 167 168 void Shader::flagForDeletion() 169 { 170 mDeleteStatus = true; 171 } 172 173 // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) 174 void Shader::initializeCompiler() 175 { 176 if (!mFragmentCompiler) 177 { 178 int result = ShInitialize(); 179 180 if (result) 181 { 182 ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; 183 184 ShBuiltInResources resources; 185 ShInitBuiltInResources(&resources); 186 187 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; 188 resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors(); 189 resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors(); 190 resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits(); 191 resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); 192 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; 193 resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); 194 resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets(); 195 resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport(); 196 resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1; 197 resources.EXT_shader_texture_lod = 1; 198 // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. 199 resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp 200 resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output 201 // GLSL ES 3.0 constants 202 resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors(); 203 resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors(); 204 resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE 205 resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 206 207 mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); 208 mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); 209 } 210 } 211 } 212 213 void Shader::releaseCompiler() 214 { 215 ShDestruct(mFragmentCompiler); 216 ShDestruct(mVertexCompiler); 217 218 mFragmentCompiler = NULL; 219 mVertexCompiler = NULL; 220 221 ShFinalize(); 222 } 223 224 void Shader::parseVaryings(void *compiler) 225 { 226 if (!mHlsl.empty()) 227 { 228 std::vector<Varying> *activeVaryings; 229 ShGetInfoPointer(compiler, SH_ACTIVE_VARYINGS_ARRAY, reinterpret_cast<void**>(&activeVaryings)); 230 231 for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++) 232 { 233 mVaryings.push_back(PackedVarying((*activeVaryings)[varyingIndex])); 234 } 235 236 mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos; 237 mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos; 238 mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos; 239 mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos; 240 mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos; 241 mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos; 242 mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos; 243 mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos; 244 mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos; 245 mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; 246 mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; 247 } 248 } 249 250 void Shader::resetVaryingsRegisterAssignment() 251 { 252 for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) 253 { 254 mVaryings[varyingIndex].resetRegisterAssignment(); 255 } 256 } 257 258 // initialize/clean up previous state 259 void Shader::uncompile() 260 { 261 // set by compileToHLSL 262 mHlsl.clear(); 263 mInfoLog.clear(); 264 265 // set by parseVaryings 266 mVaryings.clear(); 267 268 mUsesMultipleRenderTargets = false; 269 mUsesFragColor = false; 270 mUsesFragData = false; 271 mUsesFragCoord = false; 272 mUsesFrontFacing = false; 273 mUsesPointSize = false; 274 mUsesPointCoord = false; 275 mUsesDepthRange = false; 276 mUsesFragDepth = false; 277 mShaderVersion = 100; 278 mUsesDiscardRewriting = false; 279 mUsesNestedBreak = false; 280 281 mActiveUniforms.clear(); 282 mActiveInterfaceBlocks.clear(); 283 } 284 285 void Shader::compileToHLSL(void *compiler) 286 { 287 // ensure the compiler is loaded 288 initializeCompiler(); 289 290 int compileOptions = SH_OBJECT_CODE; 291 std::string sourcePath; 292 if (perfActive()) 293 { 294 sourcePath = getTempPath(); 295 writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length()); 296 compileOptions |= SH_LINE_DIRECTIVES; 297 } 298 299 int result; 300 if (sourcePath.empty()) 301 { 302 const char* sourceStrings[] = 303 { 304 mSource.c_str(), 305 }; 306 307 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); 308 } 309 else 310 { 311 const char* sourceStrings[] = 312 { 313 sourcePath.c_str(), 314 mSource.c_str(), 315 }; 316 317 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); 318 } 319 320 size_t shaderVersion = 100; 321 ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion); 322 323 mShaderVersion = static_cast<int>(shaderVersion); 324 325 if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) 326 { 327 mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; 328 TRACE("\n%s", mInfoLog.c_str()); 329 } 330 else if (result) 331 { 332 size_t objCodeLen = 0; 333 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); 334 335 char* outputHLSL = new char[objCodeLen]; 336 ShGetObjectCode(compiler, outputHLSL); 337 338 #ifdef _DEBUG 339 std::ostringstream hlslStream; 340 hlslStream << "// GLSL\n"; 341 hlslStream << "//\n"; 342 343 size_t curPos = 0; 344 while (curPos != std::string::npos) 345 { 346 size_t nextLine = mSource.find("\n", curPos); 347 size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); 348 349 hlslStream << "// " << mSource.substr(curPos, len); 350 351 curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); 352 } 353 hlslStream << "\n\n"; 354 hlslStream << outputHLSL; 355 mHlsl = hlslStream.str(); 356 #else 357 mHlsl = outputHLSL; 358 #endif 359 360 delete[] outputHLSL; 361 362 void *activeUniforms; 363 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); 364 mActiveUniforms = *(std::vector<Uniform>*)activeUniforms; 365 366 void *activeInterfaceBlocks; 367 ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks); 368 mActiveInterfaceBlocks = *(std::vector<InterfaceBlock>*)activeInterfaceBlocks; 369 } 370 else 371 { 372 size_t infoLogLen = 0; 373 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); 374 375 char* infoLog = new char[infoLogLen]; 376 ShGetInfoLog(compiler, infoLog); 377 mInfoLog = infoLog; 378 379 TRACE("\n%s", mInfoLog.c_str()); 380 } 381 } 382 383 rx::D3DWorkaroundType Shader::getD3DWorkarounds() const 384 { 385 if (mUsesDiscardRewriting) 386 { 387 // ANGLE issue 486: 388 // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization 389 return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION; 390 } 391 392 if (mUsesNestedBreak) 393 { 394 // ANGLE issue 603: 395 // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization 396 // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence 397 return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; 398 } 399 400 return rx::ANGLE_D3D_WORKAROUND_NONE; 401 } 402 403 // [OpenGL ES SL 3.00.4] Section 11 p. 120 404 // Vertex Outs/Fragment Ins packing priorities 405 static const GLenum varyingPriorityList[] = 406 { 407 // 1. Arrays of mat4 and mat4 408 GL_FLOAT_MAT4, 409 410 // Non-square matrices of type matCxR consume the same space as a square 411 // matrix of type matN where N is the greater of C and R 412 GL_FLOAT_MAT3x4, 413 GL_FLOAT_MAT4x3, 414 GL_FLOAT_MAT2x4, 415 GL_FLOAT_MAT4x2, 416 417 // 2. Arrays of mat2 and mat2 (since they occupy full rows) 418 GL_FLOAT_MAT2, 419 420 // 3. Arrays of vec4 and vec4 421 GL_FLOAT_VEC4, 422 GL_INT_VEC4, 423 GL_UNSIGNED_INT_VEC4, 424 425 // 4. Arrays of mat3 and mat3 426 GL_FLOAT_MAT3, 427 GL_FLOAT_MAT2x3, 428 GL_FLOAT_MAT3x2, 429 430 // 5. Arrays of vec3 and vec3 431 GL_FLOAT_VEC3, 432 GL_INT_VEC3, 433 GL_UNSIGNED_INT_VEC3, 434 435 // 6. Arrays of vec2 and vec2 436 GL_FLOAT_VEC2, 437 GL_INT_VEC2, 438 GL_UNSIGNED_INT_VEC2, 439 440 // 7. Arrays of float and float 441 GL_FLOAT, 442 GL_INT, 443 GL_UNSIGNED_INT, 444 }; 445 446 // true if varying x has a higher priority in packing than y 447 bool Shader::compareVarying(const PackedVarying &x, const PackedVarying &y) 448 { 449 if (x.type == y.type) 450 { 451 return x.arraySize > y.arraySize; 452 } 453 454 // Special case for handling structs: we sort these to the end of the list 455 if (x.type == GL_STRUCT_ANGLEX) 456 { 457 return false; 458 } 459 460 unsigned int xPriority = GL_INVALID_INDEX; 461 unsigned int yPriority = GL_INVALID_INDEX; 462 463 for (unsigned int priorityIndex = 0; priorityIndex < ArraySize(varyingPriorityList); priorityIndex++) 464 { 465 if (varyingPriorityList[priorityIndex] == x.type) xPriority = priorityIndex; 466 if (varyingPriorityList[priorityIndex] == y.type) yPriority = priorityIndex; 467 if (xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX) break; 468 } 469 470 ASSERT(xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX); 471 472 return xPriority <= yPriority; 473 } 474 475 int Shader::getShaderVersion() const 476 { 477 return mShaderVersion; 478 } 479 480 VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) 481 : Shader(manager, renderer, handle) 482 { 483 } 484 485 VertexShader::~VertexShader() 486 { 487 } 488 489 GLenum VertexShader::getType() 490 { 491 return GL_VERTEX_SHADER; 492 } 493 494 void VertexShader::uncompile() 495 { 496 Shader::uncompile(); 497 498 // set by ParseAttributes 499 mActiveAttributes.clear(); 500 } 501 502 void VertexShader::compile() 503 { 504 uncompile(); 505 506 compileToHLSL(mVertexCompiler); 507 parseAttributes(); 508 parseVaryings(mVertexCompiler); 509 } 510 511 int VertexShader::getSemanticIndex(const std::string &attributeName) 512 { 513 if (!attributeName.empty()) 514 { 515 int semanticIndex = 0; 516 for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++) 517 { 518 const ShaderVariable &attribute = mActiveAttributes[attributeIndex]; 519 520 if (attribute.name == attributeName) 521 { 522 return semanticIndex; 523 } 524 525 semanticIndex += AttributeRegisterCount(attribute.type); 526 } 527 } 528 529 return -1; 530 } 531 532 void VertexShader::parseAttributes() 533 { 534 const std::string &hlsl = getHLSL(); 535 if (!hlsl.empty()) 536 { 537 void *activeAttributes; 538 ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes); 539 mActiveAttributes = *(std::vector<Attribute>*)activeAttributes; 540 } 541 } 542 543 FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) 544 : Shader(manager, renderer, handle) 545 { 546 } 547 548 FragmentShader::~FragmentShader() 549 { 550 } 551 552 GLenum FragmentShader::getType() 553 { 554 return GL_FRAGMENT_SHADER; 555 } 556 557 void FragmentShader::compile() 558 { 559 uncompile(); 560 561 compileToHLSL(mFragmentCompiler); 562 parseVaryings(mFragmentCompiler); 563 std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); 564 565 const std::string &hlsl = getHLSL(); 566 if (!hlsl.empty()) 567 { 568 void *activeOutputVariables; 569 ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables); 570 mActiveOutputVariables = *(std::vector<Attribute>*)activeOutputVariables; 571 } 572 } 573 574 void FragmentShader::uncompile() 575 { 576 Shader::uncompile(); 577 578 mActiveOutputVariables.clear(); 579 } 580 581 const std::vector<Attribute> &FragmentShader::getOutputVariables() const 582 { 583 return mActiveOutputVariables; 584 } 585 586 ShShaderOutput Shader::getCompilerOutputType(GLenum shader) 587 { 588 void *compiler = NULL; 589 590 switch (shader) 591 { 592 case GL_VERTEX_SHADER: compiler = mVertexCompiler; break; 593 case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break; 594 default: UNREACHABLE(); return SH_HLSL9_OUTPUT; 595 } 596 597 size_t outputType = 0; 598 ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType); 599 600 return static_cast<ShShaderOutput>(outputType); 601 } 602 603 } 604