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