blob: baced15748c87ee2465208e5c7bb9a711cf0cff2 [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 Madill834e8b72014-04-11 13:33:58 -0400118const std::vector<Uniform> &Shader::getUniforms() const
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000119{
120 return mActiveUniforms;
121}
122
Jamie Madill834e8b72014-04-11 13:33:58 -0400123const std::vector<InterfaceBlock> &Shader::getInterfaceBlocks() const
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000124{
125 return mActiveInterfaceBlocks;
126}
127
Jamie Madill834e8b72014-04-11 13:33:58 -0400128std::vector<Varying> &Shader::getVaryings()
Jamie Madill5f562732014-02-14 16:41:24 -0500129{
130 return mVaryings;
131}
132
Geoff Lang536d7262013-08-26 17:04:20 -0400133bool Shader::isCompiled() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134{
Geoff Lang536d7262013-08-26 17:04:20 -0400135 return !mHlsl.empty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136}
137
Geoff Lang536d7262013-08-26 17:04:20 -0400138const std::string &Shader::getHLSL() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139{
140 return mHlsl;
141}
142
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000143void Shader::addRef()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000145 mRefCount++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146}
147
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000148void Shader::release()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000150 mRefCount--;
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000151
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000152 if (mRefCount == 0 && mDeleteStatus)
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000153 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000154 mResourceManager->deleteShader(mHandle);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000155 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000158unsigned int Shader::getRefCount() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000160 return mRefCount;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161}
162
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000163bool Shader::isFlaggedForDeletion() const
164{
165 return mDeleteStatus;
166}
167
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168void Shader::flagForDeletion()
169{
170 mDeleteStatus = true;
171}
172
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000173// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
174void Shader::initializeCompiler()
175{
176 if (!mFragmentCompiler)
177 {
178 int result = ShInitialize();
179
180 if (result)
181 {
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000182 ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
183
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000184 ShBuiltInResources resources;
185 ShInitBuiltInResources(&resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000186
187 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
shannon.woods@transgaming.com4e482042013-01-25 21:54:18 +0000188 resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000189 resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors();
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000190 resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000191 resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000192 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
shannon.woods@transgaming.com254317d2013-01-25 21:54:09 +0000193 resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors();
shannon.woods%transgaming.com@gtempaccount.come266c832013-04-13 03:31:48 +0000194 resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000195 resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport();
shannon.woods%transgaming.com@gtempaccount.come266c832013-04-13 03:31:48 +0000196 resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
Nicolas Capens46485082014-04-15 13:12:50 -0400197 resources.EXT_shader_texture_lod = 1;
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000198 // 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 +0000199 resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400200 resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
shannonwoods@chromium.org74b86cf2013-05-30 00:02:58 +0000201 // GLSL ES 3.0 constants
202 resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors();
203 resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors();
204 resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
205 resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000206
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000207 mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
208 mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000209 }
210 }
211}
212
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213void Shader::releaseCompiler()
214{
215 ShDestruct(mFragmentCompiler);
216 ShDestruct(mVertexCompiler);
217
218 mFragmentCompiler = NULL;
219 mVertexCompiler = NULL;
alokp@chromium.org90033b92010-05-24 15:02:43 +0000220
221 ShFinalize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222}
223
Jamie Madill47fdd132013-08-30 13:21:04 -0400224void Shader::parseVaryings(void *compiler)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000225{
Geoff Lang536d7262013-08-26 17:04:20 -0400226 if (!mHlsl.empty())
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000227 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400228 std::vector<Varying> *activeVaryings;
Jamie Madill47fdd132013-08-30 13:21:04 -0400229 ShGetInfoPointer(compiler, SH_ACTIVE_VARYINGS_ARRAY, reinterpret_cast<void**>(&activeVaryings));
Jamie Madilla6da33a2013-08-30 13:21:07 -0400230 mVaryings = *activeVaryings;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000231
Geoff Lang536d7262013-08-26 17:04:20 -0400232 mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos;
233 mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos;
234 mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos;
235 mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos;
236 mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
237 mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos;
238 mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos;
239 mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos;
240 mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos;
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500241 mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
Nicolas Capens655fe362014-04-11 13:12:34 -0400242 mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000243 }
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000244}
245
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000246void Shader::resetVaryingsRegisterAssignment()
247{
Jamie Madillce79dda2013-08-30 13:21:06 -0400248 for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000249 {
Jamie Madill139b9092013-08-30 13:21:06 -0400250 mVaryings[varyingIndex].resetRegisterAssignment();
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000251 }
252}
253
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000254// initialize/clean up previous state
255void Shader::uncompile()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000257 // set by compileToHLSL
Geoff Lang536d7262013-08-26 17:04:20 -0400258 mHlsl.clear();
259 mInfoLog.clear();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000261 // set by parseVaryings
262 mVaryings.clear();
263
shannon.woods%transgaming.com@gtempaccount.comaa8b5cf2013-04-13 03:31:55 +0000264 mUsesMultipleRenderTargets = false;
265 mUsesFragColor = false;
266 mUsesFragData = false;
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000267 mUsesFragCoord = false;
268 mUsesFrontFacing = false;
269 mUsesPointSize = false;
270 mUsesPointCoord = false;
shannonwoods@chromium.org03299882013-05-30 00:05:26 +0000271 mUsesDepthRange = false;
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400272 mUsesFragDepth = false;
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000273 mShaderVersion = 100;
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500274 mUsesDiscardRewriting = false;
Nicolas Capens655fe362014-04-11 13:12:34 -0400275 mUsesNestedBreak = false;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000276
277 mActiveUniforms.clear();
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000278 mActiveInterfaceBlocks.clear();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000279}
280
281void Shader::compileToHLSL(void *compiler)
282{
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000283 // ensure the compiler is loaded
284 initializeCompiler();
285
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000286 int compileOptions = SH_OBJECT_CODE;
287 std::string sourcePath;
288 if (perfActive())
289 {
290 sourcePath = getTempPath();
Geoff Lang536d7262013-08-26 17:04:20 -0400291 writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000292 compileOptions |= SH_LINE_DIRECTIVES;
293 }
294
295 int result;
296 if (sourcePath.empty())
297 {
Geoff Lang536d7262013-08-26 17:04:20 -0400298 const char* sourceStrings[] =
299 {
300 mSource.c_str(),
301 };
302
303 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000304 }
305 else
306 {
Geoff Lang536d7262013-08-26 17:04:20 -0400307 const char* sourceStrings[] =
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000308 {
309 sourcePath.c_str(),
Geoff Lang536d7262013-08-26 17:04:20 -0400310 mSource.c_str(),
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000311 };
312
Geoff Lang536d7262013-08-26 17:04:20 -0400313 result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000314 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000316 size_t shaderVersion = 100;
317 ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
318
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000319 mShaderVersion = static_cast<int>(shaderVersion);
320
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000321 if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
322 {
Geoff Lang536d7262013-08-26 17:04:20 -0400323 mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
324 TRACE("\n%s", mInfoLog.c_str());
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000325 }
326 else if (result)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000328 size_t objCodeLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000329 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
Geoff Lang536d7262013-08-26 17:04:20 -0400330
331 char* outputHLSL = new char[objCodeLen];
332 ShGetObjectCode(compiler, outputHLSL);
Geoff Lang7f6562b2013-08-28 09:37:27 -0400333
334#ifdef _DEBUG
335 std::ostringstream hlslStream;
336 hlslStream << "// GLSL\n";
337 hlslStream << "//\n";
338
339 size_t curPos = 0;
340 while (curPos != std::string::npos)
341 {
342 size_t nextLine = mSource.find("\n", curPos);
343 size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
344
345 hlslStream << "// " << mSource.substr(curPos, len);
346
347 curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
348 }
349 hlslStream << "\n\n";
350 hlslStream << outputHLSL;
351 mHlsl = hlslStream.str();
352#else
Geoff Lang536d7262013-08-26 17:04:20 -0400353 mHlsl = outputHLSL;
Geoff Lang7f6562b2013-08-28 09:37:27 -0400354#endif
355
Geoff Lang536d7262013-08-26 17:04:20 -0400356 delete[] outputHLSL;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000357
358 void *activeUniforms;
359 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
Jamie Madill834e8b72014-04-11 13:33:58 -0400360 mActiveUniforms = *(std::vector<Uniform>*)activeUniforms;
shannonwoods@chromium.org3f68bf02013-05-30 00:12:43 +0000361
362 void *activeInterfaceBlocks;
363 ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks);
Jamie Madill834e8b72014-04-11 13:33:58 -0400364 mActiveInterfaceBlocks = *(std::vector<InterfaceBlock>*)activeInterfaceBlocks;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365 }
366 else
367 {
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000368 size_t infoLogLen = 0;
alokp@chromium.org7beea402010-09-15 21:18:34 +0000369 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000370
Geoff Lang536d7262013-08-26 17:04:20 -0400371 char* infoLog = new char[infoLogLen];
372 ShGetInfoLog(compiler, infoLog);
373 mInfoLog = infoLog;
374
375 TRACE("\n%s", mInfoLog.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376 }
377}
378
Jamie Madill5f562732014-02-14 16:41:24 -0500379rx::D3DWorkaroundType Shader::getD3DWorkarounds() const
380{
381 if (mUsesDiscardRewriting)
382 {
Nicolas Capens655fe362014-04-11 13:12:34 -0400383 // ANGLE issue 486:
384 // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
385 return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
386 }
387
388 if (mUsesNestedBreak)
389 {
390 // ANGLE issue 603:
391 // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
392 // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
393 return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
Jamie Madill5f562732014-02-14 16:41:24 -0500394 }
395
396 return rx::ANGLE_D3D_WORKAROUND_NONE;
397}
398
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400399// [OpenGL ES SL 3.00.4] Section 11 p. 120
400// Vertex Outs/Fragment Ins packing priorities
401static const GLenum varyingPriorityList[] =
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000402{
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400403 // 1. Arrays of mat4 and mat4
404 GL_FLOAT_MAT4,
405
406 // Non-square matrices of type matCxR consume the same space as a square
407 // matrix of type matN where N is the greater of C and R
408 GL_FLOAT_MAT3x4,
409 GL_FLOAT_MAT4x3,
410 GL_FLOAT_MAT2x4,
411 GL_FLOAT_MAT4x2,
412
413 // 2. Arrays of mat2 and mat2 (since they occupy full rows)
414 GL_FLOAT_MAT2,
415
416 // 3. Arrays of vec4 and vec4
417 GL_FLOAT_VEC4,
418 GL_INT_VEC4,
419 GL_UNSIGNED_INT_VEC4,
420
421 // 4. Arrays of mat3 and mat3
422 GL_FLOAT_MAT3,
423 GL_FLOAT_MAT2x3,
424 GL_FLOAT_MAT3x2,
425
426 // 5. Arrays of vec3 and vec3
427 GL_FLOAT_VEC3,
428 GL_INT_VEC3,
429 GL_UNSIGNED_INT_VEC3,
430
431 // 6. Arrays of vec2 and vec2
432 GL_FLOAT_VEC2,
433 GL_INT_VEC2,
434 GL_UNSIGNED_INT_VEC2,
435
436 // 7. Arrays of float and float
437 GL_FLOAT,
438 GL_INT,
439 GL_UNSIGNED_INT,
440};
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000441
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000442// true if varying x has a higher priority in packing than y
Jamie Madill834e8b72014-04-11 13:33:58 -0400443bool Shader::compareVarying(const ShaderVariable &x, const ShaderVariable &y)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000444{
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400445 if (x.type == y.type)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000446 {
Jamie Madill139b9092013-08-30 13:21:06 -0400447 return x.arraySize > y.arraySize;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000448 }
449
Jamie Madill28167c62013-08-30 13:21:10 -0400450 // Special case for handling structs: we sort these to the end of the list
451 if (x.type == GL_STRUCT_ANGLEX)
452 {
453 return false;
454 }
455
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400456 unsigned int xPriority = GL_INVALID_INDEX;
457 unsigned int yPriority = GL_INVALID_INDEX;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000458
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400459 for (unsigned int priorityIndex = 0; priorityIndex < ArraySize(varyingPriorityList); priorityIndex++)
460 {
461 if (varyingPriorityList[priorityIndex] == x.type) xPriority = priorityIndex;
462 if (varyingPriorityList[priorityIndex] == y.type) yPriority = priorityIndex;
463 if (xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX) break;
464 }
shannonwoods@chromium.org4f35fdf2013-05-30 00:18:40 +0000465
Jamie Madillbcb6a1e2013-08-30 13:21:03 -0400466 ASSERT(xPriority != GL_INVALID_INDEX && yPriority != GL_INVALID_INDEX);
467
468 return xPriority <= yPriority;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000469}
470
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000471int Shader::getShaderVersion() const
472{
473 return mShaderVersion;
474}
475
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000476VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
477 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478{
479}
480
481VertexShader::~VertexShader()
482{
483}
484
485GLenum VertexShader::getType()
486{
487 return GL_VERTEX_SHADER;
488}
489
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000490void VertexShader::uncompile()
491{
492 Shader::uncompile();
493
494 // set by ParseAttributes
Jamie Madilldefb6742013-06-20 11:55:51 -0400495 mActiveAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000496}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000497
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000498void VertexShader::compile()
499{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000500 uncompile();
501
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000502 compileToHLSL(mVertexCompiler);
503 parseAttributes();
Jamie Madill47fdd132013-08-30 13:21:04 -0400504 parseVaryings(mVertexCompiler);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000505}
506
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000507int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000509 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000510 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000511 int semanticIndex = 0;
Jamie Madilldefb6742013-06-20 11:55:51 -0400512 for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400514 const ShaderVariable &attribute = mActiveAttributes[attributeIndex];
Jamie Madilldefb6742013-06-20 11:55:51 -0400515
516 if (attribute.name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000517 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000518 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000520
Jamie Madilldefb6742013-06-20 11:55:51 -0400521 semanticIndex += AttributeRegisterCount(attribute.type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000522 }
523 }
524
525 return -1;
526}
527
528void VertexShader::parseAttributes()
529{
Geoff Lang536d7262013-08-26 17:04:20 -0400530 const std::string &hlsl = getHLSL();
531 if (!hlsl.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400533 void *activeAttributes;
534 ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes);
Jamie Madill834e8b72014-04-11 13:33:58 -0400535 mActiveAttributes = *(std::vector<Attribute>*)activeAttributes;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000536 }
537}
538
shannon.woods@transgaming.comb73964e2013-01-25 21:49:14 +0000539FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle)
540 : Shader(manager, renderer, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000541{
542}
543
544FragmentShader::~FragmentShader()
545{
546}
547
548GLenum FragmentShader::getType()
549{
550 return GL_FRAGMENT_SHADER;
551}
552
553void FragmentShader::compile()
554{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000555 uncompile();
556
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000557 compileToHLSL(mFragmentCompiler);
Jamie Madill47fdd132013-08-30 13:21:04 -0400558 parseVaryings(mFragmentCompiler);
Jamie Madillce79dda2013-08-30 13:21:06 -0400559 std::sort(mVaryings.begin(), mVaryings.end(), compareVarying);
Jamie Madill46131a32013-06-20 11:55:50 -0400560
Geoff Lang536d7262013-08-26 17:04:20 -0400561 const std::string &hlsl = getHLSL();
562 if (!hlsl.empty())
Jamie Madill46131a32013-06-20 11:55:50 -0400563 {
564 void *activeOutputVariables;
565 ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables);
Jamie Madill834e8b72014-04-11 13:33:58 -0400566 mActiveOutputVariables = *(std::vector<Attribute>*)activeOutputVariables;
Jamie Madill46131a32013-06-20 11:55:50 -0400567 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568}
Jamie Madill46131a32013-06-20 11:55:50 -0400569
570void FragmentShader::uncompile()
571{
572 Shader::uncompile();
573
574 mActiveOutputVariables.clear();
575}
576
Jamie Madill834e8b72014-04-11 13:33:58 -0400577const std::vector<Attribute> &FragmentShader::getOutputVariables() const
Jamie Madill46131a32013-06-20 11:55:50 -0400578{
579 return mActiveOutputVariables;
580}
581
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000582}