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
Shader(ResourceManager * manager,GLuint handle)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
~Shader()41 Shader::~Shader()
42 {
43 delete[] mSource;
44 }
45
getName() const46 GLuint Shader::getName() const
47 {
48 return mHandle;
49 }
50
setSource(GLsizei count,const char * const * string,const GLint * length)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
getInfoLogLength() const91 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
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLogOut)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
getSourceLength() const124 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
getSource(GLsizei bufSize,GLsizei * length,char * source)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
createCompiler(GLenum shaderType)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.ARB_texture_rectangle = 1;
185 resources.MaxCallStackDepth = 64;
186 assembler->Init(resources);
187
188 return assembler;
189 }
190
clear()191 void Shader::clear()
192 {
193 infoLog.clear();
194
195 varyings.clear();
196 activeUniforms.clear();
197 activeAttributes.clear();
198 }
199
compile()200 void Shader::compile()
201 {
202 clear();
203
204 createShader();
205 TranslatorASM *compiler = createCompiler(getType());
206
207 // Ensure we don't pass a nullptr source to the compiler
208 const char *source = "\0";
209 if(mSource)
210 {
211 source = mSource;
212 }
213
214 bool success = compiler->compile(&source, 1, SH_OBJECT_CODE);
215
216 if(false)
217 {
218 static int serial = 1;
219
220 if(false)
221 {
222 char buffer[256];
223 sprintf(buffer, "shader-input-%d-%d.txt", getName(), serial);
224 FILE *file = fopen(buffer, "wt");
225 fprintf(file, "%s", mSource);
226 fclose(file);
227 }
228
229 getShader()->print("shader-output-%d-%d.txt", getName(), serial);
230
231 serial++;
232 }
233
234 shaderVersion = compiler->getShaderVersion();
235 int clientVersion = es2::getContext()->getClientVersion();
236
237 if(shaderVersion >= 300 && clientVersion < 3)
238 {
239 infoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
240 success = false;
241 }
242
243 if(!success)
244 {
245 deleteShader();
246
247 infoLog += compiler->getInfoSink().info.c_str();
248 TRACE("\n%s", infoLog.c_str());
249 }
250
251 delete compiler;
252 }
253
isCompiled()254 bool Shader::isCompiled()
255 {
256 return getShader() != 0;
257 }
258
addRef()259 void Shader::addRef()
260 {
261 mRefCount++;
262 }
263
release()264 void Shader::release()
265 {
266 mRefCount--;
267
268 if(mRefCount == 0 && mDeleteStatus)
269 {
270 mResourceManager->deleteShader(mHandle);
271 }
272 }
273
getRefCount() const274 unsigned int Shader::getRefCount() const
275 {
276 return mRefCount;
277 }
278
isFlaggedForDeletion() const279 bool Shader::isFlaggedForDeletion() const
280 {
281 return mDeleteStatus;
282 }
283
flagForDeletion()284 void Shader::flagForDeletion()
285 {
286 mDeleteStatus = true;
287 }
288
releaseCompiler()289 void Shader::releaseCompiler()
290 {
291 FreeCompilerGlobals();
292 compilerInitialized = false;
293 }
294
295 // true if varying x has a higher priority in packing than y
compareVarying(const glsl::Varying & x,const glsl::Varying & y)296 bool Shader::compareVarying(const glsl::Varying &x, const glsl::Varying &y)
297 {
298 if(x.type == y.type)
299 {
300 return x.size() > y.size();
301 }
302
303 switch(x.type)
304 {
305 case GL_FLOAT_MAT4: return true;
306 case GL_FLOAT_MAT2:
307 switch(y.type)
308 {
309 case GL_FLOAT_MAT4: return false;
310 case GL_FLOAT_MAT2: return true;
311 case GL_FLOAT_VEC4: return true;
312 case GL_FLOAT_MAT3: return true;
313 case GL_FLOAT_VEC3: return true;
314 case GL_FLOAT_VEC2: return true;
315 case GL_FLOAT: return true;
316 default: UNREACHABLE(y.type);
317 }
318 break;
319 case GL_FLOAT_VEC4:
320 switch(y.type)
321 {
322 case GL_FLOAT_MAT4: return false;
323 case GL_FLOAT_MAT2: return false;
324 case GL_FLOAT_VEC4: return true;
325 case GL_FLOAT_MAT3: return true;
326 case GL_FLOAT_VEC3: return true;
327 case GL_FLOAT_VEC2: return true;
328 case GL_FLOAT: return true;
329 default: UNREACHABLE(y.type);
330 }
331 break;
332 case GL_FLOAT_MAT3:
333 switch(y.type)
334 {
335 case GL_FLOAT_MAT4: return false;
336 case GL_FLOAT_MAT2: return false;
337 case GL_FLOAT_VEC4: return false;
338 case GL_FLOAT_MAT3: return true;
339 case GL_FLOAT_VEC3: return true;
340 case GL_FLOAT_VEC2: return true;
341 case GL_FLOAT: return true;
342 default: UNREACHABLE(y.type);
343 }
344 break;
345 case GL_FLOAT_VEC3:
346 switch(y.type)
347 {
348 case GL_FLOAT_MAT4: return false;
349 case GL_FLOAT_MAT2: return false;
350 case GL_FLOAT_VEC4: return false;
351 case GL_FLOAT_MAT3: return false;
352 case GL_FLOAT_VEC3: return true;
353 case GL_FLOAT_VEC2: return true;
354 case GL_FLOAT: return true;
355 default: UNREACHABLE(y.type);
356 }
357 break;
358 case GL_FLOAT_VEC2:
359 switch(y.type)
360 {
361 case GL_FLOAT_MAT4: return false;
362 case GL_FLOAT_MAT2: return false;
363 case GL_FLOAT_VEC4: return false;
364 case GL_FLOAT_MAT3: return false;
365 case GL_FLOAT_VEC3: return false;
366 case GL_FLOAT_VEC2: return true;
367 case GL_FLOAT: return true;
368 default: UNREACHABLE(y.type);
369 }
370 break;
371 case GL_FLOAT: return false;
372 default: UNREACHABLE(x.type);
373 }
374
375 return false;
376 }
377
VertexShader(ResourceManager * manager,GLuint handle)378 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
379 {
380 vertexShader = 0;
381 }
382
~VertexShader()383 VertexShader::~VertexShader()
384 {
385 delete vertexShader;
386 }
387
getType() const388 GLenum VertexShader::getType() const
389 {
390 return GL_VERTEX_SHADER;
391 }
392
getSemanticIndex(const std::string & attributeName) const393 int VertexShader::getSemanticIndex(const std::string &attributeName) const
394 {
395 if(!attributeName.empty())
396 {
397 for(const auto &attribute : activeAttributes)
398 {
399 if(attribute.name == attributeName)
400 {
401 return attribute.registerIndex;
402 }
403 }
404 }
405
406 return -1;
407 }
408
getShader() const409 sw::Shader *VertexShader::getShader() const
410 {
411 return vertexShader;
412 }
413
getVertexShader() const414 sw::VertexShader *VertexShader::getVertexShader() const
415 {
416 return vertexShader;
417 }
418
createShader()419 void VertexShader::createShader()
420 {
421 delete vertexShader;
422 vertexShader = new sw::VertexShader();
423 }
424
deleteShader()425 void VertexShader::deleteShader()
426 {
427 delete vertexShader;
428 vertexShader = nullptr;
429 }
430
FragmentShader(ResourceManager * manager,GLuint handle)431 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
432 {
433 pixelShader = 0;
434 }
435
~FragmentShader()436 FragmentShader::~FragmentShader()
437 {
438 delete pixelShader;
439 }
440
getType() const441 GLenum FragmentShader::getType() const
442 {
443 return GL_FRAGMENT_SHADER;
444 }
445
getShader() const446 sw::Shader *FragmentShader::getShader() const
447 {
448 return pixelShader;
449 }
450
getPixelShader() const451 sw::PixelShader *FragmentShader::getPixelShader() const
452 {
453 return pixelShader;
454 }
455
createShader()456 void FragmentShader::createShader()
457 {
458 delete pixelShader;
459 pixelShader = new sw::PixelShader();
460 }
461
deleteShader()462 void FragmentShader::deleteShader()
463 {
464 delete pixelShader;
465 pixelShader = nullptr;
466 }
467
468 }
469