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