blob: 3ff59137899ee0ae97bd2caa771c9916b05a5d0f [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
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400118const std::vector<sh::Uniform> &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);
Geoff Lang7f6562b2013-08-28 09:37:27 -0400372
373#ifdef _DEBUG
374 std::ostringstream hlslStream;
375 hlslStream << "// GLSL\n";
376 hlslStream << "//\n";
377
378 size_t curPos = 0;
379 while (curPos != std::string::npos)
380 {
381 size_t nextLine = mSource.find("\n", curPos);
382 size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
383
384 hlslStream << "// " << mSource.substr(curPos, len);
385
386 curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
387 }
388 hlslStream << "\n\n";
389 hlslStream << outputHLSL;
390 mHlsl = hlslStream.str();
391#else
Geoff Lang536d7262013-08-26 17:04:20 -0400392 mHlsl = outputHLSL;
Geoff Lang7f6562b2013-08-28 09:37:27 -0400393#endif
394
Geoff Lang536d7262013-08-26 17:04:20 -0400395 delete[] outputHLSL;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000396
397 void *activeUniforms;
398 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400399 mActiveUniforms = *(std::vector<sh::Uniform>*)activeUniforms;
shannonwoods@chromium.org3f68bf02013-05-30 00:12:43 +0000400
401 void *activeInterfaceBlocks;
402 ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks);
403 mActiveInterfaceBlocks = *(sh::ActiveInterfaceBlocks*)activeInterfaceBlocks;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000404 }
405 else
406 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000407 size_t infoLogLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000408 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409
Geoff Lang536d7262013-08-26 17:04:20 -0400410 char* infoLog = new char[infoLogLen];
411 ShGetInfoLog(compiler, infoLog);
412 mInfoLog = infoLog;
413
414 TRACE("\n%s", mInfoLog.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000415 }
416}
417
shannon.woods%transgaming.com@gtempaccount.com1886fd42013-04-13 03:41:45 +0000418Interpolation Shader::parseInterpolation(const std::string &type)
419{
420 if (type == "linear")
421 {
422 return Smooth;
423 }
424 else if (type == "centroid")
425 {
426 return Centroid;
427 }
428 else if (type == "nointerpolation")
429 {
430 return Flat;
431 }
432 else UNREACHABLE();
433
434 return Smooth;
435}
436
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000437GLenum Shader::parseType(const std::string &type)
438{
439 if (type == "float")
440 {
441 return GL_FLOAT;
442 }
443 else if (type == "float2")
444 {
445 return GL_FLOAT_VEC2;
446 }
447 else if (type == "float3")
448 {
449 return GL_FLOAT_VEC3;
450 }
451 else if (type == "float4")
452 {
453 return GL_FLOAT_VEC4;
454 }
455 else if (type == "float2x2")
456 {
457 return GL_FLOAT_MAT2;
458 }
459 else if (type == "float3x3")
460 {
461 return GL_FLOAT_MAT3;
462 }
463 else if (type == "float4x4")
464 {
465 return GL_FLOAT_MAT4;
466 }
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000467 else if (type == "float2x3")
468 {
469 return GL_FLOAT_MAT2x3;
470 }
471 else if (type == "float3x2")
472 {
473 return GL_FLOAT_MAT3x2;
474 }
475 else if (type == "float2x4")
476 {
477 return GL_FLOAT_MAT2x4;
478 }
479 else if (type == "float4x2")
480 {
481 return GL_FLOAT_MAT4x2;
482 }
483 else if (type == "float3x4")
484 {
485 return GL_FLOAT_MAT3x4;
486 }
487 else if (type == "float4x3")
488 {
489 return GL_FLOAT_MAT4x3;
490 }
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +0000491 else if (type == "int")
492 {
493 return GL_INT;
494 }
495 else if (type == "int2")
496 {
497 return GL_INT_VEC2;
498 }
499 else if (type == "int3")
500 {
501 return GL_INT_VEC3;
502 }
503 else if (type == "int4")
504 {
505 return GL_INT_VEC4;
506 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000507 else if (type == "uint")
508 {
509 return GL_UNSIGNED_INT;
510 }
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000511 else if (type == "uint2")
512 {
513 return GL_UNSIGNED_INT_VEC2;
514 }
515 else if (type == "uint3")
516 {
517 return GL_UNSIGNED_INT_VEC3;
518 }
519 else if (type == "uint4")
520 {
521 return GL_UNSIGNED_INT_VEC4;
522 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000523 else UNREACHABLE();
524
525 return GL_NONE;
526}
527
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400528// [OpenGL ES SL 3.00.4] Section 11 p. 120
529// Vertex Outs/Fragment Ins packing priorities
530static const GLenum varyingPriorityList[] =
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000531{
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400532 // 1. Arrays of mat4 and mat4
533 GL_FLOAT_MAT4,
534
535 // Non-square matrices of type matCxR consume the same space as a square
536 // matrix of type matN where N is the greater of C and R
537 GL_FLOAT_MAT3x4,
538 GL_FLOAT_MAT4x3,
539 GL_FLOAT_MAT2x4,
540 GL_FLOAT_MAT4x2,
541
542 // 2. Arrays of mat2 and mat2 (since they occupy full rows)
543 GL_FLOAT_MAT2,
544
545 // 3. Arrays of vec4 and vec4
546 GL_FLOAT_VEC4,
547 GL_INT_VEC4,
548 GL_UNSIGNED_INT_VEC4,
549
550 // 4. Arrays of mat3 and mat3
551 GL_FLOAT_MAT3,
552 GL_FLOAT_MAT2x3,
553 GL_FLOAT_MAT3x2,
554
555 // 5. Arrays of vec3 and vec3
556 GL_FLOAT_VEC3,
557 GL_INT_VEC3,
558 GL_UNSIGNED_INT_VEC3,
559
560 // 6. Arrays of vec2 and vec2
561 GL_FLOAT_VEC2,
562 GL_INT_VEC2,
563 GL_UNSIGNED_INT_VEC2,
564
565 // 7. Arrays of float and float
566 GL_FLOAT,
567 GL_INT,
568 GL_UNSIGNED_INT,
569};
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000570
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000571// true if varying x has a higher priority in packing than y
572bool Shader::compareVarying(const Varying &x, const Varying &y)
573{
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400574 if (x.type == y.type)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000575 {
576 return x.size > y.size;
577 }
578
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400579 unsigned int xPriority = GL_INVALID_INDEX;
580 unsigned int yPriority = GL_INVALID_INDEX;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000581
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400582 for (unsigned int priorityIndex = 0; priorityIndex < ArraySize(varyingPriorityList); priorityIndex++)
583 {
584 if (varyingPriorityList[priorityIndex] == x.type) xPriority = priorityIndex;
585 if (varyingPriorityList[priorityIndex] == y.type) yPriority = priorityIndex;
586 if (xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX) break;
587 }
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000588
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400589 ASSERT(xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX);
590
591 return xPriority <= yPriority;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000592}
593
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000594int Shader::getShaderVersion() const
595{
596 return mShaderVersion;
597}
598
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000599VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
600 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601{
602}
603
604VertexShader::~VertexShader()
605{
606}
607
608GLenum VertexShader::getType()
609{
610 return GL_VERTEX_SHADER;
611}
612
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000613void VertexShader::uncompile()
614{
615 Shader::uncompile();
616
617 // set by ParseAttributes
Jamie Madilldefb6742013-06-20 11:55:51 -0400618 mActiveAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000619}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000620
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000621void VertexShader::compile()
622{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000623 uncompile();
624
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000625 compileToHLSL(mVertexCompiler);
626 parseAttributes();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000627 parseVaryings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000628}
629
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000630int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000631{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000632 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000633 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000634 int semanticIndex = 0;
Jamie Madilldefb6742013-06-20 11:55:51 -0400635 for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000636 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400637 const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
638
639 if (attribute.name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000640 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000641 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000642 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000643
Jamie Madilldefb6742013-06-20 11:55:51 -0400644 semanticIndex += AttributeRegisterCount(attribute.type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645 }
646 }
647
648 return -1;
649}
650
651void VertexShader::parseAttributes()
652{
Geoff Lang536d7262013-08-26 17:04:20 -0400653 const std::string &hlsl = getHLSL();
654 if (!hlsl.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400656 void *activeAttributes;
657 ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes);
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400658 mActiveAttributes = *(std::vector<sh::Attribute>*)activeAttributes;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000659 }
660}
661
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000662FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
663 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000664{
665}
666
667FragmentShader::~FragmentShader()
668{
669}
670
671GLenum FragmentShader::getType()
672{
673 return GL_FRAGMENT_SHADER;
674}
675
676void FragmentShader::compile()
677{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000678 uncompile();
679
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000680 compileToHLSL(mFragmentCompiler);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000681 parseVaryings();
daniel@transgaming.comcde6a612012-02-17 18:01:10 +0000682 mVaryings.sort(compareVarying);
Jamie Madill46131a32013-06-20 11:55:50 -0400683
Geoff Lang536d7262013-08-26 17:04:20 -0400684 const std::string &hlsl = getHLSL();
685 if (!hlsl.empty())
Jamie Madill46131a32013-06-20 11:55:50 -0400686 {
687 void *activeOutputVariables;
688 ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables);
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400689 mActiveOutputVariables = *(std::vector<sh::Attribute>*)activeOutputVariables;
Jamie Madill46131a32013-06-20 11:55:50 -0400690 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000691}
Jamie Madill46131a32013-06-20 11:55:50 -0400692
693void FragmentShader::uncompile()
694{
695 Shader::uncompile();
696
697 mActiveOutputVariables.clear();
698}
699
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400700const std::vector<sh::Attribute> &FragmentShader::getOutputVariables() const
Jamie Madill46131a32013-06-20 11:55:50 -0400701{
702 return mActiveOutputVariables;
703}
704
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000705}