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