OSDN Git Service

Centralize shader compilation.
[android-x86/external-swiftshader.git] / src / OpenGL / libGL / Shader.cpp
1 // SwiftShader Software Renderer
2 //
3 // Copyright(c) 2005-2013 TransGaming Inc.
4 //
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
6 // transcribed, stored in a retrieval system, translated into any human or computer
7 // language by any means, or disclosed to third parties without the explicit written
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9 // or implied, including but not limited to any patent rights, are granted to you.
10 //
11
12 // Shader.cpp: Implements the Shader class and its  derived classes
13 // VertexShader and FragmentShader. Implements GL shader objects and related
14 // functionality.
15
16 #include "Shader.h"
17
18 #include "main.h"
19 #include "utilities.h"
20
21 #include <string>
22
23 namespace gl
24 {
25 bool Shader::compilerInitialized = false;
26
27 Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
28 {
29     mSource = NULL;
30     mInfoLog = NULL;
31
32         clear();
33
34     mRefCount = 0;
35     mDeleteStatus = false;
36 }
37
38 Shader::~Shader()
39 {
40     delete[] mSource;
41     delete[] mInfoLog;
42 }
43
44 GLuint Shader::getName() const
45 {
46     return mHandle;
47 }
48
49 void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
50 {
51     delete[] mSource;
52     int totalLength = 0;
53
54     for(int i = 0; i < count; i++)
55     {
56         if(length && length[i] >= 0)
57         {
58             totalLength += length[i];
59         }
60         else
61         {
62             totalLength += (int)strlen(string[i]);
63         }
64     }
65
66     mSource = new char[totalLength + 1];
67     char *code = mSource;
68
69     for(int i = 0; i < count; i++)
70     {
71         int stringLength;
72
73         if(length && length[i] >= 0)
74         {
75             stringLength = length[i];
76         }
77         else
78         {
79             stringLength = (int)strlen(string[i]);
80         }
81
82         strncpy(code, string[i], stringLength);
83         code += stringLength;
84     }
85
86     mSource[totalLength] = '\0';
87 }
88
89 int Shader::getInfoLogLength() const
90 {
91     if(!mInfoLog)
92     {
93         return 0;
94     }
95     else
96     {
97        return strlen(mInfoLog) + 1;
98     }
99 }
100
101 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
102 {
103     int index = 0;
104
105         if(bufSize > 0)
106         {
107                 if(mInfoLog)
108                 {
109                         index = std::min(bufSize - 1, (int)strlen(mInfoLog));
110                         memcpy(infoLog, mInfoLog, index);
111                 }
112
113         infoLog[index] = '\0';
114     }
115
116     if(length)
117     {
118         *length = index;
119     }
120 }
121
122 int Shader::getSourceLength() const
123 {
124     if(!mSource)
125     {
126         return 0;
127     }
128     else
129     {
130        return strlen(mSource) + 1;
131     }
132 }
133
134 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
135 {
136     int index = 0;
137
138         if(bufSize > 0)
139         {
140                 if(mSource)
141                 {
142                         index = std::min(bufSize - 1, (int)strlen(mSource));
143                         memcpy(source, mSource, index);
144                 }
145
146         source[index] = '\0';
147     }
148
149     if(length)
150     {
151         *length = index;
152     }
153 }
154
155 TranslatorASM *Shader::createCompiler(GLenum shaderType)
156 {
157         if(!compilerInitialized)
158         {
159                 InitCompilerGlobals();
160                 compilerInitialized = true;
161         }
162
163         TranslatorASM *assembler = new TranslatorASM(this, shaderType);
164
165         ShBuiltInResources resources;
166         resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
167         resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
168         resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
169         resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
170         resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
171         resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
172         resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
173         resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
174         resources.OES_standard_derivatives = 1;
175         resources.OES_fragment_precision_high = 1;
176         resources.MaxCallStackDepth = 16;
177         assembler->Init(resources);
178
179         return assembler;
180 }
181
182 void Shader::clear()
183 {
184         delete[] mInfoLog;
185         mInfoLog = NULL;
186
187         varyings.clear();
188         activeUniforms.clear();
189         activeAttributes.clear();
190 }
191
192 void Shader::compile()
193 {
194         clear();
195
196         createShader();
197         TranslatorASM *compiler = createCompiler(getType());
198
199         // Ensure we don't pass a NULL 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, 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                 int infoLogLen = compiler->getInfoSink().info.size() + 1;
225         mInfoLog = new char[infoLogLen];
226         strcpy(mInfoLog, compiler->getInfoSink().info.c_str());
227         TRACE("\n%s", mInfoLog);
228         }
229
230         delete compiler;
231 }
232
233 bool Shader::isCompiled()
234 {
235     return getShader() != 0;
236 }
237
238 void Shader::addRef()
239 {
240     mRefCount++;
241 }
242
243 void Shader::release()
244 {
245     mRefCount--;
246
247     if(mRefCount == 0 && mDeleteStatus)
248     {
249         mResourceManager->deleteShader(mHandle);
250     }
251 }
252
253 unsigned int Shader::getRefCount() const
254 {
255     return mRefCount;
256 }
257
258 bool Shader::isFlaggedForDeletion() const
259 {
260     return mDeleteStatus;
261 }
262
263 void Shader::flagForDeletion()
264 {
265     mDeleteStatus = true;
266 }
267
268 void Shader::releaseCompiler()
269 {
270     FreeCompilerGlobals();
271         compilerInitialized = false;
272 }
273
274 GLenum Shader::parseType(const std::string &type)
275 {
276     if(type == "float")
277     {
278         return GL_FLOAT;
279     }
280     else if(type == "float2")
281     {
282         return GL_FLOAT_VEC2;
283     }
284     else if(type == "float3")
285     {
286         return GL_FLOAT_VEC3;
287     }
288     else if(type == "float4")
289     {
290         return GL_FLOAT_VEC4;
291     }
292     else if(type == "float2x2")
293     {
294         return GL_FLOAT_MAT2;
295     }
296     else if(type == "float3x3")
297     {
298         return GL_FLOAT_MAT3;
299     }
300     else if(type == "float4x4")
301     {
302         return GL_FLOAT_MAT4;
303     }
304     else UNREACHABLE();
305
306     return GL_NONE;
307 }
308
309 // true if varying x has a higher priority in packing than 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();
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();
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();
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();
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();
383         }
384         break;
385       case GL_FLOAT: return false;
386       default: UNREACHABLE();
387     }
388
389     return false;
390 }
391
392 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
393 {
394         vertexShader = 0;
395 }
396
397 VertexShader::~VertexShader()
398 {
399         delete vertexShader;
400 }
401
402 GLenum VertexShader::getType()
403 {
404     return GL_VERTEX_SHADER;
405 }
406
407 int VertexShader::getSemanticIndex(const std::string &attributeName)
408 {
409     if(!attributeName.empty())
410     {
411                 for(glsl::ActiveAttributes::iterator attribute = activeAttributes.begin(); attribute != activeAttributes.end(); attribute++)
412         {
413             if(attribute->name == attributeName)
414             {
415                                 return attribute->registerIndex;
416             }
417         }
418     }
419
420     return -1;
421 }
422
423 sw::Shader *VertexShader::getShader() const
424 {
425         return vertexShader;
426 }
427
428 sw::VertexShader *VertexShader::getVertexShader() const
429 {
430         return vertexShader;
431 }
432
433 void VertexShader::createShader()
434 {
435         delete vertexShader;
436         vertexShader = new sw::VertexShader();
437 }
438
439 void VertexShader::deleteShader()
440 {
441         delete vertexShader;
442         vertexShader = nullptr;
443 }
444
445 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
446 {
447         pixelShader = 0;
448 }
449
450 FragmentShader::~FragmentShader()
451 {
452         delete pixelShader;
453 }
454
455 GLenum FragmentShader::getType()
456 {
457     return GL_FRAGMENT_SHADER;
458 }
459
460 sw::Shader *FragmentShader::getShader() const
461 {
462         return pixelShader;
463 }
464
465 sw::PixelShader *FragmentShader::getPixelShader() const
466 {
467         return pixelShader;
468 }
469
470 void FragmentShader::createShader()
471 {
472         delete pixelShader;
473         pixelShader = new sw::PixelShader();
474 }
475
476 void FragmentShader::deleteShader()
477 {
478         delete pixelShader;
479         pixelShader = nullptr;
480 }
481
482 }