blob: ea5a8d1f4c8ed261704448222e4ce5f8689c1c8e [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//
Geoff Langcec35902014-04-16 10:52:36 -04003// Copyright (c) 2002-2014 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 Madilld4116ff2014-07-11 17:02:01 -0400118unsigned int Shader::getInterfaceBlockRegister(const std::string &blockName) const
119{
120 ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0);
121 return mInterfaceBlockRegisterMap.find(blockName)->second;
122}
123
Jamie Madillf2575982014-06-25 16:04:54 -0400124const std::vector<sh::Uniform> &Shader::getUniforms() const
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000125{
126 return mActiveUniforms;
127}
128
Jamie Madillf2575982014-06-25 16:04:54 -0400129const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000130{
131 return mActiveInterfaceBlocks;
132}
133
Jamie Madillff0d2ba2014-05-14 13:49:10 -0400134std::vector<PackedVarying> &Shader::getVaryings()
Jamie Madill5f562732014-02-14 16:41:24 -0500135{
136 return mVaryings;
137}
138
Geoff Lang536d7262013-08-26 17:04:20 -0400139bool Shader::isCompiled() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140{
Geoff Lang536d7262013-08-26 17:04:20 -0400141 return !mHlsl.empty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142}
143
Geoff Lang536d7262013-08-26 17:04:20 -0400144const std::string &Shader::getHLSL() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145{
146 return mHlsl;
147}
148
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000149void Shader::addRef()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000151 mRefCount++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152}
153
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000154void Shader::release()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000156 mRefCount--;
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000157
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000158 if (mRefCount == 0 && mDeleteStatus)
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000159 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000160 mResourceManager->deleteShader(mHandle);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000161 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162}
163
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000164unsigned int Shader::getRefCount() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000166 return mRefCount;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167}
168
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000169bool Shader::isFlaggedForDeletion() const
170{
171 return mDeleteStatus;
172}
173
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174void Shader::flagForDeletion()
175{
176 mDeleteStatus = true;
177}
178
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000179// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
180void Shader::initializeCompiler()
181{
182 if (!mFragmentCompiler)
183 {
184 int result = ShInitialize();
185
186 if (result)
187 {
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000188 ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
189
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000190 ShBuiltInResources resources;
191 ShInitBuiltInResources(&resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000192
Geoff Langc0b9ef42014-07-02 10:02:37 -0400193 // TODO(geofflang): use context's caps
194 const gl::Caps &caps = mRenderer->getRendererCaps();
195 const gl::Extensions &extensions = mRenderer->getRendererExtensions();
Geoff Langcec35902014-04-16 10:52:36 -0400196
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000197 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
shannon.woods@transgaming.com4e482042013-01-25 21:54:18 +0000198 resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000199 resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000200 resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000201 resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000202 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +0000203 resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
Geoff Langaae65a42014-05-26 12:43:44 -0400204 resources.MaxDrawBuffers = caps.maxDrawBuffers;
Geoff Langc0b9ef42014-07-02 10:02:37 -0400205 resources.OES_standard_derivatives = extensions.standardDerivatives;
206 resources.EXT_draw_buffers = extensions.drawBuffers;
Nicolas Capens46485082014-04-15 13:12:50 -0400207 resources.EXT_shader_texture_lod = 1;
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000208 // 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 +0000209 resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400210 resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
shannonwoods@chromium.org74b86cf2013-05-30 00:02:58 +0000211 // GLSL ES 3.0 constants
212 resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors();
213 resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors();
214 resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
215 resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000216
Jamie Madill183bde52014-07-02 15:31:19 -0400217 mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
218 mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000219 }
220 }
221}
222
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223void Shader::releaseCompiler()
224{
225 ShDestruct(mFragmentCompiler);
226 ShDestruct(mVertexCompiler);
227
228 mFragmentCompiler = NULL;
229 mVertexCompiler = NULL;
alokp@chromium.org90033b92010-05-24 15:02:43 +0000230
231 ShFinalize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232}
233
Jamie Madill47fdd132013-08-30 13:21:04 -0400234void Shader::parseVaryings(void *compiler)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000235{
Geoff Lang536d7262013-08-26 17:04:20 -0400236 if (!mHlsl.empty())
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000237 {
Jamie Madillf2575982014-06-25 16:04:54 -0400238 std::vector<sh::Varying> *activeVaryings;
Jamie Madill47fdd132013-08-30 13:21:04 -0400239 ShGetInfoPointer(compiler, SH_ACTIVE_VARYINGS_ARRAY, reinterpret_cast<void**>(&activeVaryings));
Jamie Madillff0d2ba2014-05-14 13:49:10 -0400240
241 for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++)
242 {
243 mVaryings.push_back(PackedVarying((*activeVaryings)[varyingIndex]));
244 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000245
Geoff Lang536d7262013-08-26 17:04:20 -0400246 mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos;
247 mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos;
248 mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos;
249 mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos;
250 mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
251 mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos;
252 mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos;
253 mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos;
254 mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos;
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500255 mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
Nicolas Capens655fe362014-04-11 13:12:34 -0400256 mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000257 }
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000258}
259
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000260void Shader::resetVaryingsRegisterAssignment()
261{
Jamie Madillce79dda2013-08-30 13:21:06 -0400262 for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000263 {
Jamie Madill139b9092013-08-30 13:21:06 -0400264 mVaryings[varyingIndex].resetRegisterAssignment();
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000265 }
266}
267
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000268// initialize/clean up previous state
269void Shader::uncompile()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000271 // set by compileToHLSL
Geoff Lang536d7262013-08-26 17:04:20 -0400272 mHlsl.clear();
273 mInfoLog.clear();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000275 // set by parseVaryings
276 mVaryings.clear();
277
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000278 mUsesMultipleRenderTargets = false;
279 mUsesFragColor = false;
280 mUsesFragData = false;
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000281 mUsesFragCoord = false;
282 mUsesFrontFacing = false;
283 mUsesPointSize = false;
284 mUsesPointCoord = false;
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000285 mUsesDepthRange = false;
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400286 mUsesFragDepth = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000287 mShaderVersion = 100;
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500288 mUsesDiscardRewriting = false;
Nicolas Capens655fe362014-04-11 13:12:34 -0400289 mUsesNestedBreak = false;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000290
291 mActiveUniforms.clear();
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000292 mActiveInterfaceBlocks.clear();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000293}
294
295void Shader::compileToHLSL(void *compiler)
296{
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000297 // ensure the compiler is loaded
298 initializeCompiler();
299
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000300 int compileOptions = SH_OBJECT_CODE;
301 std::string sourcePath;
302 if (perfActive())
303 {
304 sourcePath = getTempPath();
Geoff Lang536d7262013-08-26 17:04:20 -0400305 writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000306 compileOptions |= SH_LINE_DIRECTIVES;
307 }
308
309 int result;
310 if (sourcePath.empty())
311 {
Geoff Lang536d7262013-08-26 17:04:20 -0400312 const char* sourceStrings[] =
313 {
314 mSource.c_str(),
315 };
316
317 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000318 }
319 else
320 {
Geoff Lang536d7262013-08-26 17:04:20 -0400321 const char* sourceStrings[] =
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000322 {
323 sourcePath.c_str(),
Geoff Lang536d7262013-08-26 17:04:20 -0400324 mSource.c_str(),
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000325 };
326
Geoff Lang536d7262013-08-26 17:04:20 -0400327 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000328 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000330 size_t shaderVersion = 100;
331 ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
332
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000333 mShaderVersion = static_cast<int>(shaderVersion);
334
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000335 if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
336 {
Geoff Lang536d7262013-08-26 17:04:20 -0400337 mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
338 TRACE("\n%s", mInfoLog.c_str());
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000339 }
340 else if (result)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000342 size_t objCodeLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000343 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
Geoff Lang536d7262013-08-26 17:04:20 -0400344
345 char* outputHLSL = new char[objCodeLen];
346 ShGetObjectCode(compiler, outputHLSL);
Geoff Lang7f6562b2013-08-28 09:37:27 -0400347
348#ifdef _DEBUG
349 std::ostringstream hlslStream;
350 hlslStream << "// GLSL\n";
351 hlslStream << "//\n";
352
353 size_t curPos = 0;
354 while (curPos != std::string::npos)
355 {
356 size_t nextLine = mSource.find("\n", curPos);
357 size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
358
359 hlslStream << "// " << mSource.substr(curPos, len);
360
361 curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
362 }
363 hlslStream << "\n\n";
364 hlslStream << outputHLSL;
365 mHlsl = hlslStream.str();
366#else
Geoff Lang536d7262013-08-26 17:04:20 -0400367 mHlsl = outputHLSL;
Geoff Lang7f6562b2013-08-28 09:37:27 -0400368#endif
369
Geoff Lang536d7262013-08-26 17:04:20 -0400370 delete[] outputHLSL;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000371
372 void *activeUniforms;
373 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
Jamie Madillf2575982014-06-25 16:04:54 -0400374 mActiveUniforms = *(std::vector<sh::Uniform>*)activeUniforms;
shannonwoods@chromium.org3f68bf02013-05-30 00:12:43 +0000375
376 void *activeInterfaceBlocks;
377 ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks);
Jamie Madillf2575982014-06-25 16:04:54 -0400378 mActiveInterfaceBlocks = *(std::vector<sh::InterfaceBlock>*)activeInterfaceBlocks;
Jamie Madilld4116ff2014-07-11 17:02:01 -0400379
380 for (size_t blockIndex = 0; blockIndex < mActiveInterfaceBlocks.size(); blockIndex++)
381 {
382 const sh::InterfaceBlock &interfaceBlock = mActiveInterfaceBlocks[blockIndex];
383
384 unsigned int index = -1;
385 bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index);
386 UNUSED_ASSERTION_VARIABLE(result);
387 ASSERT(result);
388
389 mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
390 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391 }
392 else
393 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000394 size_t infoLogLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000395 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396
Geoff Lang536d7262013-08-26 17:04:20 -0400397 char* infoLog = new char[infoLogLen];
398 ShGetInfoLog(compiler, infoLog);
399 mInfoLog = infoLog;
400
401 TRACE("\n%s", mInfoLog.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000402 }
403}
404
Jamie Madill5f562732014-02-14 16:41:24 -0500405rx::D3DWorkaroundType Shader::getD3DWorkarounds() const
406{
407 if (mUsesDiscardRewriting)
408 {
Nicolas Capens655fe362014-04-11 13:12:34 -0400409 // ANGLE issue 486:
410 // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
411 return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
412 }
413
414 if (mUsesNestedBreak)
415 {
416 // ANGLE issue 603:
417 // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
418 // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
419 return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
Jamie Madill5f562732014-02-14 16:41:24 -0500420 }
421
422 return rx::ANGLE_D3D_WORKAROUND_NONE;
423}
424
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000425// true if varying x has a higher priority in packing than y
Jamie Madillff0d2ba2014-05-14 13:49:10 -0400426bool Shader::compareVarying(const PackedVarying &x, const PackedVarying &y)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000427{
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400428 if (x.type == y.type)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000429 {
Jamie Madill139b9092013-08-30 13:21:06 -0400430 return x.arraySize > y.arraySize;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000431 }
432
Jamie Madill28167c62013-08-30 13:21:10 -0400433 // Special case for handling structs: we sort these to the end of the list
434 if (x.type == GL_STRUCT_ANGLEX)
435 {
436 return false;
437 }
438
Jamie Madill865d1452014-07-02 15:31:20 -0400439 if (y.type == GL_STRUCT_ANGLEX)
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400440 {
Jamie Madill865d1452014-07-02 15:31:20 -0400441 return true;
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400442 }
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000443
Jamie Madill865d1452014-07-02 15:31:20 -0400444 return gl::VariableSortOrder(x.type) <= gl::VariableSortOrder(y.type);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000445}
446
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000447int Shader::getShaderVersion() const
448{
449 return mShaderVersion;
450}
451
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000452VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
453 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454{
455}
456
457VertexShader::~VertexShader()
458{
459}
460
Jamie Madilld4116ff2014-07-11 17:02:01 -0400461GLenum VertexShader::getType() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462{
463 return GL_VERTEX_SHADER;
464}
465
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000466void VertexShader::uncompile()
467{
468 Shader::uncompile();
469
470 // set by ParseAttributes
Jamie Madilldefb6742013-06-20 11:55:51 -0400471 mActiveAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000472}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000473
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000474void VertexShader::compile()
475{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000476 uncompile();
477
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478 compileToHLSL(mVertexCompiler);
479 parseAttributes();
Jamie Madill47fdd132013-08-30 13:21:04 -0400480 parseVaryings(mVertexCompiler);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481}
482
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000483int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000485 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000487 int semanticIndex = 0;
Jamie Madilldefb6742013-06-20 11:55:51 -0400488 for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000489 {
Jamie Madillf2575982014-06-25 16:04:54 -0400490 const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
Jamie Madilldefb6742013-06-20 11:55:51 -0400491
492 if (attribute.name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000494 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000495 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000496
Jamie Madillf2575982014-06-25 16:04:54 -0400497 semanticIndex += VariableRegisterCount(attribute.type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000498 }
499 }
500
501 return -1;
502}
503
504void VertexShader::parseAttributes()
505{
Geoff Lang536d7262013-08-26 17:04:20 -0400506 const std::string &hlsl = getHLSL();
507 if (!hlsl.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400509 void *activeAttributes;
510 ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes);
Jamie Madillf2575982014-06-25 16:04:54 -0400511 mActiveAttributes = *(std::vector<sh::Attribute>*)activeAttributes;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000512 }
513}
514
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000515FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
516 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000517{
518}
519
520FragmentShader::~FragmentShader()
521{
522}
523
Jamie Madilld4116ff2014-07-11 17:02:01 -0400524GLenum FragmentShader::getType() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000525{
526 return GL_FRAGMENT_SHADER;
527}
528
529void FragmentShader::compile()
530{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000531 uncompile();
532
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000533 compileToHLSL(mFragmentCompiler);
Jamie Madill47fdd132013-08-30 13:21:04 -0400534 parseVaryings(mFragmentCompiler);
Jamie Madillce79dda2013-08-30 13:21:06 -0400535 std::sort(mVaryings.begin(), mVaryings.end(), compareVarying);
Jamie Madill46131a32013-06-20 11:55:50 -0400536
Geoff Lang536d7262013-08-26 17:04:20 -0400537 const std::string &hlsl = getHLSL();
538 if (!hlsl.empty())
Jamie Madill46131a32013-06-20 11:55:50 -0400539 {
540 void *activeOutputVariables;
541 ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables);
Jamie Madillf2575982014-06-25 16:04:54 -0400542 mActiveOutputVariables = *(std::vector<sh::Attribute>*)activeOutputVariables;
Jamie Madill46131a32013-06-20 11:55:50 -0400543 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000544}
Jamie Madill46131a32013-06-20 11:55:50 -0400545
546void FragmentShader::uncompile()
547{
548 Shader::uncompile();
549
550 mActiveOutputVariables.clear();
551}
552
Jamie Madillf2575982014-06-25 16:04:54 -0400553const std::vector<sh::Attribute> &FragmentShader::getOutputVariables() const
Jamie Madill46131a32013-06-20 11:55:50 -0400554{
555 return mActiveOutputVariables;
556}
557
Jamie Madill68fe74a2014-05-27 12:56:01 -0400558ShShaderOutput Shader::getCompilerOutputType(GLenum shader)
559{
560 void *compiler = NULL;
561
562 switch (shader)
563 {
564 case GL_VERTEX_SHADER: compiler = mVertexCompiler; break;
565 case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break;
566 default: UNREACHABLE(); return SH_HLSL9_OUTPUT;
567 }
568
569 size_t outputType = 0;
570 ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType);
571
572 return static_cast<ShShaderOutput>(outputType);
573}
574
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000575}