blob: 2b4b656ec2f82d29d54809936e04c3b7a187f24c [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
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400256 resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
shannonwoods@chromium.org74b86cf2013-05-30 00:02:58 +0000257 // GLSL ES 3.0 constants
258 resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors();
259 resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors();
260 resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
261 resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000262
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000263 mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
264 mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000265 }
266 }
267}
268
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269void Shader::releaseCompiler()
270{
271 ShDestruct(mFragmentCompiler);
272 ShDestruct(mVertexCompiler);
273
274 mFragmentCompiler = NULL;
275 mVertexCompiler = NULL;
alokp@chromium.org90033b92010-05-24 15:02:43 +0000276
277 ShFinalize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278}
279
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000280void Shader::parseVaryings()
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000281{
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000282 if (mHlsl)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000283 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000284 const char *input = strstr(mHlsl, "// Varyings") + 12;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000285
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000286 while(true)
287 {
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000288 char string1[256];
289 char string2[256];
290 char string3[256];
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000291
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000292 int matches = sscanf(input, "static %255s %255s %255s", string1, string2, string3);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000293
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000294 char *interpolation = "linear"; // Default
295 char *type = string1;
296 char *name = string2;
297
298 if (matches == 0)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000299 {
300 break;
301 }
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000302 else if (matches == 3)
303 {
304 if (string3[0] != '=') // Explicit interpolation qualifier
305 {
306 type = string2;
307 name = string3;
308 }
309 }
310 else UNREACHABLE();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000311
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000312 char *array = strstr(name, "[");
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000313 int size = 1;
314
315 if (array)
316 {
317 size = atoi(array + 1);
318 *array = '\0';
319 }
320
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000321 mVaryings.push_back(Varying(parseInterpolation(interpolation), parseType(type), name, size, array != NULL));
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000322
323 input = strstr(input, ";") + 2;
324 }
325
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000326 mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL;
327 mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL;
328 mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000329 mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
330 mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +0000331 mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
332 mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000333 mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL;
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400334 mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000335 }
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000336}
337
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000338void Shader::resetVaryingsRegisterAssignment()
339{
340 for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++)
341 {
342 var->reg = -1;
343 var->col = -1;
344 }
345}
346
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000347// initialize/clean up previous state
348void Shader::uncompile()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000350 // set by compileToHLSL
351 delete[] mHlsl;
352 mHlsl = NULL;
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000353 delete[] mInfoLog;
354 mInfoLog = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000356 // set by parseVaryings
357 mVaryings.clear();
358
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000359 mUsesMultipleRenderTargets = false;
360 mUsesFragColor = false;
361 mUsesFragData = false;
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000362 mUsesFragCoord = false;
363 mUsesFrontFacing = false;
364 mUsesPointSize = false;
365 mUsesPointCoord = false;
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000366 mUsesDepthRange = false;
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400367 mUsesFragDepth = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000368 mShaderVersion = 100;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000369
370 mActiveUniforms.clear();
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000371 mActiveInterfaceBlocks.clear();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000372}
373
374void Shader::compileToHLSL(void *compiler)
375{
376 // ensure we don't pass a NULL source to the compiler
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000377 const char *source = "\0";
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000378 if (mSource)
379 {
380 source = mSource;
381 }
382
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000383 // ensure the compiler is loaded
384 initializeCompiler();
385
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000386 int compileOptions = SH_OBJECT_CODE;
387 std::string sourcePath;
388 if (perfActive())
389 {
390 sourcePath = getTempPath();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000391 writeFile(sourcePath.c_str(), source, strlen(source));
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000392 compileOptions |= SH_LINE_DIRECTIVES;
393 }
394
395 int result;
396 if (sourcePath.empty())
397 {
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000398 result = ShCompile(compiler, &source, 1, compileOptions);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000399 }
400 else
401 {
402 const char* sourceStrings[2] =
403 {
404 sourcePath.c_str(),
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000405 source
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000406 };
407
408 result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
409 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000411 size_t shaderVersion = 100;
412 ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
413
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000414 mShaderVersion = static_cast<int>(shaderVersion);
415
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000416 if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
417 {
418 const char versionError[] = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
419 mInfoLog = new char[sizeof(versionError) + 1];
420 strcpy(mInfoLog, versionError);
421
422 TRACE("\n%s", mInfoLog);
423 }
424 else if (result)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000426 size_t objCodeLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000427 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
428 mHlsl = new char[objCodeLen];
429 ShGetObjectCode(compiler, mHlsl);
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000430
431 void *activeUniforms;
432 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
433 mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms;
shannonwoods@chromium.org3f68bf02013-05-30 00:12:43 +0000434
435 void *activeInterfaceBlocks;
436 ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks);
437 mActiveInterfaceBlocks = *(sh::ActiveInterfaceBlocks*)activeInterfaceBlocks;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000438 }
439 else
440 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000441 size_t infoLogLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000442 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
443 mInfoLog = new char[infoLogLen];
444 ShGetInfoLog(compiler, mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000445
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000446 TRACE("\n%s", mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447 }
448}
449
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000450Interpolation Shader::parseInterpolation(const std::string &type)
451{
452 if (type == "linear")
453 {
454 return Smooth;
455 }
456 else if (type == "centroid")
457 {
458 return Centroid;
459 }
460 else if (type == "nointerpolation")
461 {
462 return Flat;
463 }
464 else UNREACHABLE();
465
466 return Smooth;
467}
468
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000469GLenum Shader::parseType(const std::string &type)
470{
471 if (type == "float")
472 {
473 return GL_FLOAT;
474 }
475 else if (type == "float2")
476 {
477 return GL_FLOAT_VEC2;
478 }
479 else if (type == "float3")
480 {
481 return GL_FLOAT_VEC3;
482 }
483 else if (type == "float4")
484 {
485 return GL_FLOAT_VEC4;
486 }
487 else if (type == "float2x2")
488 {
489 return GL_FLOAT_MAT2;
490 }
491 else if (type == "float3x3")
492 {
493 return GL_FLOAT_MAT3;
494 }
495 else if (type == "float4x4")
496 {
497 return GL_FLOAT_MAT4;
498 }
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000499 else if (type == "float2x3")
500 {
501 return GL_FLOAT_MAT2x3;
502 }
503 else if (type == "float3x2")
504 {
505 return GL_FLOAT_MAT3x2;
506 }
507 else if (type == "float2x4")
508 {
509 return GL_FLOAT_MAT2x4;
510 }
511 else if (type == "float4x2")
512 {
513 return GL_FLOAT_MAT4x2;
514 }
515 else if (type == "float3x4")
516 {
517 return GL_FLOAT_MAT3x4;
518 }
519 else if (type == "float4x3")
520 {
521 return GL_FLOAT_MAT4x3;
522 }
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000523 else if (type == "int")
524 {
525 return GL_INT;
526 }
527 else if (type == "int2")
528 {
529 return GL_INT_VEC2;
530 }
531 else if (type == "int3")
532 {
533 return GL_INT_VEC3;
534 }
535 else if (type == "int4")
536 {
537 return GL_INT_VEC4;
538 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000539 else if (type == "uint")
540 {
541 return GL_UNSIGNED_INT;
542 }
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000543 else if (type == "uint2")
544 {
545 return GL_UNSIGNED_INT_VEC2;
546 }
547 else if (type == "uint3")
548 {
549 return GL_UNSIGNED_INT_VEC3;
550 }
551 else if (type == "uint4")
552 {
553 return GL_UNSIGNED_INT_VEC4;
554 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000555 else UNREACHABLE();
556
557 return GL_NONE;
558}
559
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000560typedef std::map<GLenum, int> VaryingPriorityMap;
561static VaryingPriorityMap varyingPriorities;
562
563static void makeVaryingPriorityMap()
564{
565 varyingPriorities[GL_FLOAT_MAT4] = 0;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000566 varyingPriorities[GL_FLOAT_MAT3x4] = 10;
567 varyingPriorities[GL_FLOAT_MAT4x3] = 20;
568 varyingPriorities[GL_FLOAT_MAT2x4] = 30;
569 varyingPriorities[GL_FLOAT_MAT4x2] = 40;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000570 varyingPriorities[GL_FLOAT_MAT2] = 50;
571 varyingPriorities[GL_FLOAT_VEC4] = 60;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000572 varyingPriorities[GL_INT_VEC4] = 61;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000573 varyingPriorities[GL_UNSIGNED_INT_VEC4] = 62;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000574 varyingPriorities[GL_FLOAT_MAT3] = 70;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000575 varyingPriorities[GL_FLOAT_MAT2x3] = 80;
576 varyingPriorities[GL_FLOAT_MAT3x2] = 90;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000577 varyingPriorities[GL_FLOAT_VEC3] = 100;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000578 varyingPriorities[GL_INT_VEC3] = 101;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000579 varyingPriorities[GL_UNSIGNED_INT_VEC3] = 102;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000580 varyingPriorities[GL_FLOAT_VEC2] = 110;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000581 varyingPriorities[GL_INT_VEC2] = 111;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000582 varyingPriorities[GL_UNSIGNED_INT_VEC2] = 112;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000583 varyingPriorities[GL_FLOAT] = 120;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000584 varyingPriorities[GL_INT] = 125;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000585 varyingPriorities[GL_UNSIGNED_INT] = 130;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000586}
587
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000588// true if varying x has a higher priority in packing than y
589bool Shader::compareVarying(const Varying &x, const Varying &y)
590{
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000591 if (varyingPriorities.empty())
592 {
593 makeVaryingPriorityMap();
594 }
595
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000596 if(x.type == y.type)
597 {
598 return x.size > y.size;
599 }
600
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000601 VaryingPriorityMap::iterator xPriority = varyingPriorities.find(x.type);
602 VaryingPriorityMap::iterator yPriority = varyingPriorities.find(y.type);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000603
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000604 ASSERT(xPriority != varyingPriorities.end());
605 ASSERT(yPriority != varyingPriorities.end());
606
607 return xPriority->second <= yPriority->second;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000608}
609
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000610int Shader::getShaderVersion() const
611{
612 return mShaderVersion;
613}
614
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000615VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
616 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000617{
618}
619
620VertexShader::~VertexShader()
621{
622}
623
624GLenum VertexShader::getType()
625{
626 return GL_VERTEX_SHADER;
627}
628
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000629void VertexShader::uncompile()
630{
631 Shader::uncompile();
632
633 // set by ParseAttributes
Jamie Madilldefb6742013-06-20 11:55:51 -0400634 mActiveAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000635}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000636
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637void VertexShader::compile()
638{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000639 uncompile();
640
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641 compileToHLSL(mVertexCompiler);
642 parseAttributes();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000643 parseVaryings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644}
645
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000646int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000648 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000650 int semanticIndex = 0;
Jamie Madilldefb6742013-06-20 11:55:51 -0400651 for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400653 const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
654
655 if (attribute.name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000656 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000657 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000658 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000659
Jamie Madilldefb6742013-06-20 11:55:51 -0400660 semanticIndex += AttributeRegisterCount(attribute.type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661 }
662 }
663
664 return -1;
665}
666
667void VertexShader::parseAttributes()
668{
daniel@transgaming.com2cdf8332012-02-17 18:00:50 +0000669 const char *hlsl = getHLSL();
670 if (hlsl)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000671 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400672 void *activeAttributes;
673 ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes);
674 mActiveAttributes = *(sh::ActiveShaderVariables*)activeAttributes;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000675 }
676}
677
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000678FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
679 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000680{
681}
682
683FragmentShader::~FragmentShader()
684{
685}
686
687GLenum FragmentShader::getType()
688{
689 return GL_FRAGMENT_SHADER;
690}
691
692void FragmentShader::compile()
693{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000694 uncompile();
695
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000696 compileToHLSL(mFragmentCompiler);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000697 parseVaryings();
daniel@transgaming.comcde6a612012-02-17 18:01:10 +0000698 mVaryings.sort(compareVarying);
Jamie Madill46131a32013-06-20 11:55:50 -0400699
700 const char *hlsl = getHLSL();
701 if (hlsl)
702 {
703 void *activeOutputVariables;
704 ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables);
705 mActiveOutputVariables = *(sh::ActiveShaderVariables*)activeOutputVariables;
706 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000707}
Jamie Madill46131a32013-06-20 11:55:50 -0400708
709void FragmentShader::uncompile()
710{
711 Shader::uncompile();
712
713 mActiveOutputVariables.clear();
714}
715
716const sh::ActiveShaderVariables &FragmentShader::getOutputVariables() const
717{
718 return mActiveOutputVariables;
719}
720
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000721}