OSDN Git Service

fd170d1b4716e434adfed605f6aea3f0f7ac37a3
[android-x86/external-swiftshader.git] / src / Radiance / libRAD / 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. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
15
16 #include "Shader.h"
17
18 #include "main.h"
19 #include "utilities.h"
20
21 #include "GLSLANG/ShaderLang.h"
22
23 #include <string>
24
25 namespace rad
26 {
27 bool Shader::compilerInitialized = false;
28
29 Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
30 {
31     mSource = NULL;
32     mInfoLog = NULL;
33
34         clear();
35
36     mRefCount = 0;
37     mDeleteStatus = false;
38 }
39
40 Shader::~Shader()
41 {
42     delete[] mSource;
43     delete[] mInfoLog;
44 }
45
46 GLuint Shader::getHandle() const
47 {
48     return mHandle;
49 }
50
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
91 int Shader::getInfoLogLength() const
92 {
93     if(!mInfoLog)
94     {
95         return 0;
96     }
97     else
98     {
99        return strlen(mInfoLog) + 1;
100     }
101 }
102
103 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
104 {
105     int index = 0;
106
107         if(bufSize > 0)
108         {
109                 if(mInfoLog)
110                 {
111                         index = std::min(bufSize - 1, (int)strlen(mInfoLog));
112                         memcpy(infoLog, mInfoLog, index);
113                 }
114
115         infoLog[index] = '\0';
116     }
117
118     if(length)
119     {
120         *length = index;
121     }
122 }
123
124 int Shader::getSourceLength() const
125 {
126     if(!mSource)
127     {
128         return 0;
129     }
130     else
131     {
132        return strlen(mSource) + 1;
133     }
134 }
135
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
157 TranslatorASM *Shader::createCompiler(ShShaderType type)
158 {
159         if(!compilerInitialized)
160         {
161                 ShInitialize();
162                 compilerInitialized = true;
163         }
164
165         TranslatorASM *assembler = new TranslatorASM(this, type, SH_GLES2_SPEC);
166
167         ShBuiltInResources resources;
168         ShInitBuiltInResources(&resources);     
169         resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
170         resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
171         resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
172         resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
173         resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
174         resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
175         resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
176         resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
177         resources.OES_standard_derivatives = 1;
178         resources.OES_fragment_precision_high = 1;
179         resources.MaxCallStackDepth = 16;
180         assembler->Init(resources);
181
182         return assembler;
183 }
184
185 void Shader::clear()
186 {
187         delete[] mInfoLog;
188         mInfoLog = NULL;
189
190         varyings.clear();
191         activeUniforms.clear();
192         activeAttributes.clear();
193 }
194
195 bool Shader::isCompiled()
196 {
197     return getShader() != 0;
198 }
199
200 sw::PixelShader *Shader::getPixelShader() const
201 {
202         return 0;
203 }
204
205 sw::VertexShader *Shader::getVertexShader() const
206 {
207         return 0;
208 }
209
210 void Shader::addRef()
211 {
212     mRefCount++;
213 }
214
215 void Shader::release()
216 {
217     mRefCount--;
218
219     if(mRefCount == 0 && mDeleteStatus)
220     {
221         mResourceManager->deleteShader(mHandle);
222     }
223 }
224
225 unsigned int Shader::getRefCount() const
226 {
227     return mRefCount;
228 }
229
230 bool Shader::isFlaggedForDeletion() const
231 {
232     return mDeleteStatus;
233 }
234
235 void Shader::flagForDeletion()
236 {
237     mDeleteStatus = true;
238 }
239
240 void Shader::releaseCompiler()
241 {
242     ShFinalize();
243         compilerInitialized = false;
244 }
245
246 GLenum Shader::parseType(const std::string &type)
247 {
248     if(type == "float")
249     {
250         return GL_FLOAT;
251     }
252     else if(type == "float2")
253     {
254         return GL_FLOAT_VEC2;
255     }
256     else if(type == "float3")
257     {
258         return GL_FLOAT_VEC3;
259     }
260     else if(type == "float4")
261     {
262         return GL_FLOAT_VEC4;
263     }
264     else if(type == "float2x2")
265     {
266         return GL_FLOAT_MAT2;
267     }
268     else if(type == "float3x3")
269     {
270         return GL_FLOAT_MAT3;
271     }
272     else if(type == "float4x4")
273     {
274         return GL_FLOAT_MAT4;
275     }
276     else UNREACHABLE();
277
278     return GL_NONE;
279 }
280
281 // true if varying x has a higher priority in packing than y
282 bool Shader::compareVarying(const Varying &x, const Varying &y)
283 {
284     if(x.type == y.type)
285     {
286         return x.size() > y.size();
287     }
288
289     switch (x.type)
290     {
291       case GL_FLOAT_MAT4: return true;
292       case GL_FLOAT_MAT2:
293         switch(y.type)
294         {
295           case GL_FLOAT_MAT4: return false;
296           case GL_FLOAT_MAT2: return true;
297           case GL_FLOAT_VEC4: return true;
298           case GL_FLOAT_MAT3: return true;
299           case GL_FLOAT_VEC3: return true;
300           case GL_FLOAT_VEC2: return true;
301           case GL_FLOAT:      return true;
302           default: UNREACHABLE();
303         }
304         break;
305       case GL_FLOAT_VEC4:
306         switch(y.type)
307         {
308           case GL_FLOAT_MAT4: return false;
309           case GL_FLOAT_MAT2: return false;
310           case GL_FLOAT_VEC4: return true;
311           case GL_FLOAT_MAT3: return true;
312           case GL_FLOAT_VEC3: return true;
313           case GL_FLOAT_VEC2: return true;
314           case GL_FLOAT:      return true;
315           default: UNREACHABLE();
316         }
317         break;
318       case GL_FLOAT_MAT3:
319         switch(y.type)
320         {
321           case GL_FLOAT_MAT4: return false;
322           case GL_FLOAT_MAT2: return false;
323           case GL_FLOAT_VEC4: return false;
324           case GL_FLOAT_MAT3: return true;
325           case GL_FLOAT_VEC3: return true;
326           case GL_FLOAT_VEC2: return true;
327           case GL_FLOAT:      return true;
328           default: UNREACHABLE();
329         }
330         break;
331       case GL_FLOAT_VEC3:
332         switch(y.type)
333         {
334           case GL_FLOAT_MAT4: return false;
335           case GL_FLOAT_MAT2: return false;
336           case GL_FLOAT_VEC4: return false;
337           case GL_FLOAT_MAT3: return false;
338           case GL_FLOAT_VEC3: return true;
339           case GL_FLOAT_VEC2: return true;
340           case GL_FLOAT:      return true;
341           default: UNREACHABLE();
342         }
343         break;
344       case GL_FLOAT_VEC2:
345         switch(y.type)
346         {
347           case GL_FLOAT_MAT4: return false;
348           case GL_FLOAT_MAT2: return false;
349           case GL_FLOAT_VEC4: return false;
350           case GL_FLOAT_MAT3: return false;
351           case GL_FLOAT_VEC3: return false;
352           case GL_FLOAT_VEC2: return true;
353           case GL_FLOAT:      return true;
354           default: UNREACHABLE();
355         }
356         break;
357       case GL_FLOAT: return false;
358       default: UNREACHABLE();
359     }
360
361     return false;
362 }
363
364 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
365 {
366         vertexShader = 0;
367 }
368
369 VertexShader::~VertexShader()
370 {
371         delete vertexShader;
372 }
373
374 GLenum VertexShader::getType()
375 {
376     return GL_VERTEX_SHADER;
377 }
378
379 void VertexShader::compile()
380 {
381         clear();
382
383         delete vertexShader;
384         vertexShader = new sw::VertexShader();
385
386         TranslatorASM *compiler = createCompiler(SH_VERTEX_SHADER);
387
388         // Ensure we don't pass a NULL source to the compiler
389     char *source = "\0";
390         if(mSource)
391     {
392         source = mSource;
393     }
394
395         int success = ShCompile(compiler, &source, 1, SH_OBJECT_CODE);
396
397         if(false)
398         {
399                 static int serial = 1;
400                 char buffer[256];
401                 sprintf(buffer, "vertex-input-%d-%d.txt", getHandle(), serial);
402                 FILE *file = fopen(buffer, "wt");
403                 fprintf(file, mSource);
404                 fclose(file);
405                 vertexShader->print("vertex-output-%d-%d.txt", getHandle(), serial);
406                 serial++;
407         }
408
409         if(!success)
410         {
411                 delete vertexShader;
412                 vertexShader = 0;
413
414                 int infoLogLen = 0;
415         ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
416         mInfoLog = new char[infoLogLen];
417         ShGetInfoLog(compiler, mInfoLog);
418         TRACE("\n%s", mInfoLog);
419         }
420
421         delete compiler;
422 }
423
424 int VertexShader::getSemanticIndex(const std::string &attributeName)
425 {
426     if(!attributeName.empty())
427     {
428                 for(sh::ActiveAttributes::iterator attribute = activeAttributes.begin(); attribute != activeAttributes.end(); attribute++)
429         {
430             if(attribute->name == attributeName)
431             {
432                                 return attribute->registerIndex;
433             }
434         }
435     }
436
437     return -1;
438 }
439
440 sw::Shader *VertexShader::getShader() const
441 {
442         return vertexShader;
443 }
444
445 sw::VertexShader *VertexShader::getVertexShader() const
446 {
447         return vertexShader;
448 }
449
450 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
451 {
452         pixelShader = 0;
453 }
454
455 FragmentShader::~FragmentShader()
456 {
457         delete pixelShader;
458 }
459
460 GLenum FragmentShader::getType()
461 {
462     return GL_FRAGMENT_SHADER;
463 }
464
465 void FragmentShader::compile()
466 {
467         clear();
468
469         delete pixelShader;
470         pixelShader = new sw::PixelShader();
471
472         TranslatorASM *compiler = createCompiler(SH_FRAGMENT_SHADER);
473
474         // Ensure we don't pass a NULL source to the compiler
475     char *source = "\0";
476         if(mSource)
477     {
478         source = mSource;
479     }
480
481         int success = ShCompile(compiler, &source, 1, SH_OBJECT_CODE);
482         
483         if(false)
484         {
485                 static int serial = 1;
486                 char buffer[256];
487                 sprintf(buffer, "pixel-input-%d-%d.txt", getHandle(), serial);
488                 FILE *file = fopen(buffer, "wt");
489                 fprintf(file, mSource);
490                 fclose(file);
491                 pixelShader->print("pixel-output-%d-%d.txt", getHandle(), serial);
492                 serial++;
493         }
494
495         if(!success)
496         {
497                 delete pixelShader;
498                 pixelShader = 0;
499
500                 int infoLogLen = 0;
501         ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
502         mInfoLog = new char[infoLogLen];
503         ShGetInfoLog(compiler, mInfoLog);
504         TRACE("\n%s", mInfoLog);
505         }
506
507         delete compiler;
508 }
509
510 sw::Shader *FragmentShader::getShader() const
511 {
512         return pixelShader;
513 }
514
515 sw::PixelShader *FragmentShader::getPixelShader() const
516 {
517         return pixelShader;
518 }
519 }