blob: 27ee71915ab7bec77e5c1082e822c64aa634f5aa [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002//
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +00003// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00004// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// Shader.cpp: Implements the gl::Shader class and its derived classes
9// VertexShader and FragmentShader. Implements GL shader objects and related
10// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
11
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000012#include "libGLESv2/Shader.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000013
daniel@transgaming.com29ab9522012-08-27 16:25:37 +000014#include "GLSLANG/ShaderLang.h"
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000015#include "common/utilities.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000016#include "libGLESv2/renderer/Renderer.h"
17#include "libGLESv2/Constants.h"
18#include "libGLESv2/ResourceManager.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000019
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000020namespace gl
21{
22void *Shader::mFragmentCompiler = NULL;
23void *Shader::mVertexCompiler = NULL;
24
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +000025Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
26 : mHandle(handle), mRenderer(renderer), mResourceManager(manager)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000027{
28 mSource = NULL;
29 mHlsl = NULL;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000030 mInfoLog = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031
daniel@transgaming.com938009c2012-02-17 18:02:15 +000032 uncompile();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +000033 initializeCompiler();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000035 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036 mDeleteStatus = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +000037 mShaderVersion = 100;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038}
39
40Shader::~Shader()
41{
42 delete[] mSource;
43 delete[] mHlsl;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000044 delete[] mInfoLog;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000045}
46
daniel@transgaming.com6c785212010-03-30 03:36:17 +000047GLuint Shader::getHandle() const
48{
49 return mHandle;
50}
51
shannon.woods%transgaming.com@gtempaccount.com5f339332013-04-13 03:29:02 +000052void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000053{
54 delete[] mSource;
55 int totalLength = 0;
56
57 for (int i = 0; i < count; i++)
58 {
59 if (length && length[i] >= 0)
60 {
61 totalLength += length[i];
62 }
63 else
64 {
65 totalLength += (int)strlen(string[i]);
66 }
67 }
68
69 mSource = new char[totalLength + 1];
70 char *code = mSource;
71
72 for (int i = 0; i < count; i++)
73 {
74 int stringLength;
75
76 if (length && length[i] >= 0)
77 {
78 stringLength = length[i];
79 }
80 else
81 {
82 stringLength = (int)strlen(string[i]);
83 }
84
85 strncpy(code, string[i], stringLength);
86 code += stringLength;
87 }
88
89 mSource[totalLength] = '\0';
90}
91
daniel@transgaming.comcba50572010-03-28 19:36:09 +000092int Shader::getInfoLogLength() const
93{
94 if (!mInfoLog)
95 {
96 return 0;
97 }
98 else
99 {
100 return strlen(mInfoLog) + 1;
101 }
102}
103
104void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
105{
106 int index = 0;
107
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000108 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000109 {
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000110 if (mInfoLog)
111 {
112 index = std::min(bufSize - 1, (int)strlen(mInfoLog));
113 memcpy(infoLog, mInfoLog, index);
114 }
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000115
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000116 infoLog[index] = '\0';
117 }
118
119 if (length)
120 {
121 *length = index;
122 }
123}
124
125int Shader::getSourceLength() const
126{
127 if (!mSource)
128 {
129 return 0;
130 }
131 else
132 {
133 return strlen(mSource) + 1;
134 }
135}
136
zmo@google.coma574f782011-10-03 21:45:23 +0000137int Shader::getTranslatedSourceLength() const
138{
139 if (!mHlsl)
140 {
141 return 0;
142 }
143 else
144 {
145 return strlen(mHlsl) + 1;
146 }
147}
148
149void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000150{
151 int index = 0;
152
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000153 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000154 {
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000155 if (source)
156 {
157 index = std::min(bufSize - 1, (int)strlen(source));
158 memcpy(buffer, source, index);
159 }
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000160
zmo@google.coma574f782011-10-03 21:45:23 +0000161 buffer[index] = '\0';
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000162 }
163
164 if (length)
165 {
166 *length = index;
167 }
168}
169
zmo@google.coma574f782011-10-03 21:45:23 +0000170void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer)
171{
172 getSourceImpl(mSource, bufSize, length, buffer);
173}
174
175void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
176{
177 getSourceImpl(mHlsl, bufSize, length, buffer);
178}
179
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000180const sh::ActiveUniforms &Shader::getUniforms()
181{
182 return mActiveUniforms;
183}
184
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000185const sh::ActiveInterfaceBlocks &Shader::getInterfaceBlocks()
186{
187 return mActiveInterfaceBlocks;
188}
189
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190bool Shader::isCompiled()
191{
192 return mHlsl != NULL;
193}
194
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +0000195const char *Shader::getHLSL()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000196{
197 return mHlsl;
198}
199
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000200void Shader::addRef()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000202 mRefCount++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203}
204
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000205void Shader::release()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000207 mRefCount--;
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000208
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000209 if (mRefCount == 0 && mDeleteStatus)
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000210 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000211 mResourceManager->deleteShader(mHandle);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000212 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213}
214
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000215unsigned int Shader::getRefCount() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000217 return mRefCount;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218}
219
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000220bool Shader::isFlaggedForDeletion() const
221{
222 return mDeleteStatus;
223}
224
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225void Shader::flagForDeletion()
226{
227 mDeleteStatus = true;
228}
229
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000230// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
231void Shader::initializeCompiler()
232{
233 if (!mFragmentCompiler)
234 {
235 int result = ShInitialize();
236
237 if (result)
238 {
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000239 ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
240
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000241 ShBuiltInResources resources;
242 ShInitBuiltInResources(&resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000243
244 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
shannon.woods@transgaming.com4e482042013-01-25 21:54:18 +0000245 resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000246 resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000247 resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000248 resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000249 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +0000250 resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
shannon.woods%transgaming.com@gtempaccount.come266c832013-04-13 03:31:48 +0000251 resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000252 resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport();
shannon.woods%transgaming.com@gtempaccount.come266c832013-04-13 03:31:48 +0000253 resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000254 // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
shannon.woods%transgaming.com@gtempaccount.com331192d2013-04-13 03:27:57 +0000255 resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
shannonwoods@chromium.org74b86cf2013-05-30 00:02:58 +0000256 // GLSL ES 3.0 constants
257 resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors();
258 resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors();
259 resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
260 resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000261
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000262 mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
263 mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000264 }
265 }
266}
267
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268void Shader::releaseCompiler()
269{
270 ShDestruct(mFragmentCompiler);
271 ShDestruct(mVertexCompiler);
272
273 mFragmentCompiler = NULL;
274 mVertexCompiler = NULL;
alokp@chromium.org90033b92010-05-24 15:02:43 +0000275
276 ShFinalize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277}
278
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000279void Shader::parseVaryings()
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000280{
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000281 if (mHlsl)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000282 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000283 const char *input = strstr(mHlsl, "// Varyings") + 12;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000284
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000285 while(true)
286 {
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000287 char string1[256];
288 char string2[256];
289 char string3[256];
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000290
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000291 int matches = sscanf(input, "static %255s %255s %255s", string1, string2, string3);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000292
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000293 char *interpolation = "linear"; // Default
294 char *type = string1;
295 char *name = string2;
296
297 if (matches == 0)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000298 {
299 break;
300 }
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000301 else if (matches == 3)
302 {
303 if (string3[0] != '=') // Explicit interpolation qualifier
304 {
305 type = string2;
306 name = string3;
307 }
308 }
309 else UNREACHABLE();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000310
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000311 char *array = strstr(name, "[");
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000312 int size = 1;
313
314 if (array)
315 {
316 size = atoi(array + 1);
317 *array = '\0';
318 }
319
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000320 mVaryings.push_back(Varying(parseInterpolation(interpolation), parseType(type), name, size, array != NULL));
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000321
322 input = strstr(input, ";") + 2;
323 }
324
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000325 mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL;
326 mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL;
327 mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000328 mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
329 mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +0000330 mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
331 mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000332 mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000333 }
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000334}
335
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000336void Shader::resetVaryingsRegisterAssignment()
337{
338 for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++)
339 {
340 var->reg = -1;
341 var->col = -1;
342 }
343}
344
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000345// initialize/clean up previous state
346void Shader::uncompile()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000347{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000348 // set by compileToHLSL
349 delete[] mHlsl;
350 mHlsl = NULL;
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000351 delete[] mInfoLog;
352 mInfoLog = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000354 // set by parseVaryings
355 mVaryings.clear();
356
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000357 mUsesMultipleRenderTargets = false;
358 mUsesFragColor = false;
359 mUsesFragData = false;
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000360 mUsesFragCoord = false;
361 mUsesFrontFacing = false;
362 mUsesPointSize = false;
363 mUsesPointCoord = false;
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000364 mUsesDepthRange = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000365 mShaderVersion = 100;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000366
367 mActiveUniforms.clear();
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000368 mActiveInterfaceBlocks.clear();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000369}
370
371void Shader::compileToHLSL(void *compiler)
372{
373 // ensure we don't pass a NULL source to the compiler
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000374 const char *source = "\0";
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000375 if (mSource)
376 {
377 source = mSource;
378 }
379
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000380 // ensure the compiler is loaded
381 initializeCompiler();
382
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000383 int compileOptions = SH_OBJECT_CODE;
384 std::string sourcePath;
385 if (perfActive())
386 {
387 sourcePath = getTempPath();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000388 writeFile(sourcePath.c_str(), source, strlen(source));
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000389 compileOptions |= SH_LINE_DIRECTIVES;
390 }
391
392 int result;
393 if (sourcePath.empty())
394 {
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000395 result = ShCompile(compiler, &source, 1, compileOptions);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000396 }
397 else
398 {
399 const char* sourceStrings[2] =
400 {
401 sourcePath.c_str(),
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000402 source
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000403 };
404
405 result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
406 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000408 size_t shaderVersion = 100;
409 ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
410
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000411 mShaderVersion = static_cast<int>(shaderVersion);
412
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000413 if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
414 {
415 const char versionError[] = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
416 mInfoLog = new char[sizeof(versionError) + 1];
417 strcpy(mInfoLog, versionError);
418
419 TRACE("\n%s", mInfoLog);
420 }
421 else if (result)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000422 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000423 size_t objCodeLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000424 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
425 mHlsl = new char[objCodeLen];
426 ShGetObjectCode(compiler, mHlsl);
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000427
428 void *activeUniforms;
429 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
430 mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms;
shannonwoods@chromium.org3f68bf02013-05-30 00:12:43 +0000431
432 void *activeInterfaceBlocks;
433 ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks);
434 mActiveInterfaceBlocks = *(sh::ActiveInterfaceBlocks*)activeInterfaceBlocks;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435 }
436 else
437 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000438 size_t infoLogLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000439 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
440 mInfoLog = new char[infoLogLen];
441 ShGetInfoLog(compiler, mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000442
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000443 TRACE("\n%s", mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000444 }
445}
446
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000447Interpolation Shader::parseInterpolation(const std::string &type)
448{
449 if (type == "linear")
450 {
451 return Smooth;
452 }
453 else if (type == "centroid")
454 {
455 return Centroid;
456 }
457 else if (type == "nointerpolation")
458 {
459 return Flat;
460 }
461 else UNREACHABLE();
462
463 return Smooth;
464}
465
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000466GLenum Shader::parseType(const std::string &type)
467{
468 if (type == "float")
469 {
470 return GL_FLOAT;
471 }
472 else if (type == "float2")
473 {
474 return GL_FLOAT_VEC2;
475 }
476 else if (type == "float3")
477 {
478 return GL_FLOAT_VEC3;
479 }
480 else if (type == "float4")
481 {
482 return GL_FLOAT_VEC4;
483 }
484 else if (type == "float2x2")
485 {
486 return GL_FLOAT_MAT2;
487 }
488 else if (type == "float3x3")
489 {
490 return GL_FLOAT_MAT3;
491 }
492 else if (type == "float4x4")
493 {
494 return GL_FLOAT_MAT4;
495 }
496 else UNREACHABLE();
497
498 return GL_NONE;
499}
500
501// true if varying x has a higher priority in packing than y
502bool Shader::compareVarying(const Varying &x, const Varying &y)
503{
504 if(x.type == y.type)
505 {
506 return x.size > y.size;
507 }
508
509 switch (x.type)
510 {
511 case GL_FLOAT_MAT4: return true;
512 case GL_FLOAT_MAT2:
513 switch(y.type)
514 {
515 case GL_FLOAT_MAT4: return false;
516 case GL_FLOAT_MAT2: return true;
517 case GL_FLOAT_VEC4: return true;
518 case GL_FLOAT_MAT3: return true;
519 case GL_FLOAT_VEC3: return true;
520 case GL_FLOAT_VEC2: return true;
521 case GL_FLOAT: return true;
522 default: UNREACHABLE();
523 }
524 break;
525 case GL_FLOAT_VEC4:
526 switch(y.type)
527 {
528 case GL_FLOAT_MAT4: return false;
529 case GL_FLOAT_MAT2: return false;
530 case GL_FLOAT_VEC4: return true;
531 case GL_FLOAT_MAT3: return true;
532 case GL_FLOAT_VEC3: return true;
533 case GL_FLOAT_VEC2: return true;
534 case GL_FLOAT: return true;
535 default: UNREACHABLE();
536 }
537 break;
538 case GL_FLOAT_MAT3:
539 switch(y.type)
540 {
541 case GL_FLOAT_MAT4: return false;
542 case GL_FLOAT_MAT2: return false;
543 case GL_FLOAT_VEC4: return false;
544 case GL_FLOAT_MAT3: return true;
545 case GL_FLOAT_VEC3: return true;
546 case GL_FLOAT_VEC2: return true;
547 case GL_FLOAT: return true;
548 default: UNREACHABLE();
549 }
550 break;
551 case GL_FLOAT_VEC3:
552 switch(y.type)
553 {
554 case GL_FLOAT_MAT4: return false;
555 case GL_FLOAT_MAT2: return false;
556 case GL_FLOAT_VEC4: return false;
557 case GL_FLOAT_MAT3: return false;
558 case GL_FLOAT_VEC3: return true;
559 case GL_FLOAT_VEC2: return true;
560 case GL_FLOAT: return true;
561 default: UNREACHABLE();
562 }
563 break;
564 case GL_FLOAT_VEC2:
565 switch(y.type)
566 {
567 case GL_FLOAT_MAT4: return false;
568 case GL_FLOAT_MAT2: return false;
569 case GL_FLOAT_VEC4: return false;
570 case GL_FLOAT_MAT3: return false;
571 case GL_FLOAT_VEC3: return false;
572 case GL_FLOAT_VEC2: return true;
573 case GL_FLOAT: return true;
574 default: UNREACHABLE();
575 }
576 break;
577 case GL_FLOAT: return false;
578 default: UNREACHABLE();
579 }
580
581 return false;
582}
583
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000584int Shader::getShaderVersion() const
585{
586 return mShaderVersion;
587}
588
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000589VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
590 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591{
592}
593
594VertexShader::~VertexShader()
595{
596}
597
598GLenum VertexShader::getType()
599{
600 return GL_VERTEX_SHADER;
601}
602
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000603void VertexShader::uncompile()
604{
605 Shader::uncompile();
606
607 // set by ParseAttributes
608 mAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000609}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000610
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000611void VertexShader::compile()
612{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000613 uncompile();
614
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000615 compileToHLSL(mVertexCompiler);
616 parseAttributes();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000617 parseVaryings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000618}
619
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000620int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000621{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000622 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000623 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000624 int semanticIndex = 0;
625 for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000627 if (attribute->name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000628 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000629 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000630 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000631
632 semanticIndex += VariableRowCount(attribute->type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000633 }
634 }
635
636 return -1;
637}
638
639void VertexShader::parseAttributes()
640{
daniel@transgaming.com2cdf8332012-02-17 18:00:50 +0000641 const char *hlsl = getHLSL();
642 if (hlsl)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643 {
daniel@transgaming.com2cdf8332012-02-17 18:00:50 +0000644 const char *input = strstr(hlsl, "// Attributes") + 14;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000646 while(true)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000648 char attributeType[256];
649 char attributeName[256];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000650
daniel@transgaming.com7ea933f2010-12-12 08:52:42 +0000651 int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000653 if (matches != 2)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000655 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000656 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000657
658 mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
659
660 input = strstr(input, ";") + 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661 }
662 }
663}
664
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000665FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
666 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000667{
668}
669
670FragmentShader::~FragmentShader()
671{
672}
673
674GLenum FragmentShader::getType()
675{
676 return GL_FRAGMENT_SHADER;
677}
678
679void FragmentShader::compile()
680{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000681 uncompile();
682
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000683 compileToHLSL(mFragmentCompiler);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000684 parseVaryings();
daniel@transgaming.comcde6a612012-02-17 18:01:10 +0000685 mVaryings.sort(compareVarying);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000686}
687}