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. 18 19 #include "Shader.h" 20 21 #include "main.h" 22 #include "utilities.h" 23 24 #include <string> 25 26 namespace gl 27 { 28 bool Shader::compilerInitialized = false; 29 30 Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager) 31 { 32 mSource = nullptr; 33 34 clear(); 35 36 mRefCount = 0; 37 mDeleteStatus = false; 38 } 39 40 Shader::~Shader() 41 { 42 delete[] mSource; 43 } 44 45 GLuint Shader::getName() const 46 { 47 return mHandle; 48 } 49 50 void Shader::setSource(GLsizei count, const char *const *string, const GLint *length) 51 { 52 delete[] mSource; 53 int totalLength = 0; 54 55 for(int i = 0; i < count; i++) 56 { 57 if(length && length[i] >= 0) 58 { 59 totalLength += length[i]; 60 } 61 else 62 { 63 totalLength += (int)strlen(string[i]); 64 } 65 } 66 67 mSource = new char[totalLength + 1]; 68 char *code = mSource; 69 70 for(int i = 0; i < count; i++) 71 { 72 int stringLength; 73 74 if(length && length[i] >= 0) 75 { 76 stringLength = length[i]; 77 } 78 else 79 { 80 stringLength = (int)strlen(string[i]); 81 } 82 83 strncpy(code, string[i], stringLength); 84 code += stringLength; 85 } 86 87 mSource[totalLength] = '\0'; 88 } 89 90 int Shader::getInfoLogLength() const 91 { 92 if(infoLog.empty()) 93 { 94 return 0; 95 } 96 else 97 { 98 return infoLog.size() + 1; 99 } 100 } 101 102 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLogOut) 103 { 104 int index = 0; 105 106 if(bufSize > 0) 107 { 108 if(!infoLog.empty()) 109 { 110 index = std::min(bufSize - 1, (GLsizei)infoLog.size()); 111 memcpy(infoLogOut, infoLog.c_str(), index); 112 } 113 114 infoLogOut[index] = '\0'; 115 } 116 117 if(length) 118 { 119 *length = index; 120 } 121 } 122 123 int Shader::getSourceLength() const 124 { 125 if(!mSource) 126 { 127 return 0; 128 } 129 else 130 { 131 return strlen(mSource) + 1; 132 } 133 } 134 135 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source) 136 { 137 int index = 0; 138 139 if(bufSize > 0) 140 { 141 if(mSource) 142 { 143 index = std::min(bufSize - 1, (int)strlen(mSource)); 144 memcpy(source, mSource, index); 145 } 146 147 source[index] = '\0'; 148 } 149 150 if(length) 151 { 152 *length = index; 153 } 154 } 155 156 TranslatorASM *Shader::createCompiler(GLenum shaderType) 157 { 158 if(!compilerInitialized) 159 { 160 InitCompilerGlobals(); 161 compilerInitialized = true; 162 } 163 164 TranslatorASM *assembler = new TranslatorASM(this, shaderType); 165 166 ShBuiltInResources resources; 167 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; 168 resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS; 169 resources.MaxVaryingVectors = MAX_VARYING_VECTORS; 170 resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS; 171 resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS; 172 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; 173 resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS; 174 resources.MaxDrawBuffers = MAX_DRAW_BUFFERS; 175 resources.OES_standard_derivatives = 1; 176 resources.OES_fragment_precision_high = 1; 177 resources.MaxCallStackDepth = 16; 178 assembler->Init(resources); 179 180 return assembler; 181 } 182 183 void Shader::clear() 184 { 185 infoLog.clear(); 186 187 varyings.clear(); 188 activeUniforms.clear(); 189 activeAttributes.clear(); 190 } 191 192 void Shader::compile() 193 { 194 clear(); 195 196 createShader(); 197 TranslatorASM *compiler = createCompiler(getType()); 198 199 // Ensure we don't pass a nullptr source to the compiler 200 const char *source = "\0"; 201 if(mSource) 202 { 203 source = mSource; 204 } 205 206 bool success = compiler->compile(&source, 1, SH_OBJECT_CODE); 207 208 if(false) 209 { 210 static int serial = 1; 211 char buffer[256]; 212 sprintf(buffer, "shader-input-%d-%d.txt", getName(), serial); 213 FILE *file = fopen(buffer, "wt"); 214 fprintf(file, "%s", mSource); 215 fclose(file); 216 getShader()->print("shader-output-%d-%d.txt", getName(), serial); 217 serial++; 218 } 219 220 if(!success) 221 { 222 deleteShader(); 223 224 infoLog = compiler->getInfoSink().info.c_str(); 225 TRACE("\n%s", infoLog.c_str()); 226 } 227 228 delete compiler; 229 } 230 231 bool Shader::isCompiled() 232 { 233 return getShader() != 0; 234 } 235 236 void Shader::addRef() 237 { 238 mRefCount++; 239 } 240 241 void Shader::release() 242 { 243 mRefCount--; 244 245 if(mRefCount == 0 && mDeleteStatus) 246 { 247 mResourceManager->deleteShader(mHandle); 248 } 249 } 250 251 unsigned int Shader::getRefCount() const 252 { 253 return mRefCount; 254 } 255 256 bool Shader::isFlaggedForDeletion() const 257 { 258 return mDeleteStatus; 259 } 260 261 void Shader::flagForDeletion() 262 { 263 mDeleteStatus = true; 264 } 265 266 void Shader::releaseCompiler() 267 { 268 FreeCompilerGlobals(); 269 compilerInitialized = false; 270 } 271 272 // true if varying x has a higher priority in packing than y 273 bool Shader::compareVarying(const glsl::Varying &x, const glsl::Varying &y) 274 { 275 if(x.type == y.type) 276 { 277 return x.size() > y.size(); 278 } 279 280 switch(x.type) 281 { 282 case GL_FLOAT_MAT4: return true; 283 case GL_FLOAT_MAT2: 284 switch(y.type) 285 { 286 case GL_FLOAT_MAT4: return false; 287 case GL_FLOAT_MAT2: return true; 288 case GL_FLOAT_VEC4: return true; 289 case GL_FLOAT_MAT3: return true; 290 case GL_FLOAT_VEC3: return true; 291 case GL_FLOAT_VEC2: return true; 292 case GL_FLOAT: return true; 293 default: UNREACHABLE(y.type); 294 } 295 break; 296 case GL_FLOAT_VEC4: 297 switch(y.type) 298 { 299 case GL_FLOAT_MAT4: return false; 300 case GL_FLOAT_MAT2: return false; 301 case GL_FLOAT_VEC4: return true; 302 case GL_FLOAT_MAT3: return true; 303 case GL_FLOAT_VEC3: return true; 304 case GL_FLOAT_VEC2: return true; 305 case GL_FLOAT: return true; 306 default: UNREACHABLE(y.type); 307 } 308 break; 309 case GL_FLOAT_MAT3: 310 switch(y.type) 311 { 312 case GL_FLOAT_MAT4: return false; 313 case GL_FLOAT_MAT2: return false; 314 case GL_FLOAT_VEC4: return false; 315 case GL_FLOAT_MAT3: return true; 316 case GL_FLOAT_VEC3: return true; 317 case GL_FLOAT_VEC2: return true; 318 case GL_FLOAT: return true; 319 default: UNREACHABLE(y.type); 320 } 321 break; 322 case GL_FLOAT_VEC3: 323 switch(y.type) 324 { 325 case GL_FLOAT_MAT4: return false; 326 case GL_FLOAT_MAT2: return false; 327 case GL_FLOAT_VEC4: return false; 328 case GL_FLOAT_MAT3: return false; 329 case GL_FLOAT_VEC3: return true; 330 case GL_FLOAT_VEC2: return true; 331 case GL_FLOAT: return true; 332 default: UNREACHABLE(y.type); 333 } 334 break; 335 case GL_FLOAT_VEC2: 336 switch(y.type) 337 { 338 case GL_FLOAT_MAT4: return false; 339 case GL_FLOAT_MAT2: return false; 340 case GL_FLOAT_VEC4: return false; 341 case GL_FLOAT_MAT3: return false; 342 case GL_FLOAT_VEC3: return false; 343 case GL_FLOAT_VEC2: return true; 344 case GL_FLOAT: return true; 345 default: UNREACHABLE(y.type); 346 } 347 break; 348 case GL_FLOAT: return false; 349 default: UNREACHABLE(x.type); 350 } 351 352 return false; 353 } 354 355 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) 356 { 357 vertexShader = 0; 358 } 359 360 VertexShader::~VertexShader() 361 { 362 delete vertexShader; 363 } 364 365 GLenum VertexShader::getType() 366 { 367 return GL_VERTEX_SHADER; 368 } 369 370 int VertexShader::getSemanticIndex(const std::string &attributeName) 371 { 372 if(!attributeName.empty()) 373 { 374 for(glsl::ActiveAttributes::iterator attribute = activeAttributes.begin(); attribute != activeAttributes.end(); attribute++) 375 { 376 if(attribute->name == attributeName) 377 { 378 return attribute->registerIndex; 379 } 380 } 381 } 382 383 return -1; 384 } 385 386 sw::Shader *VertexShader::getShader() const 387 { 388 return vertexShader; 389 } 390 391 sw::VertexShader *VertexShader::getVertexShader() const 392 { 393 return vertexShader; 394 } 395 396 void VertexShader::createShader() 397 { 398 delete vertexShader; 399 vertexShader = new sw::VertexShader(); 400 } 401 402 void VertexShader::deleteShader() 403 { 404 delete vertexShader; 405 vertexShader = nullptr; 406 } 407 408 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) 409 { 410 pixelShader = 0; 411 } 412 413 FragmentShader::~FragmentShader() 414 { 415 delete pixelShader; 416 } 417 418 GLenum FragmentShader::getType() 419 { 420 return GL_FRAGMENT_SHADER; 421 } 422 423 sw::Shader *FragmentShader::getShader() const 424 { 425 return pixelShader; 426 } 427 428 sw::PixelShader *FragmentShader::getPixelShader() const 429 { 430 return pixelShader; 431 } 432 433 void FragmentShader::createShader() 434 { 435 delete pixelShader; 436 pixelShader = new sw::PixelShader(); 437 } 438 439 void FragmentShader::deleteShader() 440 { 441 delete pixelShader; 442 pixelShader = nullptr; 443 } 444 445 } 446