blob: a8a0ce18a1a0890ae53b85af9e2ec670d9f6ee88 [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{
daniel@transgaming.com938009c2012-02-17 18:02:15 +000028 uncompile();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +000029 initializeCompiler();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000031 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032 mDeleteStatus = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +000033 mShaderVersion = 100;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034}
35
36Shader::~Shader()
37{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038}
39
daniel@transgaming.com6c785212010-03-30 03:36:17 +000040GLuint Shader::getHandle() const
41{
42 return mHandle;
43}
44
shannon.woods%transgaming.com@gtempaccount.com5f339332013-04-13 03:29:02 +000045void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000046{
Geoff Lang536d7262013-08-26 17:04:20 -040047 std::ostringstream stream;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000048
49 for (int i = 0; i < count; i++)
50 {
Geoff Lang536d7262013-08-26 17:04:20 -040051 stream << string[i];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000052 }
53
Geoff Lang536d7262013-08-26 17:04:20 -040054 mSource = stream.str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055}
56
daniel@transgaming.comcba50572010-03-28 19:36:09 +000057int Shader::getInfoLogLength() const
58{
Geoff Lang536d7262013-08-26 17:04:20 -040059 return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1);
daniel@transgaming.comcba50572010-03-28 19:36:09 +000060}
61
Geoff Lang536d7262013-08-26 17:04:20 -040062void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
daniel@transgaming.comcba50572010-03-28 19:36:09 +000063{
64 int index = 0;
65
daniel@transgaming.com807d8c32012-04-04 15:06:04 +000066 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +000067 {
Geoff Lang536d7262013-08-26 17:04:20 -040068 index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
69 memcpy(infoLog, mInfoLog.c_str(), index);
daniel@transgaming.comcba50572010-03-28 19:36:09 +000070
daniel@transgaming.comcba50572010-03-28 19:36:09 +000071 infoLog[index] = '\0';
72 }
73
74 if (length)
75 {
76 *length = index;
77 }
78}
79
80int Shader::getSourceLength() const
81{
Geoff Lang536d7262013-08-26 17:04:20 -040082 return mSource.empty() ? 0 : (mSource.length() + 1);
daniel@transgaming.comcba50572010-03-28 19:36:09 +000083}
84
zmo@google.coma574f782011-10-03 21:45:23 +000085int Shader::getTranslatedSourceLength() const
86{
Geoff Lang536d7262013-08-26 17:04:20 -040087 return mHlsl.empty() ? 0 : (mHlsl.length() + 1);
zmo@google.coma574f782011-10-03 21:45:23 +000088}
89
Geoff Lang536d7262013-08-26 17:04:20 -040090void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const
daniel@transgaming.comcba50572010-03-28 19:36:09 +000091{
92 int index = 0;
93
daniel@transgaming.com807d8c32012-04-04 15:06:04 +000094 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +000095 {
Geoff Lang536d7262013-08-26 17:04:20 -040096 index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
97 memcpy(buffer, source.c_str(), index);
daniel@transgaming.comcba50572010-03-28 19:36:09 +000098
zmo@google.coma574f782011-10-03 21:45:23 +000099 buffer[index] = '\0';
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000100 }
101
102 if (length)
103 {
104 *length = index;
105 }
106}
107
Geoff Lang536d7262013-08-26 17:04:20 -0400108void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
zmo@google.coma574f782011-10-03 21:45:23 +0000109{
110 getSourceImpl(mSource, bufSize, length, buffer);
111}
112
Geoff Lang536d7262013-08-26 17:04:20 -0400113void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
zmo@google.coma574f782011-10-03 21:45:23 +0000114{
115 getSourceImpl(mHlsl, bufSize, length, buffer);
116}
117
Geoff Lang536d7262013-08-26 17:04:20 -0400118const sh::ActiveUniforms &Shader::getUniforms() const
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000119{
120 return mActiveUniforms;
121}
122
Geoff Lang536d7262013-08-26 17:04:20 -0400123const sh::ActiveInterfaceBlocks &Shader::getInterfaceBlocks() const
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000124{
125 return mActiveInterfaceBlocks;
126}
127
Geoff Lang536d7262013-08-26 17:04:20 -0400128bool Shader::isCompiled() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129{
Geoff Lang536d7262013-08-26 17:04:20 -0400130 return !mHlsl.empty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131}
132
Geoff Lang536d7262013-08-26 17:04:20 -0400133const std::string &Shader::getHLSL() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134{
135 return mHlsl;
136}
137
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000138void Shader::addRef()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000140 mRefCount++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141}
142
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000143void Shader::release()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000145 mRefCount--;
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000146
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000147 if (mRefCount == 0 && mDeleteStatus)
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000148 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000149 mResourceManager->deleteShader(mHandle);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000150 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151}
152
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000153unsigned int Shader::getRefCount() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000155 return mRefCount;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000158bool Shader::isFlaggedForDeletion() const
159{
160 return mDeleteStatus;
161}
162
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163void Shader::flagForDeletion()
164{
165 mDeleteStatus = true;
166}
167
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000168// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
169void Shader::initializeCompiler()
170{
171 if (!mFragmentCompiler)
172 {
173 int result = ShInitialize();
174
175 if (result)
176 {
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000177 ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
178
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000179 ShBuiltInResources resources;
180 ShInitBuiltInResources(&resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000181
182 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
shannon.woods@transgaming.com4e482042013-01-25 21:54:18 +0000183 resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000184 resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000185 resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000186 resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000187 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +0000188 resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
shannon.woods%transgaming.com@gtempaccount.come266c832013-04-13 03:31:48 +0000189 resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000190 resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport();
shannon.woods%transgaming.com@gtempaccount.come266c832013-04-13 03:31:48 +0000191 resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000192 // 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 +0000193 resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400194 resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
shannonwoods@chromium.org74b86cf2013-05-30 00:02:58 +0000195 // GLSL ES 3.0 constants
196 resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors();
197 resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors();
198 resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
199 resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000200
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000201 mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
202 mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000203 }
204 }
205}
206
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207void Shader::releaseCompiler()
208{
209 ShDestruct(mFragmentCompiler);
210 ShDestruct(mVertexCompiler);
211
212 mFragmentCompiler = NULL;
213 mVertexCompiler = NULL;
alokp@chromium.org90033b92010-05-24 15:02:43 +0000214
215 ShFinalize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216}
217
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000218void Shader::parseVaryings()
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000219{
Geoff Lang536d7262013-08-26 17:04:20 -0400220 if (!mHlsl.empty())
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000221 {
Geoff Lang536d7262013-08-26 17:04:20 -0400222 const std::string varyingsTitle("// Varyings");
223 size_t input = mHlsl.find(varyingsTitle);
224 if (input != std::string::npos)
225 {
226 input += varyingsTitle.length() + 1;
227 }
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000228
Geoff Lang536d7262013-08-26 17:04:20 -0400229 while(input != std::string::npos)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000230 {
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000231 char string1[256];
232 char string2[256];
233 char string3[256];
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000234
Geoff Lang536d7262013-08-26 17:04:20 -0400235 int matches = sscanf(mHlsl.c_str() + input, "static %255s %255s %255s", string1, string2, string3);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000236
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000237 char *interpolation = "linear"; // Default
238 char *type = string1;
239 char *name = string2;
240
241 if (matches == 0)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000242 {
243 break;
244 }
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000245 else if (matches == 3)
246 {
247 if (string3[0] != '=') // Explicit interpolation qualifier
248 {
249 type = string2;
250 name = string3;
251 }
252 }
253 else UNREACHABLE();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000254
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000255 char *array = strstr(name, "[");
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000256 int size = 1;
257
258 if (array)
259 {
260 size = atoi(array + 1);
261 *array = '\0';
262 }
263
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000264 mVaryings.push_back(Varying(parseInterpolation(interpolation), parseType(type), name, size, array != NULL));
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000265
Geoff Lang536d7262013-08-26 17:04:20 -0400266 const std::string semiColon(";");
267 input = mHlsl.find(semiColon, input);
268 if (input != std::string::npos)
269 {
270 input += semiColon.length() + 1;
271 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000272 }
273
Geoff Lang536d7262013-08-26 17:04:20 -0400274 mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos;
275 mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos;
276 mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos;
277 mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos;
278 mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
279 mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos;
280 mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos;
281 mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos;
282 mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000283 }
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000284}
285
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000286void Shader::resetVaryingsRegisterAssignment()
287{
288 for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++)
289 {
290 var->reg = -1;
291 var->col = -1;
292 }
293}
294
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000295// initialize/clean up previous state
296void Shader::uncompile()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000298 // set by compileToHLSL
Geoff Lang536d7262013-08-26 17:04:20 -0400299 mHlsl.clear();
300 mInfoLog.clear();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000302 // set by parseVaryings
303 mVaryings.clear();
304
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000305 mUsesMultipleRenderTargets = false;
306 mUsesFragColor = false;
307 mUsesFragData = false;
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000308 mUsesFragCoord = false;
309 mUsesFrontFacing = false;
310 mUsesPointSize = false;
311 mUsesPointCoord = false;
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000312 mUsesDepthRange = false;
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400313 mUsesFragDepth = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000314 mShaderVersion = 100;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000315
316 mActiveUniforms.clear();
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000317 mActiveInterfaceBlocks.clear();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000318}
319
320void Shader::compileToHLSL(void *compiler)
321{
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000322 // ensure the compiler is loaded
323 initializeCompiler();
324
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000325 int compileOptions = SH_OBJECT_CODE;
326 std::string sourcePath;
327 if (perfActive())
328 {
329 sourcePath = getTempPath();
Geoff Lang536d7262013-08-26 17:04:20 -0400330 writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000331 compileOptions |= SH_LINE_DIRECTIVES;
332 }
333
334 int result;
335 if (sourcePath.empty())
336 {
Geoff Lang536d7262013-08-26 17:04:20 -0400337 const char* sourceStrings[] =
338 {
339 mSource.c_str(),
340 };
341
342 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000343 }
344 else
345 {
Geoff Lang536d7262013-08-26 17:04:20 -0400346 const char* sourceStrings[] =
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000347 {
348 sourcePath.c_str(),
Geoff Lang536d7262013-08-26 17:04:20 -0400349 mSource.c_str(),
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000350 };
351
Geoff Lang536d7262013-08-26 17:04:20 -0400352 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000353 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000355 size_t shaderVersion = 100;
356 ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
357
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000358 mShaderVersion = static_cast<int>(shaderVersion);
359
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000360 if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
361 {
Geoff Lang536d7262013-08-26 17:04:20 -0400362 mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
363 TRACE("\n%s", mInfoLog.c_str());
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000364 }
365 else if (result)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000367 size_t objCodeLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000368 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
Geoff Lang536d7262013-08-26 17:04:20 -0400369
370 char* outputHLSL = new char[objCodeLen];
371 ShGetObjectCode(compiler, outputHLSL);
372 mHlsl = outputHLSL;
373 delete[] outputHLSL;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000374
375 void *activeUniforms;
376 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
377 mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms;
shannonwoods@chromium.org3f68bf02013-05-30 00:12:43 +0000378
379 void *activeInterfaceBlocks;
380 ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks);
381 mActiveInterfaceBlocks = *(sh::ActiveInterfaceBlocks*)activeInterfaceBlocks;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382 }
383 else
384 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000385 size_t infoLogLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000386 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387
Geoff Lang536d7262013-08-26 17:04:20 -0400388 char* infoLog = new char[infoLogLen];
389 ShGetInfoLog(compiler, infoLog);
390 mInfoLog = infoLog;
391
392 TRACE("\n%s", mInfoLog.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393 }
394}
395
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000396Interpolation Shader::parseInterpolation(const std::string &type)
397{
398 if (type == "linear")
399 {
400 return Smooth;
401 }
402 else if (type == "centroid")
403 {
404 return Centroid;
405 }
406 else if (type == "nointerpolation")
407 {
408 return Flat;
409 }
410 else UNREACHABLE();
411
412 return Smooth;
413}
414
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000415GLenum Shader::parseType(const std::string &type)
416{
417 if (type == "float")
418 {
419 return GL_FLOAT;
420 }
421 else if (type == "float2")
422 {
423 return GL_FLOAT_VEC2;
424 }
425 else if (type == "float3")
426 {
427 return GL_FLOAT_VEC3;
428 }
429 else if (type == "float4")
430 {
431 return GL_FLOAT_VEC4;
432 }
433 else if (type == "float2x2")
434 {
435 return GL_FLOAT_MAT2;
436 }
437 else if (type == "float3x3")
438 {
439 return GL_FLOAT_MAT3;
440 }
441 else if (type == "float4x4")
442 {
443 return GL_FLOAT_MAT4;
444 }
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000445 else if (type == "float2x3")
446 {
447 return GL_FLOAT_MAT2x3;
448 }
449 else if (type == "float3x2")
450 {
451 return GL_FLOAT_MAT3x2;
452 }
453 else if (type == "float2x4")
454 {
455 return GL_FLOAT_MAT2x4;
456 }
457 else if (type == "float4x2")
458 {
459 return GL_FLOAT_MAT4x2;
460 }
461 else if (type == "float3x4")
462 {
463 return GL_FLOAT_MAT3x4;
464 }
465 else if (type == "float4x3")
466 {
467 return GL_FLOAT_MAT4x3;
468 }
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000469 else if (type == "int")
470 {
471 return GL_INT;
472 }
473 else if (type == "int2")
474 {
475 return GL_INT_VEC2;
476 }
477 else if (type == "int3")
478 {
479 return GL_INT_VEC3;
480 }
481 else if (type == "int4")
482 {
483 return GL_INT_VEC4;
484 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000485 else if (type == "uint")
486 {
487 return GL_UNSIGNED_INT;
488 }
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000489 else if (type == "uint2")
490 {
491 return GL_UNSIGNED_INT_VEC2;
492 }
493 else if (type == "uint3")
494 {
495 return GL_UNSIGNED_INT_VEC3;
496 }
497 else if (type == "uint4")
498 {
499 return GL_UNSIGNED_INT_VEC4;
500 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000501 else UNREACHABLE();
502
503 return GL_NONE;
504}
505
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000506typedef std::map<GLenum, int> VaryingPriorityMap;
507static VaryingPriorityMap varyingPriorities;
508
509static void makeVaryingPriorityMap()
510{
511 varyingPriorities[GL_FLOAT_MAT4] = 0;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000512 varyingPriorities[GL_FLOAT_MAT3x4] = 10;
513 varyingPriorities[GL_FLOAT_MAT4x3] = 20;
514 varyingPriorities[GL_FLOAT_MAT2x4] = 30;
515 varyingPriorities[GL_FLOAT_MAT4x2] = 40;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000516 varyingPriorities[GL_FLOAT_MAT2] = 50;
517 varyingPriorities[GL_FLOAT_VEC4] = 60;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000518 varyingPriorities[GL_INT_VEC4] = 61;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000519 varyingPriorities[GL_UNSIGNED_INT_VEC4] = 62;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000520 varyingPriorities[GL_FLOAT_MAT3] = 70;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000521 varyingPriorities[GL_FLOAT_MAT2x3] = 80;
522 varyingPriorities[GL_FLOAT_MAT3x2] = 90;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000523 varyingPriorities[GL_FLOAT_VEC3] = 100;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000524 varyingPriorities[GL_INT_VEC3] = 101;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000525 varyingPriorities[GL_UNSIGNED_INT_VEC3] = 102;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000526 varyingPriorities[GL_FLOAT_VEC2] = 110;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000527 varyingPriorities[GL_INT_VEC2] = 111;
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000528 varyingPriorities[GL_UNSIGNED_INT_VEC2] = 112;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000529 varyingPriorities[GL_FLOAT] = 120;
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000530 varyingPriorities[GL_INT] = 125;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000531 varyingPriorities[GL_UNSIGNED_INT] = 130;
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000532}
533
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000534// true if varying x has a higher priority in packing than y
535bool Shader::compareVarying(const Varying &x, const Varying &y)
536{
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000537 if (varyingPriorities.empty())
538 {
539 makeVaryingPriorityMap();
540 }
541
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000542 if(x.type == y.type)
543 {
544 return x.size > y.size;
545 }
546
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000547 VaryingPriorityMap::iterator xPriority = varyingPriorities.find(x.type);
548 VaryingPriorityMap::iterator yPriority = varyingPriorities.find(y.type);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000549
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000550 ASSERT(xPriority != varyingPriorities.end());
551 ASSERT(yPriority != varyingPriorities.end());
552
553 return xPriority->second <= yPriority->second;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000554}
555
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000556int Shader::getShaderVersion() const
557{
558 return mShaderVersion;
559}
560
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000561VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
562 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000563{
564}
565
566VertexShader::~VertexShader()
567{
568}
569
570GLenum VertexShader::getType()
571{
572 return GL_VERTEX_SHADER;
573}
574
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000575void VertexShader::uncompile()
576{
577 Shader::uncompile();
578
579 // set by ParseAttributes
Jamie Madilldefb6742013-06-20 11:55:51 -0400580 mActiveAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000581}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000582
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000583void VertexShader::compile()
584{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000585 uncompile();
586
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000587 compileToHLSL(mVertexCompiler);
588 parseAttributes();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000589 parseVaryings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000590}
591
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000592int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000594 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000595 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000596 int semanticIndex = 0;
Jamie Madilldefb6742013-06-20 11:55:51 -0400597 for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400599 const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
600
601 if (attribute.name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000602 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000603 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000604 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000605
Jamie Madilldefb6742013-06-20 11:55:51 -0400606 semanticIndex += AttributeRegisterCount(attribute.type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000607 }
608 }
609
610 return -1;
611}
612
613void VertexShader::parseAttributes()
614{
Geoff Lang536d7262013-08-26 17:04:20 -0400615 const std::string &hlsl = getHLSL();
616 if (!hlsl.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000617 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400618 void *activeAttributes;
619 ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes);
620 mActiveAttributes = *(sh::ActiveShaderVariables*)activeAttributes;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000621 }
622}
623
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000624FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
625 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626{
627}
628
629FragmentShader::~FragmentShader()
630{
631}
632
633GLenum FragmentShader::getType()
634{
635 return GL_FRAGMENT_SHADER;
636}
637
638void FragmentShader::compile()
639{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000640 uncompile();
641
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000642 compileToHLSL(mFragmentCompiler);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000643 parseVaryings();
daniel@transgaming.comcde6a612012-02-17 18:01:10 +0000644 mVaryings.sort(compareVarying);
Jamie Madill46131a32013-06-20 11:55:50 -0400645
Geoff Lang536d7262013-08-26 17:04:20 -0400646 const std::string &hlsl = getHLSL();
647 if (!hlsl.empty())
Jamie Madill46131a32013-06-20 11:55:50 -0400648 {
649 void *activeOutputVariables;
650 ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables);
651 mActiveOutputVariables = *(sh::ActiveShaderVariables*)activeOutputVariables;
652 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653}
Jamie Madill46131a32013-06-20 11:55:50 -0400654
655void FragmentShader::uncompile()
656{
657 Shader::uncompile();
658
659 mActiveOutputVariables.clear();
660}
661
662const sh::ActiveShaderVariables &FragmentShader::getOutputVariables() const
663{
664 return mActiveOutputVariables;
665}
666
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000667}