1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Shader.cpp: Implements the Shader class and its derived classes 16 // VertexShader and FragmentShader. Implements GL shader objects and related 17 // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. 18 19 #include "Shader.h" 20 21 #include "main.h" 22 #include "utilities.h" 23 24 #include <string> 25 #include <algorithm> 26 27 namespace es2 28 { 29 bool Shader::compilerInitialized = false; 30 31 Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager) 32 { 33 mSource = nullptr; 34 35 clear(); 36 37 mRefCount = 0; 38 mDeleteStatus = false; 39 } 40 41 Shader::~Shader() 42 { 43 delete[] mSource; 44 } 45 46 GLuint Shader::getName() const 47 { 48 return mHandle; 49 } 50 51 void Shader::setSource(GLsizei count, const char *const *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 size_t Shader::getInfoLogLength() const 92 { 93 if(infoLog.empty()) 94 { 95 return 0; 96 } 97 else 98 { 99 return infoLog.size() + 1; 100 } 101 } 102 103 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLogOut) 104 { 105 int index = 0; 106 107 if(bufSize > 0) 108 { 109 if(!infoLog.empty()) 110 { 111 index = std::min(bufSize - 1, (GLsizei)infoLog.size()); 112 memcpy(infoLogOut, infoLog.c_str(), index); 113 } 114 115 infoLogOut[index] = '\0'; 116 } 117 118 if(length) 119 { 120 *length = index; 121 } 122 } 123 124 size_t Shader::getSourceLength() const 125 { 126 if(!mSource) 127 { 128 return 0; 129 } 130 else 131 { 132 return strlen(mSource) + 1; 133 } 134 } 135 136 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source) 137 { 138 int index = 0; 139 140 if(bufSize > 0) 141 { 142 if(mSource) 143 { 144 index = std::min(bufSize - 1, (int)strlen(mSource)); 145 memcpy(source, mSource, index); 146 } 147 148 source[index] = '\0'; 149 } 150 151 if(length) 152 { 153 *length = index; 154 } 155 } 156 157 TranslatorASM *Shader::createCompiler(GLenum shaderType) 158 { 159 if(!compilerInitialized) 160 { 161 InitCompilerGlobals(); 162 compilerInitialized = true; 163 } 164 165 TranslatorASM *assembler = new TranslatorASM(this, shaderType); 166 167 ShBuiltInResources resources; 168 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; 169 resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS; 170 resources.MaxVaryingVectors = MAX_VARYING_VECTORS; 171 resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS; 172 resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS; 173 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; 174 resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS; 175 resources.MaxDrawBuffers = MAX_DRAW_BUFFERS; 176 resources.MaxVertexOutputVectors = MAX_VERTEX_OUTPUT_VECTORS; 177 resources.MaxFragmentInputVectors = MAX_FRAGMENT_INPUT_VECTORS; 178 resources.MinProgramTexelOffset = MIN_PROGRAM_TEXEL_OFFSET; 179 resources.MaxProgramTexelOffset = MAX_PROGRAM_TEXEL_OFFSET; 180 resources.OES_standard_derivatives = 1; 181 resources.OES_fragment_precision_high = 1; 182 resources.OES_EGL_image_external = 1; 183 resources.EXT_draw_buffers = 1; 184 resources.MaxCallStackDepth = 16; 185 assembler->Init(resources); 186 187 return assembler; 188 } 189 190 void Shader::clear() 191 { 192 infoLog.clear(); 193 194 varyings.clear(); 195 activeUniforms.clear(); 196 activeAttributes.clear(); 197 } 198 199 void Shader::compile() 200 { 201 clear(); 202 203 createShader(); 204 TranslatorASM *compiler = createCompiler(getType()); 205 206 // Ensure we don't pass a nullptr source to the compiler 207 const char *source = "\0"; 208 if(mSource) 209 { 210 source = mSource; 211 } 212 213 bool success = compiler->compile(&source, 1, SH_OBJECT_CODE); 214 215 if(false) 216 { 217 static int serial = 1; 218 char buffer[256]; 219 sprintf(buffer, "shader-input-%d-%d.txt", getName(), serial); 220 FILE *file = fopen(buffer, "wt"); 221 fprintf(file, "%s", mSource); 222 fclose(file); 223 getShader()->print("shader-output-%d-%d.txt", getName(), serial); 224 serial++; 225 } 226 227 int shaderVersion = compiler->getShaderVersion(); 228 int clientVersion = es2::getContext()->getClientVersion(); 229 230 if(shaderVersion >= 300 && clientVersion < 3) 231 { 232 infoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; 233 success = false; 234 } 235 236 if(!success) 237 { 238 deleteShader(); 239 240 infoLog += compiler->getInfoSink().info.c_str(); 241 TRACE("\n%s", infoLog.c_str()); 242 } 243 244 delete compiler; 245 } 246 247 bool Shader::isCompiled() 248 { 249 return getShader() != 0; 250 } 251 252 void Shader::addRef() 253 { 254 mRefCount++; 255 } 256 257 void Shader::release() 258 { 259 mRefCount--; 260 261 if(mRefCount == 0 && mDeleteStatus) 262 { 263 mResourceManager->deleteShader(mHandle); 264 } 265 } 266 267 unsigned int Shader::getRefCount() const 268 { 269 return mRefCount; 270 } 271 272 bool Shader::isFlaggedForDeletion() const 273 { 274 return mDeleteStatus; 275 } 276 277 void Shader::flagForDeletion() 278 { 279 mDeleteStatus = true; 280 } 281 282 void Shader::releaseCompiler() 283 { 284 FreeCompilerGlobals(); 285 compilerInitialized = false; 286 } 287 288 // true if varying x has a higher priority in packing than y 289 bool Shader::compareVarying(const glsl::Varying &x, const glsl::Varying &y) 290 { 291 if(x.type == y.type) 292 { 293 return x.size() > y.size(); 294 } 295 296 switch(x.type) 297 { 298 case GL_FLOAT_MAT4: return true; 299 case GL_FLOAT_MAT2: 300 switch(y.type) 301 { 302 case GL_FLOAT_MAT4: return false; 303 case GL_FLOAT_MAT2: return true; 304 case GL_FLOAT_VEC4: return true; 305 case GL_FLOAT_MAT3: return true; 306 case GL_FLOAT_VEC3: return true; 307 case GL_FLOAT_VEC2: return true; 308 case GL_FLOAT: return true; 309 default: UNREACHABLE(y.type); 310 } 311 break; 312 case GL_FLOAT_VEC4: 313 switch(y.type) 314 { 315 case GL_FLOAT_MAT4: return false; 316 case GL_FLOAT_MAT2: return false; 317 case GL_FLOAT_VEC4: return true; 318 case GL_FLOAT_MAT3: return true; 319 case GL_FLOAT_VEC3: return true; 320 case GL_FLOAT_VEC2: return true; 321 case GL_FLOAT: return true; 322 default: UNREACHABLE(y.type); 323 } 324 break; 325 case GL_FLOAT_MAT3: 326 switch(y.type) 327 { 328 case GL_FLOAT_MAT4: return false; 329 case GL_FLOAT_MAT2: return false; 330 case GL_FLOAT_VEC4: return false; 331 case GL_FLOAT_MAT3: return true; 332 case GL_FLOAT_VEC3: return true; 333 case GL_FLOAT_VEC2: return true; 334 case GL_FLOAT: return true; 335 default: UNREACHABLE(y.type); 336 } 337 break; 338 case GL_FLOAT_VEC3: 339 switch(y.type) 340 { 341 case GL_FLOAT_MAT4: return false; 342 case GL_FLOAT_MAT2: return false; 343 case GL_FLOAT_VEC4: return false; 344 case GL_FLOAT_MAT3: return false; 345 case GL_FLOAT_VEC3: return true; 346 case GL_FLOAT_VEC2: return true; 347 case GL_FLOAT: return true; 348 default: UNREACHABLE(y.type); 349 } 350 break; 351 case GL_FLOAT_VEC2: 352 switch(y.type) 353 { 354 case GL_FLOAT_MAT4: return false; 355 case GL_FLOAT_MAT2: return false; 356 case GL_FLOAT_VEC4: return false; 357 case GL_FLOAT_MAT3: return false; 358 case GL_FLOAT_VEC3: return false; 359 case GL_FLOAT_VEC2: return true; 360 case GL_FLOAT: return true; 361 default: UNREACHABLE(y.type); 362 } 363 break; 364 case GL_FLOAT: return false; 365 default: UNREACHABLE(x.type); 366 } 367 368 return false; 369 } 370 371 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) 372 { 373 vertexShader = 0; 374 } 375 376 VertexShader::~VertexShader() 377 { 378 delete vertexShader; 379 } 380 381 GLenum VertexShader::getType() const 382 { 383 return GL_VERTEX_SHADER; 384 } 385 386 int VertexShader::getSemanticIndex(const std::string &attributeName) 387 { 388 if(!attributeName.empty()) 389 { 390 for(glsl::ActiveAttributes::iterator attribute = activeAttributes.begin(); attribute != activeAttributes.end(); attribute++) 391 { 392 if(attribute->name == attributeName) 393 { 394 return attribute->registerIndex; 395 } 396 } 397 } 398 399 return -1; 400 } 401 402 sw::Shader *VertexShader::getShader() const 403 { 404 return vertexShader; 405 } 406 407 sw::VertexShader *VertexShader::getVertexShader() const 408 { 409 return vertexShader; 410 } 411 412 void VertexShader::createShader() 413 { 414 delete vertexShader; 415 vertexShader = new sw::VertexShader(); 416 } 417 418 void VertexShader::deleteShader() 419 { 420 delete vertexShader; 421 vertexShader = nullptr; 422 } 423 424 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) 425 { 426 pixelShader = 0; 427 } 428 429 FragmentShader::~FragmentShader() 430 { 431 delete pixelShader; 432 } 433 434 GLenum FragmentShader::getType() const 435 { 436 return GL_FRAGMENT_SHADER; 437 } 438 439 sw::Shader *FragmentShader::getShader() const 440 { 441 return pixelShader; 442 } 443 444 sw::PixelShader *FragmentShader::getPixelShader() const 445 { 446 return pixelShader; 447 } 448 449 void FragmentShader::createShader() 450 { 451 delete pixelShader; 452 pixelShader = new sw::PixelShader(); 453 } 454 455 void FragmentShader::deleteShader() 456 { 457 delete pixelShader; 458 pixelShader = nullptr; 459 } 460 461 } 462