1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/Shader.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,624 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// Shader.cpp: Implements the gl::Shader class and its derived classes 1.12 +// VertexShader and FragmentShader. Implements GL shader objects and related 1.13 +// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. 1.14 + 1.15 +#include "libGLESv2/Shader.h" 1.16 + 1.17 +#include <algorithm> 1.18 + 1.19 +#include "GLSLANG/ShaderLang.h" 1.20 +#include "libGLESv2/utilities.h" 1.21 +#include "libGLESv2/renderer/Renderer.h" 1.22 +#include "libGLESv2/Constants.h" 1.23 +#include "libGLESv2/ResourceManager.h" 1.24 + 1.25 +namespace gl 1.26 +{ 1.27 +void *Shader::mFragmentCompiler = NULL; 1.28 +void *Shader::mVertexCompiler = NULL; 1.29 + 1.30 +Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) 1.31 + : mHandle(handle), mRenderer(renderer), mResourceManager(manager) 1.32 +{ 1.33 + mSource = NULL; 1.34 + mHlsl = NULL; 1.35 + mInfoLog = NULL; 1.36 + 1.37 + uncompile(); 1.38 + initializeCompiler(); 1.39 + 1.40 + mRefCount = 0; 1.41 + mDeleteStatus = false; 1.42 +} 1.43 + 1.44 +Shader::~Shader() 1.45 +{ 1.46 + delete[] mSource; 1.47 + delete[] mHlsl; 1.48 + delete[] mInfoLog; 1.49 +} 1.50 + 1.51 +GLuint Shader::getHandle() const 1.52 +{ 1.53 + return mHandle; 1.54 +} 1.55 + 1.56 +void Shader::setSource(GLsizei count, const char **string, const GLint *length) 1.57 +{ 1.58 + delete[] mSource; 1.59 + int totalLength = 0; 1.60 + 1.61 + for (int i = 0; i < count; i++) 1.62 + { 1.63 + if (length && length[i] >= 0) 1.64 + { 1.65 + totalLength += length[i]; 1.66 + } 1.67 + else 1.68 + { 1.69 + totalLength += (int)strlen(string[i]); 1.70 + } 1.71 + } 1.72 + 1.73 + mSource = new char[totalLength + 1]; 1.74 + char *code = mSource; 1.75 + 1.76 + for (int i = 0; i < count; i++) 1.77 + { 1.78 + int stringLength; 1.79 + 1.80 + if (length && length[i] >= 0) 1.81 + { 1.82 + stringLength = length[i]; 1.83 + } 1.84 + else 1.85 + { 1.86 + stringLength = (int)strlen(string[i]); 1.87 + } 1.88 + 1.89 + strncpy(code, string[i], stringLength); 1.90 + code += stringLength; 1.91 + } 1.92 + 1.93 + mSource[totalLength] = '\0'; 1.94 +} 1.95 + 1.96 +int Shader::getInfoLogLength() const 1.97 +{ 1.98 + if (!mInfoLog) 1.99 + { 1.100 + return 0; 1.101 + } 1.102 + else 1.103 + { 1.104 + return strlen(mInfoLog) + 1; 1.105 + } 1.106 +} 1.107 + 1.108 +void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) 1.109 +{ 1.110 + int index = 0; 1.111 + 1.112 + if (bufSize > 0) 1.113 + { 1.114 + if (mInfoLog) 1.115 + { 1.116 + index = std::min(bufSize - 1, (int)strlen(mInfoLog)); 1.117 + memcpy(infoLog, mInfoLog, index); 1.118 + } 1.119 + 1.120 + infoLog[index] = '\0'; 1.121 + } 1.122 + 1.123 + if (length) 1.124 + { 1.125 + *length = index; 1.126 + } 1.127 +} 1.128 + 1.129 +int Shader::getSourceLength() const 1.130 +{ 1.131 + if (!mSource) 1.132 + { 1.133 + return 0; 1.134 + } 1.135 + else 1.136 + { 1.137 + return strlen(mSource) + 1; 1.138 + } 1.139 +} 1.140 + 1.141 +int Shader::getTranslatedSourceLength() const 1.142 +{ 1.143 + if (!mHlsl) 1.144 + { 1.145 + return 0; 1.146 + } 1.147 + else 1.148 + { 1.149 + return strlen(mHlsl) + 1; 1.150 + } 1.151 +} 1.152 + 1.153 +void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer) 1.154 +{ 1.155 + int index = 0; 1.156 + 1.157 + if (bufSize > 0) 1.158 + { 1.159 + if (source) 1.160 + { 1.161 + index = std::min(bufSize - 1, (int)strlen(source)); 1.162 + memcpy(buffer, source, index); 1.163 + } 1.164 + 1.165 + buffer[index] = '\0'; 1.166 + } 1.167 + 1.168 + if (length) 1.169 + { 1.170 + *length = index; 1.171 + } 1.172 +} 1.173 + 1.174 +void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) 1.175 +{ 1.176 + getSourceImpl(mSource, bufSize, length, buffer); 1.177 +} 1.178 + 1.179 +void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) 1.180 +{ 1.181 + getSourceImpl(mHlsl, bufSize, length, buffer); 1.182 +} 1.183 + 1.184 +const sh::ActiveUniforms &Shader::getUniforms() 1.185 +{ 1.186 + return mActiveUniforms; 1.187 +} 1.188 + 1.189 +bool Shader::isCompiled() 1.190 +{ 1.191 + return mHlsl != NULL; 1.192 +} 1.193 + 1.194 +const char *Shader::getHLSL() 1.195 +{ 1.196 + return mHlsl; 1.197 +} 1.198 + 1.199 +void Shader::addRef() 1.200 +{ 1.201 + mRefCount++; 1.202 +} 1.203 + 1.204 +void Shader::release() 1.205 +{ 1.206 + mRefCount--; 1.207 + 1.208 + if (mRefCount == 0 && mDeleteStatus) 1.209 + { 1.210 + mResourceManager->deleteShader(mHandle); 1.211 + } 1.212 +} 1.213 + 1.214 +unsigned int Shader::getRefCount() const 1.215 +{ 1.216 + return mRefCount; 1.217 +} 1.218 + 1.219 +bool Shader::isFlaggedForDeletion() const 1.220 +{ 1.221 + return mDeleteStatus; 1.222 +} 1.223 + 1.224 +void Shader::flagForDeletion() 1.225 +{ 1.226 + mDeleteStatus = true; 1.227 +} 1.228 + 1.229 +// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) 1.230 +void Shader::initializeCompiler() 1.231 +{ 1.232 + if (!mFragmentCompiler) 1.233 + { 1.234 + int result = ShInitialize(); 1.235 + 1.236 + if (result) 1.237 + { 1.238 + ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; 1.239 + 1.240 + ShBuiltInResources resources; 1.241 + ShInitBuiltInResources(&resources); 1.242 + 1.243 + resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; 1.244 + resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors(); 1.245 + resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors(); 1.246 + resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits(); 1.247 + resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); 1.248 + resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; 1.249 + resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); 1.250 + resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets(); 1.251 + resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport(); 1.252 + resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1; 1.253 + // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. 1.254 + resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp 1.255 + resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output 1.256 + 1.257 + mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); 1.258 + mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); 1.259 + } 1.260 + } 1.261 +} 1.262 + 1.263 +void Shader::releaseCompiler() 1.264 +{ 1.265 + ShDestruct(mFragmentCompiler); 1.266 + ShDestruct(mVertexCompiler); 1.267 + 1.268 + mFragmentCompiler = NULL; 1.269 + mVertexCompiler = NULL; 1.270 + 1.271 + ShFinalize(); 1.272 +} 1.273 + 1.274 +void Shader::parseVaryings() 1.275 +{ 1.276 + if (mHlsl) 1.277 + { 1.278 + const char *input = strstr(mHlsl, "// Varyings") + 12; 1.279 + 1.280 + while(true) 1.281 + { 1.282 + char varyingType[256]; 1.283 + char varyingName[256]; 1.284 + 1.285 + int matches = sscanf(input, "static %255s %255s", varyingType, varyingName); 1.286 + 1.287 + if (matches != 2) 1.288 + { 1.289 + break; 1.290 + } 1.291 + 1.292 + char *array = strstr(varyingName, "["); 1.293 + int size = 1; 1.294 + 1.295 + if (array) 1.296 + { 1.297 + size = atoi(array + 1); 1.298 + *array = '\0'; 1.299 + } 1.300 + 1.301 + mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL)); 1.302 + 1.303 + input = strstr(input, ";") + 2; 1.304 + } 1.305 + 1.306 + mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL; 1.307 + mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL; 1.308 + mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL; 1.309 + mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL; 1.310 + mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL; 1.311 + mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL; 1.312 + mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL; 1.313 + mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL; 1.314 + mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL; 1.315 + } 1.316 +} 1.317 + 1.318 +void Shader::resetVaryingsRegisterAssignment() 1.319 +{ 1.320 + for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++) 1.321 + { 1.322 + var->reg = -1; 1.323 + var->col = -1; 1.324 + } 1.325 +} 1.326 + 1.327 +// initialize/clean up previous state 1.328 +void Shader::uncompile() 1.329 +{ 1.330 + // set by compileToHLSL 1.331 + delete[] mHlsl; 1.332 + mHlsl = NULL; 1.333 + delete[] mInfoLog; 1.334 + mInfoLog = NULL; 1.335 + 1.336 + // set by parseVaryings 1.337 + mVaryings.clear(); 1.338 + 1.339 + mUsesMultipleRenderTargets = false; 1.340 + mUsesFragColor = false; 1.341 + mUsesFragData = false; 1.342 + mUsesFragCoord = false; 1.343 + mUsesFrontFacing = false; 1.344 + mUsesPointSize = false; 1.345 + mUsesPointCoord = false; 1.346 + mUsesDepthRange = false; 1.347 + mUsesFragDepth = false; 1.348 + 1.349 + mActiveUniforms.clear(); 1.350 +} 1.351 + 1.352 +void Shader::compileToHLSL(void *compiler) 1.353 +{ 1.354 + // ensure we don't pass a NULL source to the compiler 1.355 + const char *source = "\0"; 1.356 + if (mSource) 1.357 + { 1.358 + source = mSource; 1.359 + } 1.360 + 1.361 + // ensure the compiler is loaded 1.362 + initializeCompiler(); 1.363 + 1.364 + int compileOptions = SH_OBJECT_CODE; 1.365 + std::string sourcePath; 1.366 + if (perfActive()) 1.367 + { 1.368 + sourcePath = getTempPath(); 1.369 + writeFile(sourcePath.c_str(), source, strlen(source)); 1.370 + compileOptions |= SH_LINE_DIRECTIVES; 1.371 + } 1.372 + 1.373 + int result; 1.374 + if (sourcePath.empty()) 1.375 + { 1.376 + result = ShCompile(compiler, &source, 1, compileOptions); 1.377 + } 1.378 + else 1.379 + { 1.380 + const char* sourceStrings[2] = 1.381 + { 1.382 + sourcePath.c_str(), 1.383 + source 1.384 + }; 1.385 + 1.386 + result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH); 1.387 + } 1.388 + 1.389 + if (result) 1.390 + { 1.391 + size_t objCodeLen = 0; 1.392 + ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); 1.393 + mHlsl = new char[objCodeLen]; 1.394 + ShGetObjectCode(compiler, mHlsl); 1.395 + 1.396 + void *activeUniforms; 1.397 + ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); 1.398 + mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms; 1.399 + } 1.400 + else 1.401 + { 1.402 + size_t infoLogLen = 0; 1.403 + ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); 1.404 + mInfoLog = new char[infoLogLen]; 1.405 + ShGetInfoLog(compiler, mInfoLog); 1.406 + 1.407 + TRACE("\n%s", mInfoLog); 1.408 + } 1.409 +} 1.410 + 1.411 +GLenum Shader::parseType(const std::string &type) 1.412 +{ 1.413 + if (type == "float") 1.414 + { 1.415 + return GL_FLOAT; 1.416 + } 1.417 + else if (type == "float2") 1.418 + { 1.419 + return GL_FLOAT_VEC2; 1.420 + } 1.421 + else if (type == "float3") 1.422 + { 1.423 + return GL_FLOAT_VEC3; 1.424 + } 1.425 + else if (type == "float4") 1.426 + { 1.427 + return GL_FLOAT_VEC4; 1.428 + } 1.429 + else if (type == "float2x2") 1.430 + { 1.431 + return GL_FLOAT_MAT2; 1.432 + } 1.433 + else if (type == "float3x3") 1.434 + { 1.435 + return GL_FLOAT_MAT3; 1.436 + } 1.437 + else if (type == "float4x4") 1.438 + { 1.439 + return GL_FLOAT_MAT4; 1.440 + } 1.441 + else UNREACHABLE(); 1.442 + 1.443 + return GL_NONE; 1.444 +} 1.445 + 1.446 +// true if varying x has a higher priority in packing than y 1.447 +bool Shader::compareVarying(const Varying &x, const Varying &y) 1.448 +{ 1.449 + if(x.type == y.type) 1.450 + { 1.451 + return x.size > y.size; 1.452 + } 1.453 + 1.454 + switch (x.type) 1.455 + { 1.456 + case GL_FLOAT_MAT4: return true; 1.457 + case GL_FLOAT_MAT2: 1.458 + switch(y.type) 1.459 + { 1.460 + case GL_FLOAT_MAT4: return false; 1.461 + case GL_FLOAT_MAT2: return true; 1.462 + case GL_FLOAT_VEC4: return true; 1.463 + case GL_FLOAT_MAT3: return true; 1.464 + case GL_FLOAT_VEC3: return true; 1.465 + case GL_FLOAT_VEC2: return true; 1.466 + case GL_FLOAT: return true; 1.467 + default: UNREACHABLE(); 1.468 + } 1.469 + break; 1.470 + case GL_FLOAT_VEC4: 1.471 + switch(y.type) 1.472 + { 1.473 + case GL_FLOAT_MAT4: return false; 1.474 + case GL_FLOAT_MAT2: return false; 1.475 + case GL_FLOAT_VEC4: return true; 1.476 + case GL_FLOAT_MAT3: return true; 1.477 + case GL_FLOAT_VEC3: return true; 1.478 + case GL_FLOAT_VEC2: return true; 1.479 + case GL_FLOAT: return true; 1.480 + default: UNREACHABLE(); 1.481 + } 1.482 + break; 1.483 + case GL_FLOAT_MAT3: 1.484 + switch(y.type) 1.485 + { 1.486 + case GL_FLOAT_MAT4: return false; 1.487 + case GL_FLOAT_MAT2: return false; 1.488 + case GL_FLOAT_VEC4: return false; 1.489 + case GL_FLOAT_MAT3: return true; 1.490 + case GL_FLOAT_VEC3: return true; 1.491 + case GL_FLOAT_VEC2: return true; 1.492 + case GL_FLOAT: return true; 1.493 + default: UNREACHABLE(); 1.494 + } 1.495 + break; 1.496 + case GL_FLOAT_VEC3: 1.497 + switch(y.type) 1.498 + { 1.499 + case GL_FLOAT_MAT4: return false; 1.500 + case GL_FLOAT_MAT2: return false; 1.501 + case GL_FLOAT_VEC4: return false; 1.502 + case GL_FLOAT_MAT3: return false; 1.503 + case GL_FLOAT_VEC3: return true; 1.504 + case GL_FLOAT_VEC2: return true; 1.505 + case GL_FLOAT: return true; 1.506 + default: UNREACHABLE(); 1.507 + } 1.508 + break; 1.509 + case GL_FLOAT_VEC2: 1.510 + switch(y.type) 1.511 + { 1.512 + case GL_FLOAT_MAT4: return false; 1.513 + case GL_FLOAT_MAT2: return false; 1.514 + case GL_FLOAT_VEC4: return false; 1.515 + case GL_FLOAT_MAT3: return false; 1.516 + case GL_FLOAT_VEC3: return false; 1.517 + case GL_FLOAT_VEC2: return true; 1.518 + case GL_FLOAT: return true; 1.519 + default: UNREACHABLE(); 1.520 + } 1.521 + break; 1.522 + case GL_FLOAT: return false; 1.523 + default: UNREACHABLE(); 1.524 + } 1.525 + 1.526 + return false; 1.527 +} 1.528 + 1.529 +VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) 1.530 + : Shader(manager, renderer, handle) 1.531 +{ 1.532 +} 1.533 + 1.534 +VertexShader::~VertexShader() 1.535 +{ 1.536 +} 1.537 + 1.538 +GLenum VertexShader::getType() 1.539 +{ 1.540 + return GL_VERTEX_SHADER; 1.541 +} 1.542 + 1.543 +void VertexShader::uncompile() 1.544 +{ 1.545 + Shader::uncompile(); 1.546 + 1.547 + // set by ParseAttributes 1.548 + mAttributes.clear(); 1.549 +} 1.550 + 1.551 +void VertexShader::compile() 1.552 +{ 1.553 + uncompile(); 1.554 + 1.555 + compileToHLSL(mVertexCompiler); 1.556 + parseAttributes(); 1.557 + parseVaryings(); 1.558 +} 1.559 + 1.560 +int VertexShader::getSemanticIndex(const std::string &attributeName) 1.561 +{ 1.562 + if (!attributeName.empty()) 1.563 + { 1.564 + int semanticIndex = 0; 1.565 + for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++) 1.566 + { 1.567 + if (attribute->name == attributeName) 1.568 + { 1.569 + return semanticIndex; 1.570 + } 1.571 + 1.572 + semanticIndex += VariableRowCount(attribute->type); 1.573 + } 1.574 + } 1.575 + 1.576 + return -1; 1.577 +} 1.578 + 1.579 +void VertexShader::parseAttributes() 1.580 +{ 1.581 + const char *hlsl = getHLSL(); 1.582 + if (hlsl) 1.583 + { 1.584 + const char *input = strstr(hlsl, "// Attributes") + 14; 1.585 + 1.586 + while(true) 1.587 + { 1.588 + char attributeType[256]; 1.589 + char attributeName[256]; 1.590 + 1.591 + int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName); 1.592 + 1.593 + if (matches != 2) 1.594 + { 1.595 + break; 1.596 + } 1.597 + 1.598 + mAttributes.push_back(Attribute(parseType(attributeType), attributeName)); 1.599 + 1.600 + input = strstr(input, ";") + 2; 1.601 + } 1.602 + } 1.603 +} 1.604 + 1.605 +FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) 1.606 + : Shader(manager, renderer, handle) 1.607 +{ 1.608 +} 1.609 + 1.610 +FragmentShader::~FragmentShader() 1.611 +{ 1.612 +} 1.613 + 1.614 +GLenum FragmentShader::getType() 1.615 +{ 1.616 + return GL_FRAGMENT_SHADER; 1.617 +} 1.618 + 1.619 +void FragmentShader::compile() 1.620 +{ 1.621 + uncompile(); 1.622 + 1.623 + compileToHLSL(mFragmentCompiler); 1.624 + parseVaryings(); 1.625 + mVaryings.sort(compareVarying); 1.626 +} 1.627 +}