blob: 19066579c41c992ae4203d1bfed0c4eb1c643141 [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
Jamie Madille294bb82014-07-17 14:16:26 -040025template <typename VarT>
26const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableList)
27{
28 // TODO: handle staticUse. for now, assume all returned variables are active.
29 ASSERT(variableList);
30 return variableList;
31}
32
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +000033Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
34 : mHandle(handle), mRenderer(renderer), mResourceManager(manager)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035{
daniel@transgaming.com938009c2012-02-17 18:02:15 +000036 uncompile();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +000037 initializeCompiler();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000039 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000040 mDeleteStatus = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +000041 mShaderVersion = 100;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042}
43
44Shader::~Shader()
45{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000046}
47
daniel@transgaming.com6c785212010-03-30 03:36:17 +000048GLuint Shader::getHandle() const
49{
50 return mHandle;
51}
52
shannon.woods%transgaming.com@gtempaccount.com5f339332013-04-13 03:29:02 +000053void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000054{
Geoff Lang536d7262013-08-26 17:04:20 -040055 std::ostringstream stream;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000056
57 for (int i = 0; i < count; i++)
58 {
Geoff Lang536d7262013-08-26 17:04:20 -040059 stream << string[i];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000060 }
61
Geoff Lang536d7262013-08-26 17:04:20 -040062 mSource = stream.str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000063}
64
daniel@transgaming.comcba50572010-03-28 19:36:09 +000065int Shader::getInfoLogLength() const
66{
Geoff Lang536d7262013-08-26 17:04:20 -040067 return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1);
daniel@transgaming.comcba50572010-03-28 19:36:09 +000068}
69
Geoff Lang536d7262013-08-26 17:04:20 -040070void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
daniel@transgaming.comcba50572010-03-28 19:36:09 +000071{
72 int index = 0;
73
daniel@transgaming.com807d8c32012-04-04 15:06:04 +000074 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +000075 {
Geoff Lang536d7262013-08-26 17:04:20 -040076 index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
77 memcpy(infoLog, mInfoLog.c_str(), index);
daniel@transgaming.comcba50572010-03-28 19:36:09 +000078
daniel@transgaming.comcba50572010-03-28 19:36:09 +000079 infoLog[index] = '\0';
80 }
81
82 if (length)
83 {
84 *length = index;
85 }
86}
87
88int Shader::getSourceLength() const
89{
Geoff Lang536d7262013-08-26 17:04:20 -040090 return mSource.empty() ? 0 : (mSource.length() + 1);
daniel@transgaming.comcba50572010-03-28 19:36:09 +000091}
92
zmo@google.coma574f782011-10-03 21:45:23 +000093int Shader::getTranslatedSourceLength() const
94{
Geoff Lang536d7262013-08-26 17:04:20 -040095 return mHlsl.empty() ? 0 : (mHlsl.length() + 1);
zmo@google.coma574f782011-10-03 21:45:23 +000096}
97
Geoff Lang536d7262013-08-26 17:04:20 -040098void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const
daniel@transgaming.comcba50572010-03-28 19:36:09 +000099{
100 int index = 0;
101
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000102 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000103 {
Geoff Lang536d7262013-08-26 17:04:20 -0400104 index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
105 memcpy(buffer, source.c_str(), index);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000106
zmo@google.coma574f782011-10-03 21:45:23 +0000107 buffer[index] = '\0';
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000108 }
109
110 if (length)
111 {
112 *length = index;
113 }
114}
115
Geoff Lang536d7262013-08-26 17:04:20 -0400116void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
zmo@google.coma574f782011-10-03 21:45:23 +0000117{
118 getSourceImpl(mSource, bufSize, length, buffer);
119}
120
Geoff Lang536d7262013-08-26 17:04:20 -0400121void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
zmo@google.coma574f782011-10-03 21:45:23 +0000122{
123 getSourceImpl(mHlsl, bufSize, length, buffer);
124}
125
Jamie Madillbf9cce22014-07-18 10:33:09 -0400126unsigned int Shader::getUniformRegister(const std::string &uniformName) const
127{
128 ASSERT(mUniformRegisterMap.count(uniformName) > 0);
129 return mUniformRegisterMap.find(uniformName)->second;
130}
131
Jamie Madilld4116ff2014-07-11 17:02:01 -0400132unsigned int Shader::getInterfaceBlockRegister(const std::string &blockName) const
133{
134 ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0);
135 return mInterfaceBlockRegisterMap.find(blockName)->second;
136}
137
Jamie Madillf2575982014-06-25 16:04:54 -0400138const std::vector<sh::Uniform> &Shader::getUniforms() const
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000139{
140 return mActiveUniforms;
141}
142
Jamie Madillf2575982014-06-25 16:04:54 -0400143const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000144{
145 return mActiveInterfaceBlocks;
146}
147
Jamie Madillff0d2ba2014-05-14 13:49:10 -0400148std::vector<PackedVarying> &Shader::getVaryings()
Jamie Madill5f562732014-02-14 16:41:24 -0500149{
150 return mVaryings;
151}
152
Geoff Lang536d7262013-08-26 17:04:20 -0400153bool Shader::isCompiled() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154{
Geoff Lang536d7262013-08-26 17:04:20 -0400155 return !mHlsl.empty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
Geoff Lang536d7262013-08-26 17:04:20 -0400158const std::string &Shader::getHLSL() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159{
160 return mHlsl;
161}
162
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000163void Shader::addRef()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000165 mRefCount++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166}
167
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000168void Shader::release()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000170 mRefCount--;
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000171
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000172 if (mRefCount == 0 && mDeleteStatus)
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000173 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000174 mResourceManager->deleteShader(mHandle);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000175 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176}
177
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000178unsigned int Shader::getRefCount() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000180 return mRefCount;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181}
182
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000183bool Shader::isFlaggedForDeletion() const
184{
185 return mDeleteStatus;
186}
187
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188void Shader::flagForDeletion()
189{
190 mDeleteStatus = true;
191}
192
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000193// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
194void Shader::initializeCompiler()
195{
196 if (!mFragmentCompiler)
197 {
198 int result = ShInitialize();
199
200 if (result)
201 {
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000202 ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
203
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000204 ShBuiltInResources resources;
205 ShInitBuiltInResources(&resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000206
Geoff Langc0b9ef42014-07-02 10:02:37 -0400207 // TODO(geofflang): use context's caps
208 const gl::Caps &caps = mRenderer->getRendererCaps();
209 const gl::Extensions &extensions = mRenderer->getRendererExtensions();
Geoff Langcec35902014-04-16 10:52:36 -0400210
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000211 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
shannon.woods@transgaming.com4e482042013-01-25 21:54:18 +0000212 resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000213 resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000214 resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000215 resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000216 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +0000217 resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
Geoff Langaae65a42014-05-26 12:43:44 -0400218 resources.MaxDrawBuffers = caps.maxDrawBuffers;
Geoff Langc0b9ef42014-07-02 10:02:37 -0400219 resources.OES_standard_derivatives = extensions.standardDerivatives;
220 resources.EXT_draw_buffers = extensions.drawBuffers;
Nicolas Capens46485082014-04-15 13:12:50 -0400221 resources.EXT_shader_texture_lod = 1;
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000222 // 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 +0000223 resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400224 resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
shannonwoods@chromium.org74b86cf2013-05-30 00:02:58 +0000225 // GLSL ES 3.0 constants
226 resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors();
227 resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors();
228 resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
229 resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000230
Jamie Madill183bde52014-07-02 15:31:19 -0400231 mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
232 mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000233 }
234 }
235}
236
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237void Shader::releaseCompiler()
238{
239 ShDestruct(mFragmentCompiler);
240 ShDestruct(mVertexCompiler);
241
242 mFragmentCompiler = NULL;
243 mVertexCompiler = NULL;
alokp@chromium.org90033b92010-05-24 15:02:43 +0000244
245 ShFinalize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246}
247
Jamie Madill47fdd132013-08-30 13:21:04 -0400248void Shader::parseVaryings(void *compiler)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000249{
Geoff Lang536d7262013-08-26 17:04:20 -0400250 if (!mHlsl.empty())
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000251 {
Jamie Madille294bb82014-07-17 14:16:26 -0400252 const std::vector<sh::Varying> *activeVaryings = ShGetVaryings(compiler);
253 ASSERT(activeVaryings);
Jamie Madillff0d2ba2014-05-14 13:49:10 -0400254
255 for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++)
256 {
257 mVaryings.push_back(PackedVarying((*activeVaryings)[varyingIndex]));
258 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000259
Geoff Lang536d7262013-08-26 17:04:20 -0400260 mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos;
261 mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos;
262 mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos;
263 mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos;
264 mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
265 mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos;
266 mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos;
267 mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos;
268 mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos;
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500269 mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
Nicolas Capens655fe362014-04-11 13:12:34 -0400270 mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000271 }
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000272}
273
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000274void Shader::resetVaryingsRegisterAssignment()
275{
Jamie Madillce79dda2013-08-30 13:21:06 -0400276 for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000277 {
Jamie Madill139b9092013-08-30 13:21:06 -0400278 mVaryings[varyingIndex].resetRegisterAssignment();
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000279 }
280}
281
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000282// initialize/clean up previous state
283void Shader::uncompile()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000285 // set by compileToHLSL
Geoff Lang536d7262013-08-26 17:04:20 -0400286 mHlsl.clear();
287 mInfoLog.clear();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000289 // set by parseVaryings
290 mVaryings.clear();
291
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000292 mUsesMultipleRenderTargets = false;
293 mUsesFragColor = false;
294 mUsesFragData = false;
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000295 mUsesFragCoord = false;
296 mUsesFrontFacing = false;
297 mUsesPointSize = false;
298 mUsesPointCoord = false;
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000299 mUsesDepthRange = false;
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400300 mUsesFragDepth = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000301 mShaderVersion = 100;
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500302 mUsesDiscardRewriting = false;
Nicolas Capens655fe362014-04-11 13:12:34 -0400303 mUsesNestedBreak = false;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000304
305 mActiveUniforms.clear();
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000306 mActiveInterfaceBlocks.clear();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000307}
308
309void Shader::compileToHLSL(void *compiler)
310{
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000311 // ensure the compiler is loaded
312 initializeCompiler();
313
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000314 int compileOptions = SH_OBJECT_CODE;
315 std::string sourcePath;
316 if (perfActive())
317 {
318 sourcePath = getTempPath();
Geoff Lang536d7262013-08-26 17:04:20 -0400319 writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000320 compileOptions |= SH_LINE_DIRECTIVES;
321 }
322
323 int result;
324 if (sourcePath.empty())
325 {
Geoff Lang536d7262013-08-26 17:04:20 -0400326 const char* sourceStrings[] =
327 {
328 mSource.c_str(),
329 };
330
331 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000332 }
333 else
334 {
Geoff Lang536d7262013-08-26 17:04:20 -0400335 const char* sourceStrings[] =
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000336 {
337 sourcePath.c_str(),
Geoff Lang536d7262013-08-26 17:04:20 -0400338 mSource.c_str(),
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000339 };
340
Geoff Lang536d7262013-08-26 17:04:20 -0400341 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000342 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000344 size_t shaderVersion = 100;
345 ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
346
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000347 mShaderVersion = static_cast<int>(shaderVersion);
348
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000349 if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
350 {
Geoff Lang536d7262013-08-26 17:04:20 -0400351 mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
352 TRACE("\n%s", mInfoLog.c_str());
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000353 }
354 else if (result)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000356 size_t objCodeLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000357 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
Geoff Lang536d7262013-08-26 17:04:20 -0400358
359 char* outputHLSL = new char[objCodeLen];
360 ShGetObjectCode(compiler, outputHLSL);
Geoff Lang7f6562b2013-08-28 09:37:27 -0400361
362#ifdef _DEBUG
363 std::ostringstream hlslStream;
364 hlslStream << "// GLSL\n";
365 hlslStream << "//\n";
366
367 size_t curPos = 0;
368 while (curPos != std::string::npos)
369 {
370 size_t nextLine = mSource.find("\n", curPos);
371 size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
372
373 hlslStream << "// " << mSource.substr(curPos, len);
374
375 curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
376 }
377 hlslStream << "\n\n";
378 hlslStream << outputHLSL;
379 mHlsl = hlslStream.str();
380#else
Geoff Lang536d7262013-08-26 17:04:20 -0400381 mHlsl = outputHLSL;
Geoff Lang7f6562b2013-08-28 09:37:27 -0400382#endif
383
Jamie Madille294bb82014-07-17 14:16:26 -0400384 SafeDeleteArray(outputHLSL);
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000385
Jamie Madille294bb82014-07-17 14:16:26 -0400386 mActiveUniforms = *GetShaderVariables(ShGetUniforms(compiler));
shannonwoods@chromium.org3f68bf02013-05-30 00:12:43 +0000387
Jamie Madillbf9cce22014-07-18 10:33:09 -0400388 for (size_t uniformIndex = 0; uniformIndex < mActiveUniforms.size(); uniformIndex++)
389 {
390 const sh::Uniform &uniform = mActiveUniforms[uniformIndex];
391
392 unsigned int index = -1;
393 bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index);
394 UNUSED_ASSERTION_VARIABLE(result);
395 ASSERT(result);
396
397 mUniformRegisterMap[uniform.name] = index;
398 }
399
Jamie Madille294bb82014-07-17 14:16:26 -0400400 mActiveInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler));
Jamie Madilld4116ff2014-07-11 17:02:01 -0400401
402 for (size_t blockIndex = 0; blockIndex < mActiveInterfaceBlocks.size(); blockIndex++)
403 {
404 const sh::InterfaceBlock &interfaceBlock = mActiveInterfaceBlocks[blockIndex];
405
406 unsigned int index = -1;
407 bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index);
408 UNUSED_ASSERTION_VARIABLE(result);
409 ASSERT(result);
410
411 mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
412 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000413 }
414 else
415 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000416 size_t infoLogLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000417 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000418
Geoff Lang536d7262013-08-26 17:04:20 -0400419 char* infoLog = new char[infoLogLen];
420 ShGetInfoLog(compiler, infoLog);
421 mInfoLog = infoLog;
422
423 TRACE("\n%s", mInfoLog.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000424 }
425}
426
Jamie Madill5f562732014-02-14 16:41:24 -0500427rx::D3DWorkaroundType Shader::getD3DWorkarounds() const
428{
429 if (mUsesDiscardRewriting)
430 {
Nicolas Capens655fe362014-04-11 13:12:34 -0400431 // ANGLE issue 486:
432 // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
433 return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
434 }
435
436 if (mUsesNestedBreak)
437 {
438 // ANGLE issue 603:
439 // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
440 // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
441 return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
Jamie Madill5f562732014-02-14 16:41:24 -0500442 }
443
444 return rx::ANGLE_D3D_WORKAROUND_NONE;
445}
446
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000447// true if varying x has a higher priority in packing than y
Jamie Madillff0d2ba2014-05-14 13:49:10 -0400448bool Shader::compareVarying(const PackedVarying &x, const PackedVarying &y)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000449{
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400450 if (x.type == y.type)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000451 {
Jamie Madill139b9092013-08-30 13:21:06 -0400452 return x.arraySize > y.arraySize;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000453 }
454
Jamie Madill28167c62013-08-30 13:21:10 -0400455 // Special case for handling structs: we sort these to the end of the list
456 if (x.type == GL_STRUCT_ANGLEX)
457 {
458 return false;
459 }
460
Jamie Madill865d1452014-07-02 15:31:20 -0400461 if (y.type == GL_STRUCT_ANGLEX)
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400462 {
Jamie Madill865d1452014-07-02 15:31:20 -0400463 return true;
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400464 }
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000465
Jamie Madill865d1452014-07-02 15:31:20 -0400466 return gl::VariableSortOrder(x.type) <= gl::VariableSortOrder(y.type);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000467}
468
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000469int Shader::getShaderVersion() const
470{
471 return mShaderVersion;
472}
473
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000474VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
475 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000476{
477}
478
479VertexShader::~VertexShader()
480{
481}
482
Jamie Madilld4116ff2014-07-11 17:02:01 -0400483GLenum VertexShader::getType() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484{
485 return GL_VERTEX_SHADER;
486}
487
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000488void VertexShader::uncompile()
489{
490 Shader::uncompile();
491
492 // set by ParseAttributes
Jamie Madilldefb6742013-06-20 11:55:51 -0400493 mActiveAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000494}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000495
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496void VertexShader::compile()
497{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000498 uncompile();
499
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000500 compileToHLSL(mVertexCompiler);
501 parseAttributes();
Jamie Madill47fdd132013-08-30 13:21:04 -0400502 parseVaryings(mVertexCompiler);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000503}
504
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000505int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000506{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000507 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000509 int semanticIndex = 0;
Jamie Madilldefb6742013-06-20 11:55:51 -0400510 for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000511 {
Jamie Madillf2575982014-06-25 16:04:54 -0400512 const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
Jamie Madilldefb6742013-06-20 11:55:51 -0400513
514 if (attribute.name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000515 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000516 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000517 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000518
Jamie Madillf2575982014-06-25 16:04:54 -0400519 semanticIndex += VariableRegisterCount(attribute.type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000520 }
521 }
522
523 return -1;
524}
525
526void VertexShader::parseAttributes()
527{
Geoff Lang536d7262013-08-26 17:04:20 -0400528 const std::string &hlsl = getHLSL();
529 if (!hlsl.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000530 {
Jamie Madille294bb82014-07-17 14:16:26 -0400531 mActiveAttributes = *GetShaderVariables(ShGetAttributes(mVertexCompiler));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532 }
533}
534
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000535FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
536 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000537{
538}
539
540FragmentShader::~FragmentShader()
541{
542}
543
Jamie Madilld4116ff2014-07-11 17:02:01 -0400544GLenum FragmentShader::getType() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000545{
546 return GL_FRAGMENT_SHADER;
547}
548
549void FragmentShader::compile()
550{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000551 uncompile();
552
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000553 compileToHLSL(mFragmentCompiler);
Jamie Madill47fdd132013-08-30 13:21:04 -0400554 parseVaryings(mFragmentCompiler);
Jamie Madillce79dda2013-08-30 13:21:06 -0400555 std::sort(mVaryings.begin(), mVaryings.end(), compareVarying);
Jamie Madill46131a32013-06-20 11:55:50 -0400556
Geoff Lang536d7262013-08-26 17:04:20 -0400557 const std::string &hlsl = getHLSL();
558 if (!hlsl.empty())
Jamie Madill46131a32013-06-20 11:55:50 -0400559 {
Jamie Madille294bb82014-07-17 14:16:26 -0400560 mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(mFragmentCompiler));
Jamie Madill46131a32013-06-20 11:55:50 -0400561 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000562}
Jamie Madill46131a32013-06-20 11:55:50 -0400563
564void FragmentShader::uncompile()
565{
566 Shader::uncompile();
567
568 mActiveOutputVariables.clear();
569}
570
Jamie Madillf2575982014-06-25 16:04:54 -0400571const std::vector<sh::Attribute> &FragmentShader::getOutputVariables() const
Jamie Madill46131a32013-06-20 11:55:50 -0400572{
573 return mActiveOutputVariables;
574}
575
Jamie Madill68fe74a2014-05-27 12:56:01 -0400576ShShaderOutput Shader::getCompilerOutputType(GLenum shader)
577{
578 void *compiler = NULL;
579
580 switch (shader)
581 {
582 case GL_VERTEX_SHADER: compiler = mVertexCompiler; break;
583 case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break;
584 default: UNREACHABLE(); return SH_HLSL9_OUTPUT;
585 }
586
587 size_t outputType = 0;
588 ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType);
589
590 return static_cast<ShShaderOutput>(outputType);
591}
592
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593}