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
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 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
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 int 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.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
clear()183 void Shader::clear()
184 {
185 infoLog.clear();
186
187 varyings.clear();
188 activeUniforms.clear();
189 activeAttributes.clear();
190 }
191
compile()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 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
isCompiled()231 bool Shader::isCompiled()
232 {
233 return getShader() != 0;
234 }
235
addRef()236 void Shader::addRef()
237 {
238 mRefCount++;
239 }
240
release()241 void Shader::release()
242 {
243 mRefCount--;
244
245 if(mRefCount == 0 && mDeleteStatus)
246 {
247 mResourceManager->deleteShader(mHandle);
248 }
249 }
250
getRefCount() const251 unsigned int Shader::getRefCount() const
252 {
253 return mRefCount;
254 }
255
isFlaggedForDeletion() const256 bool Shader::isFlaggedForDeletion() const
257 {
258 return mDeleteStatus;
259 }
260
flagForDeletion()261 void Shader::flagForDeletion()
262 {
263 mDeleteStatus = true;
264 }
265
releaseCompiler()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
compareVarying(const glsl::Varying & x,const glsl::Varying & 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
VertexShader(ResourceManager * manager,GLuint handle)355 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
356 {
357 vertexShader = 0;
358 }
359
~VertexShader()360 VertexShader::~VertexShader()
361 {
362 delete vertexShader;
363 }
364
getType()365 GLenum VertexShader::getType()
366 {
367 return GL_VERTEX_SHADER;
368 }
369
getSemanticIndex(const std::string & attributeName)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
getShader() const386 sw::Shader *VertexShader::getShader() const
387 {
388 return vertexShader;
389 }
390
getVertexShader() const391 sw::VertexShader *VertexShader::getVertexShader() const
392 {
393 return vertexShader;
394 }
395
createShader()396 void VertexShader::createShader()
397 {
398 delete vertexShader;
399 vertexShader = new sw::VertexShader();
400 }
401
deleteShader()402 void VertexShader::deleteShader()
403 {
404 delete vertexShader;
405 vertexShader = nullptr;
406 }
407
FragmentShader(ResourceManager * manager,GLuint handle)408 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
409 {
410 pixelShader = 0;
411 }
412
~FragmentShader()413 FragmentShader::~FragmentShader()
414 {
415 delete pixelShader;
416 }
417
getType()418 GLenum FragmentShader::getType()
419 {
420 return GL_FRAGMENT_SHADER;
421 }
422
getShader() const423 sw::Shader *FragmentShader::getShader() const
424 {
425 return pixelShader;
426 }
427
getPixelShader() const428 sw::PixelShader *FragmentShader::getPixelShader() const
429 {
430 return pixelShader;
431 }
432
createShader()433 void FragmentShader::createShader()
434 {
435 delete pixelShader;
436 pixelShader = new sw::PixelShader();
437 }
438
deleteShader()439 void FragmentShader::deleteShader()
440 {
441 delete pixelShader;
442 pixelShader = nullptr;
443 }
444
445 }
446