blob: 5329e6fc2ac69c142c006f48ff92607f6f577f3c [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 }
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000496 else if (type == "float2x3")
497 {
498 return GL_FLOAT_MAT2x3;
499 }
500 else if (type == "float3x2")
501 {
502 return GL_FLOAT_MAT3x2;
503 }
504 else if (type == "float2x4")
505 {
506 return GL_FLOAT_MAT2x4;
507 }
508 else if (type == "float4x2")
509 {
510 return GL_FLOAT_MAT4x2;
511 }
512 else if (type == "float3x4")
513 {
514 return GL_FLOAT_MAT3x4;
515 }
516 else if (type == "float4x3")
517 {
518 return GL_FLOAT_MAT4x3;
519 }
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000520 else if (type == "int")
521 {
522 return GL_INT;
523 }
524 else if (type == "int2")
525 {
526 return GL_INT_VEC2;
527 }
528 else if (type == "int3")
529 {
530 return GL_INT_VEC3;
531 }
532 else if (type == "int4")
533 {
534 return GL_INT_VEC4;
535 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000536 else if (type == "uint")
537 {
538 return GL_UNSIGNED_INT;
539 }
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000540 else if (type == "uint2")
541 {
542 return GL_UNSIGNED_INT_VEC2;
543 }
544 else if (type == "uint3")
545 {
546 return GL_UNSIGNED_INT_VEC3;
547 }
548 else if (type == "uint4")
549 {
550 return GL_UNSIGNED_INT_VEC4;
551 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000552 else UNREACHABLE();
553
554 return GL_NONE;
555}
556
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000557typedef std::map<GLenum, int> VaryingPriorityMap;
558static VaryingPriorityMap varyingPriorities;
559
560static void makeVaryingPriorityMap()
561{
562 varyingPriorities[GL_FLOAT_MAT4] = 0;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000563 varyingPriorities[GL_FLOAT_MAT3x4] = 10;
564 varyingPriorities[GL_FLOAT_MAT4x3] = 20;
565 varyingPriorities[GL_FLOAT_MAT2x4] = 30;
566 varyingPriorities[GL_FLOAT_MAT4x2] = 40;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000567 varyingPriorities[GL_FLOAT_MAT2] = 50;
568 varyingPriorities[GL_FLOAT_VEC4] = 60;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000569 varyingPriorities[GL_INT_VEC4] = 61;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000570 varyingPriorities[GL_UNSIGNED_INT_VEC4] = 62;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000571 varyingPriorities[GL_FLOAT_MAT3] = 70;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000572 varyingPriorities[GL_FLOAT_MAT2x3] = 80;
573 varyingPriorities[GL_FLOAT_MAT3x2] = 90;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000574 varyingPriorities[GL_FLOAT_VEC3] = 100;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000575 varyingPriorities[GL_INT_VEC3] = 101;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000576 varyingPriorities[GL_UNSIGNED_INT_VEC3] = 102;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000577 varyingPriorities[GL_FLOAT_VEC2] = 110;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000578 varyingPriorities[GL_INT_VEC2] = 111;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000579 varyingPriorities[GL_UNSIGNED_INT_VEC2] = 112;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000580 varyingPriorities[GL_FLOAT] = 120;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000581 varyingPriorities[GL_INT] = 125;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000582 varyingPriorities[GL_UNSIGNED_INT] = 130;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000583}
584
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000585// true if varying x has a higher priority in packing than y
586bool Shader::compareVarying(const Varying &x, const Varying &y)
587{
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000588 if (varyingPriorities.empty())
589 {
590 makeVaryingPriorityMap();
591 }
592
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000593 if(x.type == y.type)
594 {
595 return x.size > y.size;
596 }
597
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000598 VaryingPriorityMap::iterator xPriority = varyingPriorities.find(x.type);
599 VaryingPriorityMap::iterator yPriority = varyingPriorities.find(y.type);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000600
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000601 ASSERT(xPriority != varyingPriorities.end());
602 ASSERT(yPriority != varyingPriorities.end());
603
604 return xPriority->second <= yPriority->second;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000605}
606
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000607int Shader::getShaderVersion() const
608{
609 return mShaderVersion;
610}
611
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000612VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
613 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000614{
615}
616
617VertexShader::~VertexShader()
618{
619}
620
621GLenum VertexShader::getType()
622{
623 return GL_VERTEX_SHADER;
624}
625
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000626void VertexShader::uncompile()
627{
628 Shader::uncompile();
629
630 // set by ParseAttributes
631 mAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000632}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000633
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000634void VertexShader::compile()
635{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000636 uncompile();
637
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000638 compileToHLSL(mVertexCompiler);
639 parseAttributes();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000640 parseVaryings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641}
642
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000643int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000645 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000647 int semanticIndex = 0;
648 for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000650 if (attribute->name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000652 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000654
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000655 semanticIndex += AttributeRegisterCount(attribute->type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000656 }
657 }
658
659 return -1;
660}
661
662void VertexShader::parseAttributes()
663{
daniel@transgaming.com2cdf8332012-02-17 18:00:50 +0000664 const char *hlsl = getHLSL();
665 if (hlsl)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000666 {
daniel@transgaming.com2cdf8332012-02-17 18:00:50 +0000667 const char *input = strstr(hlsl, "// Attributes") + 14;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000669 while(true)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000670 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000671 char attributeType[256];
672 char attributeName[256];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000673
daniel@transgaming.com7ea933f2010-12-12 08:52:42 +0000674 int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000675
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000676 if (matches != 2)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000677 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000678 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000679 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000680
681 mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
682
683 input = strstr(input, ";") + 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000684 }
685 }
686}
687
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000688FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
689 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000690{
691}
692
693FragmentShader::~FragmentShader()
694{
695}
696
697GLenum FragmentShader::getType()
698{
699 return GL_FRAGMENT_SHADER;
700}
701
702void FragmentShader::compile()
703{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000704 uncompile();
705
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000706 compileToHLSL(mFragmentCompiler);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000707 parseVaryings();
daniel@transgaming.comcde6a612012-02-17 18:01:10 +0000708 mVaryings.sort(compareVarying);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000709}
710}