blob: 819705465dc440af74ce53859a384e31c57b1658 [file] [log] [blame]
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001//
Geoff Lang48dcae72014-02-05 16:28:24 -05002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Program.cpp: Implements the gl::Program class. Implements GL program objects
8// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +000010#include "libGLESv2/BinaryStream.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000011#include "libGLESv2/ProgramBinary.h"
Geoff Lang04fb89a2014-06-09 15:05:36 -040012#include "libGLESv2/Framebuffer.h"
Jamie Madillaef95de2014-09-05 10:12:41 -040013#include "libGLESv2/FramebufferAttachment.h"
Geoff Lang04fb89a2014-06-09 15:05:36 -040014#include "libGLESv2/Renderbuffer.h"
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000015#include "libGLESv2/renderer/ShaderExecutable.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000016
17#include "common/debug.h"
apatrick@chromium.org90080e32012-07-09 22:15:33 +000018#include "common/version.h"
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000019#include "common/utilities.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040020#include "common/platform.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000021
22#include "libGLESv2/main.h"
23#include "libGLESv2/Shader.h"
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000024#include "libGLESv2/Program.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000025#include "libGLESv2/renderer/Renderer.h"
Brandon Jonesd8d72432014-08-22 15:11:23 -070026#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
Brandon Jonesf05cdee2014-08-27 15:24:07 -070027#include "libGLESv2/renderer/d3d/ShaderD3D.h"
Brandon Jonesc7a41042014-06-23 12:03:25 -070028#include "libGLESv2/renderer/d3d/VertexDataManager.h"
Nicolas Capense6050882013-07-08 10:43:10 -040029#include "libGLESv2/Context.h"
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +000030#include "libGLESv2/Buffer.h"
Jamie Madillc600c8c2014-05-16 11:22:21 -040031#include "common/blocklayout.h"
Jamie Madillc2141fb2013-08-30 13:21:08 -040032
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000033namespace gl
34{
shannonwoods@chromium.orgb4e07b82013-05-30 00:19:31 +000035
Jamie Madill1b2a8f92014-05-14 13:09:39 -040036namespace
shannonwoods@chromium.org6d7b61c2013-05-30 00:06:38 +000037{
38
Jamie Madill66d43d22014-07-11 17:02:03 -040039TextureType GetTextureType(GLenum samplerType)
40{
41 switch (samplerType)
42 {
43 case GL_SAMPLER_2D:
44 case GL_INT_SAMPLER_2D:
45 case GL_UNSIGNED_INT_SAMPLER_2D:
46 case GL_SAMPLER_2D_SHADOW:
47 return TEXTURE_2D;
48 case GL_SAMPLER_3D:
49 case GL_INT_SAMPLER_3D:
50 case GL_UNSIGNED_INT_SAMPLER_3D:
51 return TEXTURE_3D;
52 case GL_SAMPLER_CUBE:
53 case GL_SAMPLER_CUBE_SHADOW:
54 return TEXTURE_CUBE;
55 case GL_INT_SAMPLER_CUBE:
56 case GL_UNSIGNED_INT_SAMPLER_CUBE:
57 return TEXTURE_CUBE;
58 case GL_SAMPLER_2D_ARRAY:
59 case GL_INT_SAMPLER_2D_ARRAY:
60 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
61 case GL_SAMPLER_2D_ARRAY_SHADOW:
62 return TEXTURE_2D_ARRAY;
63 default: UNREACHABLE();
64 }
65
66 return TEXTURE_2D;
67}
68
Jamie Madill8ff21ae2014-02-04 16:04:05 -050069unsigned int ParseAndStripArrayIndex(std::string* name)
shannonwoods@chromium.org6d7b61c2013-05-30 00:06:38 +000070{
71 unsigned int subscript = GL_INVALID_INDEX;
72
73 // Strip any trailing array operator and retrieve the subscript
74 size_t open = name->find_last_of('[');
75 size_t close = name->find_last_of(']');
76 if (open != std::string::npos && close == name->length() - 1)
77 {
78 subscript = atoi(name->substr(open + 1).c_str());
79 name->erase(open);
80 }
81
82 return subscript;
83}
84
Jamie Madill3f2e61d2014-09-05 10:38:05 -040085void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
Jamie Madillc5a83002014-02-14 16:41:25 -050086{
Jamie Madill3b7e2052014-03-17 09:47:43 -040087 size_t layoutIndex = 0;
Jamie Madillc5a83002014-02-14 16:41:25 -050088 for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
89 {
Jamie Madill3b7e2052014-03-17 09:47:43 -040090 ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS);
91
Jamie Madillf2575982014-06-25 16:04:54 -040092 const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex];
Jamie Madillc5a83002014-02-14 16:41:25 -050093
94 if (shaderAttr.type != GL_NONE)
95 {
Jamie Madillac0a2672014-04-11 13:33:56 -040096 GLenum transposedType = TransposeMatrixType(shaderAttr.type);
97
98 for (size_t rowIndex = 0; static_cast<int>(rowIndex) < VariableRowCount(transposedType); rowIndex++, layoutIndex++)
Jamie Madill3b7e2052014-03-17 09:47:43 -040099 {
100 VertexFormat *defaultFormat = &inputLayout[layoutIndex];
101
Jamie Madillf2575982014-06-25 16:04:54 -0400102 defaultFormat->mType = VariableComponentType(transposedType);
Jamie Madill3b7e2052014-03-17 09:47:43 -0400103 defaultFormat->mNormalized = false;
104 defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
Jamie Madillac0a2672014-04-11 13:33:56 -0400105 defaultFormat->mComponents = VariableColumnCount(transposedType);
Jamie Madill3b7e2052014-03-17 09:47:43 -0400106 }
Jamie Madillc5a83002014-02-14 16:41:25 -0500107 }
108 }
109}
110
Jamie Madillf6be8d72014-09-05 10:38:07 -0400111std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<rx::PixelShaderOutputVariable> &shaderOutputVars)
Jamie Madill3f2e61d2014-09-05 10:38:05 -0400112{
Jamie Madill3f2e61d2014-09-05 10:38:05 -0400113 std::vector<GLenum> defaultPixelOutput(1);
Jamie Madill3f2e61d2014-09-05 10:38:05 -0400114
115 ASSERT(!shaderOutputVars.empty());
116 defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex;
117
118 return defaultPixelOutput;
119}
120
Jamie Madilla6f267f2014-08-27 11:44:15 -0400121bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
122{
123 return var.isRowMajorLayout;
124}
125
126bool IsRowMajorLayout(const sh::ShaderVariable &var)
127{
128 return false;
129}
130
shannonwoods@chromium.org6d7b61c2013-05-30 00:06:38 +0000131}
132
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400133VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
daniel@transgaming.comdb019952012-12-20 21:13:32 +0000134 : name(name), element(element), index(index)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000135{
136}
137
Geoff Lang04fb89a2014-06-09 15:05:36 -0400138ProgramBinary::VertexExecutable::VertexExecutable(const VertexFormat inputLayout[],
Jamie Madill7a29e4a2014-05-02 10:41:48 -0400139 const GLenum signature[],
Jamie Madillc5a83002014-02-14 16:41:25 -0500140 rx::ShaderExecutable *shaderExecutable)
141 : mShaderExecutable(shaderExecutable)
142{
143 for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
144 {
145 mInputs[attributeIndex] = inputLayout[attributeIndex];
Jamie Madill7a29e4a2014-05-02 10:41:48 -0400146 mSignature[attributeIndex] = signature[attributeIndex];
Jamie Madillc5a83002014-02-14 16:41:25 -0500147 }
148}
149
Jamie Madill8b4f8f82014-03-26 14:01:58 -0400150ProgramBinary::VertexExecutable::~VertexExecutable()
151{
Geoff Lang04fb89a2014-06-09 15:05:36 -0400152 SafeDelete(mShaderExecutable);
Jamie Madill8b4f8f82014-03-26 14:01:58 -0400153}
154
Jamie Madill7a29e4a2014-05-02 10:41:48 -0400155bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const
Jamie Madillc5a83002014-02-14 16:41:25 -0500156{
Jamie Madill7a29e4a2014-05-02 10:41:48 -0400157 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Jamie Madillc5a83002014-02-14 16:41:25 -0500158 {
Jamie Madill7a29e4a2014-05-02 10:41:48 -0400159 if (mSignature[attributeIndex] != signature[attributeIndex])
Jamie Madillc5a83002014-02-14 16:41:25 -0500160 {
161 return false;
162 }
163 }
164
165 return true;
166}
167
Geoff Lang04fb89a2014-06-09 15:05:36 -0400168ProgramBinary::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable)
169 : mOutputSignature(outputSignature),
170 mShaderExecutable(shaderExecutable)
171{
172}
173
174ProgramBinary::PixelExecutable::~PixelExecutable()
175{
176 SafeDelete(mShaderExecutable);
177}
178
Geoff Lang48dcae72014-02-05 16:28:24 -0500179LinkedVarying::LinkedVarying()
180{
181}
182
183LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
184 unsigned int semanticIndex, unsigned int semanticIndexCount)
185 : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount)
186{
187}
188
daniel@transgaming.come87ca002012-07-24 18:30:43 +0000189unsigned int ProgramBinary::mCurrentSerial = 1;
190
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500191ProgramBinary::ProgramBinary(rx::Renderer *renderer)
192 : RefCountObject(0),
193 mRenderer(renderer),
Jamie Madill5f562732014-02-14 16:41:24 -0500194 mDynamicHLSL(NULL),
Jamie Madillc5a83002014-02-14 16:41:25 -0500195 mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
Geoff Lang04fb89a2014-06-09 15:05:36 -0400196 mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500197 mGeometryExecutable(NULL),
198 mUsedVertexSamplerRange(0),
199 mUsedPixelSamplerRange(0),
200 mUsesPointSize(false),
201 mShaderVersion(100),
Jamie Madilld4cfa572014-07-08 10:00:32 -0400202 mDirtySamplerMapping(true),
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500203 mVertexUniformStorage(NULL),
204 mFragmentUniformStorage(NULL),
205 mValidated(false),
206 mSerial(issueSerial())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000207{
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000208 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
209 {
210 mSemanticIndex[index] = -1;
211 }
212
213 for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
214 {
215 mSamplersPS[index].active = false;
216 }
217
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000218 for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000219 {
220 mSamplersVS[index].active = false;
221 }
Jamie Madill5f562732014-02-14 16:41:24 -0500222
Brandon Jonesd8d72432014-08-22 15:11:23 -0700223 mDynamicHLSL = new rx::DynamicHLSL(renderer);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000224}
225
226ProgramBinary::~ProgramBinary()
227{
Geoff Lang04fb89a2014-06-09 15:05:36 -0400228 reset();
Jamie Madill5f562732014-02-14 16:41:24 -0500229 SafeDelete(mDynamicHLSL);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000230}
231
daniel@transgaming.come87ca002012-07-24 18:30:43 +0000232unsigned int ProgramBinary::getSerial() const
233{
234 return mSerial;
235}
236
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000237int ProgramBinary::getShaderVersion() const
238{
239 return mShaderVersion;
240}
241
daniel@transgaming.come87ca002012-07-24 18:30:43 +0000242unsigned int ProgramBinary::issueSerial()
243{
244 return mCurrentSerial++;
245}
246
Geoff Lang04fb89a2014-06-09 15:05:36 -0400247rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000248{
Jamie Madillaef95de2014-09-05 10:12:41 -0400249 std::vector<GLenum> outputs;
250
251 const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender();
252
253 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
Geoff Lang04fb89a2014-06-09 15:05:36 -0400254 {
Jamie Madillaef95de2014-09-05 10:12:41 -0400255 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
256
257 if (colorbuffer)
Geoff Lang04fb89a2014-06-09 15:05:36 -0400258 {
Jamie Madillaef95de2014-09-05 10:12:41 -0400259 outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
Geoff Lang04fb89a2014-06-09 15:05:36 -0400260 }
261 else
262 {
Jamie Madillaef95de2014-09-05 10:12:41 -0400263 outputs.push_back(GL_NONE);
Geoff Lang04fb89a2014-06-09 15:05:36 -0400264 }
265 }
266
267 return getPixelExecutableForOutputLayout(outputs);
268}
269
270rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature)
271{
272 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
273 {
274 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
275 {
276 return mPixelExecutables[executableIndex]->shaderExecutable();
277 }
278 }
279
280 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
281 outputSignature);
282
283 // Generate new pixel executable
284 InfoLog tempInfoLog;
285 rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL,
286 mTransformFeedbackLinkedVaryings,
287 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
288 mPixelWorkarounds);
289
290 if (!pixelExecutable)
291 {
292 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
293 tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
294 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
295 }
296 else
297 {
298 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
299 }
300
301 return pixelExecutable;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000302}
303
Jamie Madill7a29e4a2014-05-02 10:41:48 -0400304rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000305{
Jamie Madill7a29e4a2014-05-02 10:41:48 -0400306 GLenum signature[MAX_VERTEX_ATTRIBS];
307 mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
308
Jamie Madillc5a83002014-02-14 16:41:25 -0500309 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
310 {
Jamie Madill7a29e4a2014-05-02 10:41:48 -0400311 if (mVertexExecutables[executableIndex]->matchesSignature(signature))
Jamie Madillc5a83002014-02-14 16:41:25 -0500312 {
313 return mVertexExecutables[executableIndex]->shaderExecutable();
314 }
315 }
316
Jamie Madillc5ede1a2014-02-14 16:41:27 -0500317 // Generate new dynamic layout with attribute conversions
Geoff Lang04fb89a2014-06-09 15:05:36 -0400318 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes);
Jamie Madillc5ede1a2014-02-14 16:41:27 -0500319
Jamie Madillc5a83002014-02-14 16:41:25 -0500320 // Generate new vertex executable
321 InfoLog tempInfoLog;
Geoff Lang04fb89a2014-06-09 15:05:36 -0400322 rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL.c_str(),
Geoff Lang48dcae72014-02-05 16:28:24 -0500323 rx::SHADER_VERTEX,
324 mTransformFeedbackLinkedVaryings,
325 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
326 mVertexWorkarounds);
Jamie Madillc5a83002014-02-14 16:41:25 -0500327
328 if (!vertexExecutable)
329 {
330 std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
331 tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
332 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
333 }
334 else
335 {
Geoff Lang04fb89a2014-06-09 15:05:36 -0400336 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
Jamie Madillc5a83002014-02-14 16:41:25 -0500337 }
338
339 return vertexExecutable;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000340}
341
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500342rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000343{
344 return mGeometryExecutable;
345}
346
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000347GLuint ProgramBinary::getAttributeLocation(const char *name)
348{
349 if (name)
350 {
351 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
352 {
353 if (mLinkedAttribute[index].name == std::string(name))
354 {
355 return index;
356 }
357 }
358 }
359
360 return -1;
361}
362
363int ProgramBinary::getSemanticIndex(int attributeIndex)
364{
365 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400366
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000367 return mSemanticIndex[attributeIndex];
368}
369
370// Returns one more than the highest sampler index used.
371GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
372{
373 switch (type)
374 {
375 case SAMPLER_PIXEL:
376 return mUsedPixelSamplerRange;
377 case SAMPLER_VERTEX:
378 return mUsedVertexSamplerRange;
379 default:
380 UNREACHABLE();
381 return 0;
382 }
383}
384
daniel@transgaming.com087e5782012-09-17 21:28:47 +0000385bool ProgramBinary::usesPointSize() const
386{
387 return mUsesPointSize;
388}
389
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000390bool ProgramBinary::usesPointSpriteEmulation() const
391{
392 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
393}
394
395bool ProgramBinary::usesGeometryShader() const
396{
397 return usesPointSpriteEmulation();
398}
399
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000400// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
401// index (0-15 for the pixel shader and 0-3 for the vertex shader).
Brandon Jones43a53e22014-08-28 16:23:22 -0700402GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000403{
404 GLint logicalTextureUnit = -1;
405
406 switch (type)
407 {
408 case SAMPLER_PIXEL:
Jamie Madill66d43d22014-07-11 17:02:03 -0400409 ASSERT(samplerIndex < ArraySize(mSamplersPS));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000410
411 if (mSamplersPS[samplerIndex].active)
412 {
413 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
414 }
415 break;
416 case SAMPLER_VERTEX:
Jamie Madill66d43d22014-07-11 17:02:03 -0400417 ASSERT(samplerIndex < ArraySize(mSamplersVS));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000418
419 if (mSamplersVS[samplerIndex].active)
420 {
421 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
422 }
423 break;
424 default: UNREACHABLE();
425 }
426
Brandon Jones43a53e22014-08-28 16:23:22 -0700427 if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000428 {
429 return logicalTextureUnit;
430 }
431
432 return -1;
433}
434
435// Returns the texture type for a given Direct3D 9 sampler type and
436// index (0-15 for the pixel shader and 0-3 for the vertex shader).
437TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
438{
439 switch (type)
440 {
441 case SAMPLER_PIXEL:
Jamie Madill66d43d22014-07-11 17:02:03 -0400442 ASSERT(samplerIndex < ArraySize(mSamplersPS));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000443 ASSERT(mSamplersPS[samplerIndex].active);
444 return mSamplersPS[samplerIndex].textureType;
445 case SAMPLER_VERTEX:
Jamie Madill66d43d22014-07-11 17:02:03 -0400446 ASSERT(samplerIndex < ArraySize(mSamplersVS));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000447 ASSERT(mSamplersVS[samplerIndex].active);
448 return mSamplersVS[samplerIndex].textureType;
449 default: UNREACHABLE();
450 }
451
452 return TEXTURE_2D;
453}
454
455GLint ProgramBinary::getUniformLocation(std::string name)
456{
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500457 unsigned int subscript = ParseAndStripArrayIndex(&name);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000458
459 unsigned int numUniforms = mUniformIndex.size();
460 for (unsigned int location = 0; location < numUniforms; location++)
461 {
shannonwoods@chromium.org0ee85f82013-05-30 00:05:47 +0000462 if (mUniformIndex[location].name == name)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000463 {
shannonwoods@chromium.org0ee85f82013-05-30 00:05:47 +0000464 const int index = mUniformIndex[location].index;
465 const bool isArray = mUniforms[index]->isArray();
466
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400467 if ((isArray && mUniformIndex[location].element == subscript) ||
shannonwoods@chromium.org0ee85f82013-05-30 00:05:47 +0000468 (subscript == GL_INVALID_INDEX))
469 {
470 return location;
471 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000472 }
473 }
474
475 return -1;
476}
477
shannonwoods@chromium.orgc2ed9912013-05-30 00:05:33 +0000478GLuint ProgramBinary::getUniformIndex(std::string name)
479{
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500480 unsigned int subscript = ParseAndStripArrayIndex(&name);
shannonwoods@chromium.orgc2ed9912013-05-30 00:05:33 +0000481
482 // The app is not allowed to specify array indices other than 0 for arrays of basic types
483 if (subscript != 0 && subscript != GL_INVALID_INDEX)
484 {
485 return GL_INVALID_INDEX;
486 }
487
488 unsigned int numUniforms = mUniforms.size();
489 for (unsigned int index = 0; index < numUniforms; index++)
490 {
491 if (mUniforms[index]->name == name)
492 {
493 if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
494 {
495 return index;
496 }
497 }
498 }
499
500 return GL_INVALID_INDEX;
501}
502
shannonwoods@chromium.org42766252013-05-30 00:07:12 +0000503GLuint ProgramBinary::getUniformBlockIndex(std::string name)
504{
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500505 unsigned int subscript = ParseAndStripArrayIndex(&name);
shannonwoods@chromium.org42766252013-05-30 00:07:12 +0000506
507 unsigned int numUniformBlocks = mUniformBlocks.size();
508 for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
509 {
510 const UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
511 if (uniformBlock.name == name)
512 {
513 const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
514 if (subscript == uniformBlock.elementIndex || arrayElementZero)
515 {
516 return blockIndex;
517 }
518 }
519 }
520
521 return GL_INVALID_INDEX;
522}
523
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +0000524UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex)
525{
526 ASSERT(blockIndex < mUniformBlocks.size());
527 return mUniformBlocks[blockIndex];
528}
529
Jamie Madilld1e78c92013-06-20 11:55:50 -0400530GLint ProgramBinary::getFragDataLocation(const char *name) const
531{
532 std::string baseName(name);
533 unsigned int arrayIndex;
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500534 arrayIndex = ParseAndStripArrayIndex(&baseName);
Jamie Madilld1e78c92013-06-20 11:55:50 -0400535
536 for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
537 {
538 const VariableLocation &outputVariable = locationIt->second;
539
540 if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
541 {
542 return static_cast<GLint>(locationIt->first);
543 }
544 }
545
546 return -1;
547}
548
Geoff Lang48dcae72014-02-05 16:28:24 -0500549size_t ProgramBinary::getTransformFeedbackVaryingCount() const
550{
551 return mTransformFeedbackLinkedVaryings.size();
552}
553
554const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const
555{
556 return mTransformFeedbackLinkedVaryings[idx];
557}
558
559GLenum ProgramBinary::getTransformFeedbackBufferMode() const
560{
561 return mTransformFeedbackBufferMode;
562}
563
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000564template <typename T>
Geoff Langae1990c2014-05-12 16:57:14 -0400565static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
566{
567 ASSERT(dest != NULL);
568 ASSERT(dirtyFlag != NULL);
569
570 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
571 *dest = source;
572}
573
574template <typename T>
Jamie Madill36398922014-05-20 14:51:53 -0400575void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000576{
Jamie Madillf2575982014-06-25 16:04:54 -0400577 const int components = VariableComponentCount(targetUniformType);
578 const GLenum targetBoolType = VariableBoolVectorType(targetUniformType);
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000579
Jamie Madill36398922014-05-20 14:51:53 -0400580 LinkedUniform *targetUniform = getUniformByLocation(location);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000581
shannon.woods@transgaming.com15de0f92013-02-28 23:10:31 +0000582 int elementCount = targetUniform->elementCount();
583
shannon.woods@transgaming.com15de0f92013-02-28 23:10:31 +0000584 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
585
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000586 if (targetUniform->type == targetUniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000587 {
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000588 T *target = (T*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000589
590 for (int i = 0; i < count; i++)
591 {
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000592 for (int c = 0; c < components; c++)
593 {
Geoff Langae1990c2014-05-12 16:57:14 -0400594 SetIfDirty(target + c, v[c], &targetUniform->dirty);
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000595 }
596 for (int c = components; c < 4; c++)
597 {
Geoff Langae1990c2014-05-12 16:57:14 -0400598 SetIfDirty(target + c, T(0), &targetUniform->dirty);
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000599 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000600 target += 4;
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000601 v += components;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000602 }
603 }
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000604 else if (targetUniform->type == targetBoolType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000605 {
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000606 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000607
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000608 for (int i = 0; i < count; i++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000609 {
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000610 for (int c = 0; c < components; c++)
611 {
Geoff Langae1990c2014-05-12 16:57:14 -0400612 SetIfDirty(boolParams + c, (v[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000613 }
614 for (int c = components; c < 4; c++)
615 {
Geoff Langae1990c2014-05-12 16:57:14 -0400616 SetIfDirty(boolParams + c, GL_FALSE, &targetUniform->dirty);
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000617 }
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000618 boolParams += 4;
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000619 v += components;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000620 }
621 }
Jamie Madill36398922014-05-20 14:51:53 -0400622 else UNREACHABLE();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000623}
624
Jamie Madill36398922014-05-20 14:51:53 -0400625void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000626{
Jamie Madill36398922014-05-20 14:51:53 -0400627 setUniform(location, count, v, GL_FLOAT);
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000628}
629
Jamie Madill36398922014-05-20 14:51:53 -0400630void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000631{
Jamie Madill36398922014-05-20 14:51:53 -0400632 setUniform(location, count, v, GL_FLOAT_VEC2);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000633}
634
Jamie Madill36398922014-05-20 14:51:53 -0400635void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000636{
Jamie Madill36398922014-05-20 14:51:53 -0400637 setUniform(location, count, v, GL_FLOAT_VEC3);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000638}
639
Jamie Madill36398922014-05-20 14:51:53 -0400640void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000641{
Jamie Madill36398922014-05-20 14:51:53 -0400642 setUniform(location, count, v, GL_FLOAT_VEC4);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000643}
644
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000645template<typename T>
Geoff Langae1990c2014-05-12 16:57:14 -0400646bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000647{
Geoff Langae1990c2014-05-12 16:57:14 -0400648 bool dirty = false;
shannonwoods@chromium.org2c2b82b2013-05-30 00:15:12 +0000649 int copyWidth = std::min(targetHeight, srcWidth);
650 int copyHeight = std::min(targetWidth, srcHeight);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000651
652 for (int x = 0; x < copyWidth; x++)
653 {
654 for (int y = 0; y < copyHeight; y++)
655 {
Geoff Langae1990c2014-05-12 16:57:14 -0400656 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000657 }
658 }
659 // clear unfilled right side
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000660 for (int y = 0; y < copyWidth; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000661 {
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000662 for (int x = copyHeight; x < targetWidth; x++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000663 {
Geoff Langae1990c2014-05-12 16:57:14 -0400664 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000665 }
666 }
667 // clear unfilled bottom.
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000668 for (int y = copyWidth; y < targetHeight; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000669 {
670 for (int x = 0; x < targetWidth; x++)
671 {
Geoff Langae1990c2014-05-12 16:57:14 -0400672 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000673 }
674 }
Geoff Langae1990c2014-05-12 16:57:14 -0400675
676 return dirty;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000677}
678
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000679template<typename T>
Geoff Langae1990c2014-05-12 16:57:14 -0400680bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000681{
Geoff Langae1990c2014-05-12 16:57:14 -0400682 bool dirty = false;
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000683 int copyWidth = std::min(targetWidth, srcWidth);
684 int copyHeight = std::min(targetHeight, srcHeight);
685
686 for (int y = 0; y < copyHeight; y++)
687 {
688 for (int x = 0; x < copyWidth; x++)
689 {
Geoff Langae1990c2014-05-12 16:57:14 -0400690 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000691 }
692 }
693 // clear unfilled right side
694 for (int y = 0; y < copyHeight; y++)
695 {
696 for (int x = copyWidth; x < targetWidth; x++)
697 {
Geoff Langae1990c2014-05-12 16:57:14 -0400698 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000699 }
700 }
701 // clear unfilled bottom.
702 for (int y = copyHeight; y < targetHeight; y++)
703 {
704 for (int x = 0; x < targetWidth; x++)
705 {
Geoff Langae1990c2014-05-12 16:57:14 -0400706 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000707 }
708 }
Geoff Langae1990c2014-05-12 16:57:14 -0400709
710 return dirty;
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000711}
712
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000713template <int cols, int rows>
Jamie Madill36398922014-05-20 14:51:53 -0400714void ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000715{
Jamie Madill36398922014-05-20 14:51:53 -0400716 LinkedUniform *targetUniform = getUniformByLocation(location);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000717
daniel@transgaming.come6d12e92012-12-20 21:12:47 +0000718 int elementCount = targetUniform->elementCount();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000719
daniel@transgaming.come6d12e92012-12-20 21:12:47 +0000720 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
shannonwoods@chromium.org2c2b82b2013-05-30 00:15:12 +0000721 const unsigned int targetMatrixStride = (4 * rows);
722 GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000723
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000724 for (int i = 0; i < count; i++)
725 {
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000726 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
727 if (transpose == GL_FALSE)
728 {
Geoff Langae1990c2014-05-12 16:57:14 -0400729 targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000730 }
731 else
732 {
Geoff Langae1990c2014-05-12 16:57:14 -0400733 targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000734 }
shannonwoods@chromium.org2c2b82b2013-05-30 00:15:12 +0000735 target += targetMatrixStride;
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000736 value += cols * rows;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000737 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000738}
739
Jamie Madill36398922014-05-20 14:51:53 -0400740void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000741{
Jamie Madill36398922014-05-20 14:51:53 -0400742 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000743}
744
Jamie Madill36398922014-05-20 14:51:53 -0400745void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000746{
Jamie Madill36398922014-05-20 14:51:53 -0400747 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000748}
749
Jamie Madill36398922014-05-20 14:51:53 -0400750void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000751{
Jamie Madill36398922014-05-20 14:51:53 -0400752 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000753}
754
Jamie Madill36398922014-05-20 14:51:53 -0400755void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000756{
Jamie Madill36398922014-05-20 14:51:53 -0400757 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000758}
759
Jamie Madill36398922014-05-20 14:51:53 -0400760void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000761{
Jamie Madill36398922014-05-20 14:51:53 -0400762 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000763}
764
Jamie Madill36398922014-05-20 14:51:53 -0400765void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000766{
Jamie Madill36398922014-05-20 14:51:53 -0400767 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000768}
769
Jamie Madill36398922014-05-20 14:51:53 -0400770void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000771{
Jamie Madill36398922014-05-20 14:51:53 -0400772 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000773}
774
Jamie Madill36398922014-05-20 14:51:53 -0400775void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000776{
Jamie Madill36398922014-05-20 14:51:53 -0400777 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000778}
779
Jamie Madill36398922014-05-20 14:51:53 -0400780void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000781{
Jamie Madill36398922014-05-20 14:51:53 -0400782 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000783}
784
Jamie Madill36398922014-05-20 14:51:53 -0400785void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000786{
Jamie Madill834e8b72014-04-11 13:33:58 -0400787 LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000788
shannon.woods@transgaming.com15de0f92013-02-28 23:10:31 +0000789 int elementCount = targetUniform->elementCount();
790
shannon.woods@transgaming.com15de0f92013-02-28 23:10:31 +0000791 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
792
Nicolas Capense6050882013-07-08 10:43:10 -0400793 if (targetUniform->type == GL_INT || IsSampler(targetUniform->type))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000794 {
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000795 GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000796
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000797 for (int i = 0; i < count; i++)
798 {
Geoff Langae1990c2014-05-12 16:57:14 -0400799 SetIfDirty(target + 0, v[0], &targetUniform->dirty);
800 SetIfDirty(target + 1, 0, &targetUniform->dirty);
801 SetIfDirty(target + 2, 0, &targetUniform->dirty);
802 SetIfDirty(target + 3, 0, &targetUniform->dirty);
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000803 target += 4;
804 v += 1;
805 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000806 }
807 else if (targetUniform->type == GL_BOOL)
808 {
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000809 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000810
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000811 for (int i = 0; i < count; i++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000812 {
Geoff Langae1990c2014-05-12 16:57:14 -0400813 SetIfDirty(boolParams + 0, (v[0] == 0) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
814 SetIfDirty(boolParams + 1, GL_FALSE, &targetUniform->dirty);
815 SetIfDirty(boolParams + 2, GL_FALSE, &targetUniform->dirty);
816 SetIfDirty(boolParams + 3, GL_FALSE, &targetUniform->dirty);
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000817 boolParams += 4;
818 v += 1;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000819 }
820 }
Jamie Madill36398922014-05-20 14:51:53 -0400821 else UNREACHABLE();
Jamie Madilld4cfa572014-07-08 10:00:32 -0400822
823 // Set a special flag if we change a sampler uniform
824 if (IsSampler(targetUniform->type) &&
825 (memcmp(targetUniform->data, v, sizeof(GLint)) != 0))
826 {
827 mDirtySamplerMapping = true;
828 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000829}
830
Jamie Madill36398922014-05-20 14:51:53 -0400831void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000832{
Jamie Madill36398922014-05-20 14:51:53 -0400833 setUniform(location, count, v, GL_INT_VEC2);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000834}
835
Jamie Madill36398922014-05-20 14:51:53 -0400836void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000837{
Jamie Madill36398922014-05-20 14:51:53 -0400838 setUniform(location, count, v, GL_INT_VEC3);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000839}
840
Jamie Madill36398922014-05-20 14:51:53 -0400841void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000842{
Jamie Madill36398922014-05-20 14:51:53 -0400843 setUniform(location, count, v, GL_INT_VEC4);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000844}
845
Jamie Madill36398922014-05-20 14:51:53 -0400846void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000847{
Jamie Madill36398922014-05-20 14:51:53 -0400848 setUniform(location, count, v, GL_UNSIGNED_INT);
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000849}
850
Jamie Madill36398922014-05-20 14:51:53 -0400851void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000852{
Jamie Madill36398922014-05-20 14:51:53 -0400853 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000854}
855
Jamie Madill36398922014-05-20 14:51:53 -0400856void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000857{
Jamie Madill36398922014-05-20 14:51:53 -0400858 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000859}
860
Jamie Madill36398922014-05-20 14:51:53 -0400861void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000862{
Jamie Madill36398922014-05-20 14:51:53 -0400863 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000864}
865
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000866template <typename T>
Jamie Madill99a1e982014-08-25 15:47:54 -0400867void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000868{
Jamie Madill834e8b72014-04-11 13:33:58 -0400869 LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000870
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000871 if (IsMatrixType(targetUniform->type))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000872 {
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000873 const int rows = VariableRowCount(targetUniform->type);
874 const int cols = VariableColumnCount(targetUniform->type);
Jamie Madillf07558a2013-10-31 11:16:22 -0400875 transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows);
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000876 }
Jamie Madillf2575982014-06-25 16:04:54 -0400877 else if (uniformType == VariableComponentType(targetUniform->type))
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000878 {
Jamie Madillf2575982014-06-25 16:04:54 -0400879 unsigned int size = VariableComponentCount(targetUniform->type);
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000880 memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
881 size * sizeof(T));
882 }
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000883 else
884 {
Jamie Madillf2575982014-06-25 16:04:54 -0400885 unsigned int size = VariableComponentCount(targetUniform->type);
886 switch (VariableComponentType(targetUniform->type))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000887 {
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000888 case GL_BOOL:
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000889 {
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000890 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000891
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000892 for (unsigned int i = 0; i < size; i++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000893 {
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000894 params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000895 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000896 }
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000897 break;
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000898
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000899 case GL_FLOAT:
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000900 {
901 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
902
903 for (unsigned int i = 0; i < size; i++)
904 {
905 params[i] = static_cast<T>(floatParams[i]);
906 }
907 }
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000908 break;
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000909
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000910 case GL_INT:
911 {
912 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
913
914 for (unsigned int i = 0; i < size; i++)
915 {
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000916 params[i] = static_cast<T>(intParams[i]);
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000917 }
918 }
919 break;
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400920
shannon.woods%transgaming.com@gtempaccount.come2290122013-04-13 03:41:07 +0000921 case GL_UNSIGNED_INT:
922 {
923 GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000924
shannon.woods%transgaming.com@gtempaccount.come2290122013-04-13 03:41:07 +0000925 for (unsigned int i = 0; i < size; i++)
926 {
927 params[i] = static_cast<T>(uintParams[i]);
928 }
929 }
930 break;
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400931
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000932 default: UNREACHABLE();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000933 }
934 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000935}
936
Jamie Madill99a1e982014-08-25 15:47:54 -0400937void ProgramBinary::getUniformfv(GLint location, GLfloat *params)
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000938{
Jamie Madill99a1e982014-08-25 15:47:54 -0400939 getUniformv(location, params, GL_FLOAT);
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000940}
941
Jamie Madill99a1e982014-08-25 15:47:54 -0400942void ProgramBinary::getUniformiv(GLint location, GLint *params)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000943{
Jamie Madill99a1e982014-08-25 15:47:54 -0400944 getUniformv(location, params, GL_INT);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000945}
946
Jamie Madill99a1e982014-08-25 15:47:54 -0400947void ProgramBinary::getUniformuiv(GLint location, GLuint *params)
shannon.woods%transgaming.com@gtempaccount.come2290122013-04-13 03:41:07 +0000948{
Jamie Madill99a1e982014-08-25 15:47:54 -0400949 getUniformv(location, params, GL_UNSIGNED_INT);
shannon.woods%transgaming.com@gtempaccount.come2290122013-04-13 03:41:07 +0000950}
951
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000952void ProgramBinary::dirtyAllUniforms()
953{
954 unsigned int numUniforms = mUniforms.size();
955 for (unsigned int index = 0; index < numUniforms; index++)
956 {
957 mUniforms[index]->dirty = true;
958 }
959}
960
Jamie Madilld4cfa572014-07-08 10:00:32 -0400961void ProgramBinary::updateSamplerMapping()
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000962{
Jamie Madilld4cfa572014-07-08 10:00:32 -0400963 if (!mDirtySamplerMapping)
964 {
965 return;
966 }
967
968 mDirtySamplerMapping = false;
969
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000970 // Retrieve sampler uniform values
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500971 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000972 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400973 LinkedUniform *targetUniform = mUniforms[uniformIndex];
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000974
975 if (targetUniform->dirty)
976 {
Nicolas Capense6050882013-07-08 10:43:10 -0400977 if (IsSampler(targetUniform->type))
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000978 {
daniel@transgaming.come6d12e92012-12-20 21:12:47 +0000979 int count = targetUniform->elementCount();
Jamie Madilld4cfa572014-07-08 10:00:32 -0400980 GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data);
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000981
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +0000982 if (targetUniform->isReferencedByFragmentShader())
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000983 {
daniel@transgaming.come76b64b2013-01-11 04:10:08 +0000984 unsigned int firstIndex = targetUniform->psRegisterIndex;
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000985
986 for (int i = 0; i < count; i++)
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000987 {
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000988 unsigned int samplerIndex = firstIndex + i;
989
990 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000991 {
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000992 ASSERT(mSamplersPS[samplerIndex].active);
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000993 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000994 }
995 }
996 }
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000997
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +0000998 if (targetUniform->isReferencedByVertexShader())
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000999 {
daniel@transgaming.come76b64b2013-01-11 04:10:08 +00001000 unsigned int firstIndex = targetUniform->vsRegisterIndex;
daniel@transgaming.comf9561862012-12-20 21:12:07 +00001001
1002 for (int i = 0; i < count; i++)
1003 {
1004 unsigned int samplerIndex = firstIndex + i;
1005
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00001006 if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
daniel@transgaming.comf9561862012-12-20 21:12:07 +00001007 {
1008 ASSERT(mSamplersVS[samplerIndex].active);
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +00001009 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
daniel@transgaming.comf9561862012-12-20 21:12:07 +00001010 }
1011 }
1012 }
daniel@transgaming.comb6e55102012-12-20 21:08:14 +00001013 }
1014 }
1015 }
Jamie Madilld4cfa572014-07-08 10:00:32 -04001016}
1017
1018// Applies all the uniforms set for this program object to the renderer
1019void ProgramBinary::applyUniforms()
1020{
1021 updateSamplerMapping();
daniel@transgaming.comb6e55102012-12-20 21:08:14 +00001022
Jamie Madill8ff21ae2014-02-04 16:04:05 -05001023 mRenderer->applyUniforms(*this);
1024
1025 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
1026 {
1027 mUniforms[uniformIndex]->dirty = false;
1028 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001029}
1030
Brandon Jones43a53e22014-08-28 16:23:22 -07001031bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps)
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +00001032{
1033 const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
1034 const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
1035
1036 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1037 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1038
1039 ASSERT(boundBuffers.size() == mUniformBlocks.size());
1040
1041 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
1042 {
Jamie Madillf2575982014-06-25 16:04:54 -04001043 UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex);
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +00001044 gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
1045
1046 ASSERT(uniformBlock && uniformBuffer);
1047
Brandon Jonesd38f9262014-06-18 16:26:45 -07001048 if (uniformBuffer->getSize() < uniformBlock->dataSize)
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +00001049 {
1050 // undefined behaviour
1051 return false;
1052 }
1053
Jamie Madill04668672014-09-03 09:40:49 -04001054 // Unnecessary to apply an unreferenced standard or shared UBO
1055 if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
1056 {
1057 continue;
1058 }
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +00001059
1060 if (uniformBlock->isReferencedByVertexShader())
1061 {
1062 unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
1063 ASSERT(vertexUniformBuffers[registerIndex] == NULL);
Brandon Jones43a53e22014-08-28 16:23:22 -07001064 ASSERT(registerIndex < caps.maxVertexUniformBlocks);
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +00001065 vertexUniformBuffers[registerIndex] = uniformBuffer;
1066 }
1067
1068 if (uniformBlock->isReferencedByFragmentShader())
1069 {
1070 unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
1071 ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
Brandon Jones43a53e22014-08-28 16:23:22 -07001072 ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +00001073 fragmentUniformBuffers[registerIndex] = uniformBuffer;
1074 }
1075 }
1076
1077 return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
1078}
1079
Brandon Jones71620962014-08-20 14:04:59 -07001080bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001081{
Jamie Madilld15250e2014-09-03 09:40:44 -04001082 std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
1083 std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
Jamie Madill5f562732014-02-14 16:41:24 -05001084
1085 for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001086 {
Jamie Madillff0d2ba2014-05-14 13:49:10 -04001087 PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001088 bool matched = false;
1089
Jamie Madill54ad4f82014-09-03 09:40:46 -04001090 // Built-in varyings obey special rules
1091 if (input->isBuiltIn())
1092 {
1093 continue;
1094 }
1095
Jamie Madill5f562732014-02-14 16:41:24 -05001096 for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001097 {
Jamie Madillff0d2ba2014-05-14 13:49:10 -04001098 PackedVarying *output = &vertexVaryings[vertVaryingIndex];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001099 if (output->name == input->name)
1100 {
Jamie Madill42bcf322014-08-25 16:20:46 -04001101 if (!linkValidateVaryings(infoLog, output->name, *input, *output))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001102 {
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001103 return false;
1104 }
1105
Jamie Madill139b9092013-08-30 13:21:06 -04001106 output->registerIndex = input->registerIndex;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001107
1108 matched = true;
1109 break;
1110 }
1111 }
1112
Jamie Madill54ad4f82014-09-03 09:40:46 -04001113 // We permit unmatched, unreferenced varyings
1114 if (!matched && input->staticUse)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001115 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001116 infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001117 return false;
1118 }
1119 }
1120
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001121 return true;
1122}
1123
Geoff Lang900013c2014-07-07 11:32:19 -04001124bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001125{
Jamie Madill9c4b24a2014-06-12 13:41:17 -04001126#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
1127 return false;
1128#else
Geoff Lang900013c2014-07-07 11:32:19 -04001129 ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1130
Geoff Lang04fb89a2014-06-09 15:05:36 -04001131 reset();
1132
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001133 BinaryInputStream stream(binary, length);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001134
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001135 int format = stream.readInt<int>();
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001136 if (format != GL_PROGRAM_BINARY_ANGLE)
1137 {
1138 infoLog.append("Invalid program binary format.");
1139 return false;
1140 }
1141
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001142 int majorVersion = stream.readInt<int>();
1143 int minorVersion = stream.readInt<int>();
Jamie Madill0aa84f62014-02-13 13:17:23 -05001144 if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
Jamie Madill049108d2013-11-19 10:41:49 -05001145 {
1146 infoLog.append("Invalid program binary version.");
1147 return false;
1148 }
1149
Jamie Madill0aa84f62014-02-13 13:17:23 -05001150 unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001151 stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
Jamie Madill0aa84f62014-02-13 13:17:23 -05001152 if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001153 {
1154 infoLog.append("Invalid program binary version.");
1155 return false;
1156 }
1157
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001158 int compileFlags = stream.readInt<int>();
shannonwoods@chromium.orgf97a0842013-05-30 00:10:33 +00001159 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
1160 {
1161 infoLog.append("Mismatched compilation flags.");
1162 return false;
1163 }
1164
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001165 for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
1166 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001167 stream.readInt(&mLinkedAttribute[i].type);
1168 stream.readString(&mLinkedAttribute[i].name);
1169 stream.readInt(&mShaderAttributes[i].type);
1170 stream.readString(&mShaderAttributes[i].name);
1171 stream.readInt(&mSemanticIndex[i]);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001172 }
1173
Al Patrick3f2daa82013-08-07 12:58:57 -07001174 initAttributesByLayout();
1175
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001176 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
1177 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001178 stream.readBool(&mSamplersPS[i].active);
1179 stream.readInt(&mSamplersPS[i].logicalTextureUnit);
1180 stream.readInt(&mSamplersPS[i].textureType);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001181 }
1182
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00001183 for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001184 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001185 stream.readBool(&mSamplersVS[i].active);
1186 stream.readInt(&mSamplersVS[i].logicalTextureUnit);
1187 stream.readInt(&mSamplersVS[i].textureType);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001188 }
1189
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001190 stream.readInt(&mUsedVertexSamplerRange);
1191 stream.readInt(&mUsedPixelSamplerRange);
1192 stream.readBool(&mUsesPointSize);
1193 stream.readInt(&mShaderVersion);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001194
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001195 const unsigned int uniformCount = stream.readInt<unsigned int>();
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001196 if (stream.error())
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001197 {
1198 infoLog.append("Invalid program binary.");
1199 return false;
1200 }
1201
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001202 mUniforms.resize(uniformCount);
1203 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001204 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001205 GLenum type = stream.readInt<GLenum>();
1206 GLenum precision = stream.readInt<GLenum>();
1207 std::string name = stream.readString();
1208 unsigned int arraySize = stream.readInt<unsigned int>();
1209 int blockIndex = stream.readInt<int>();
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001210
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001211 int offset = stream.readInt<int>();
1212 int arrayStride = stream.readInt<int>();
1213 int matrixStride = stream.readInt<int>();
1214 bool isRowMajorMatrix = stream.readBool();
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001215
Jamie Madillf2575982014-06-25 16:04:54 -04001216 const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001217
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001218 LinkedUniform *uniform = new LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo);
1219
1220 stream.readInt(&uniform->psRegisterIndex);
1221 stream.readInt(&uniform->vsRegisterIndex);
1222 stream.readInt(&uniform->registerCount);
1223 stream.readInt(&uniform->registerElement);
1224
1225 mUniforms[uniformIndex] = uniform;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001226 }
1227
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001228 unsigned int uniformBlockCount = stream.readInt<unsigned int>();
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001229 if (stream.error())
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001230 {
1231 infoLog.append("Invalid program binary.");
1232 return false;
1233 }
1234
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001235 mUniformBlocks.resize(uniformBlockCount);
1236 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001237 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001238 std::string name = stream.readString();
1239 unsigned int elementIndex = stream.readInt<unsigned int>();
1240 unsigned int dataSize = stream.readInt<unsigned int>();
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001241
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001242 UniformBlock *uniformBlock = new UniformBlock(name, elementIndex, dataSize);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001243
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001244 stream.readInt(&uniformBlock->psRegisterIndex);
1245 stream.readInt(&uniformBlock->vsRegisterIndex);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001246
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001247 unsigned int numMembers = stream.readInt<unsigned int>();
1248 uniformBlock->memberUniformIndexes.resize(numMembers);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001249 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
1250 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001251 stream.readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001252 }
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001253
1254 mUniformBlocks[uniformBlockIndex] = uniformBlock;
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001255 }
1256
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001257 const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001258 if (stream.error())
1259 {
1260 infoLog.append("Invalid program binary.");
1261 return false;
1262 }
1263
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001264 mUniformIndex.resize(uniformIndexCount);
1265 for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001266 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001267 stream.readString(&mUniformIndex[uniformIndexIndex].name);
1268 stream.readInt(&mUniformIndex[uniformIndexIndex].element);
1269 stream.readInt(&mUniformIndex[uniformIndexIndex].index);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001270 }
1271
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001272 stream.readInt(&mTransformFeedbackBufferMode);
1273 const unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
1274 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
1275 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
Geoff Lang48dcae72014-02-05 16:28:24 -05001276 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001277 LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
Geoff Lang48dcae72014-02-05 16:28:24 -05001278
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001279 stream.readString(&varying.name);
1280 stream.readInt(&varying.type);
1281 stream.readInt(&varying.size);
1282 stream.readString(&varying.semanticName);
1283 stream.readInt(&varying.semanticIndex);
1284 stream.readInt(&varying.semanticIndexCount);
Geoff Lang48dcae72014-02-05 16:28:24 -05001285 }
1286
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001287 stream.readString(&mVertexHLSL);
Jamie Madillc5a83002014-02-14 16:41:25 -05001288
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001289 stream.readInt(&mVertexWorkarounds);
1290
1291 const unsigned int vertexShaderCount = stream.readInt<unsigned int>();
Jamie Madillc5a83002014-02-14 16:41:25 -05001292 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
1293 {
Jamie Madill7a29e4a2014-05-02 10:41:48 -04001294 VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
Jamie Madillc5a83002014-02-14 16:41:25 -05001295
Jamie Madill7a29e4a2014-05-02 10:41:48 -04001296 for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
Jamie Madillc5a83002014-02-14 16:41:25 -05001297 {
Jamie Madill7a29e4a2014-05-02 10:41:48 -04001298 VertexFormat *vertexInput = &inputLayout[inputIndex];
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001299 stream.readInt(&vertexInput->mType);
1300 stream.readInt(&vertexInput->mNormalized);
1301 stream.readInt(&vertexInput->mComponents);
1302 stream.readBool(&vertexInput->mPureInteger);
Jamie Madillc5a83002014-02-14 16:41:25 -05001303 }
1304
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001305 unsigned int vertexShaderSize = stream.readInt<unsigned int>();
Geoff Lang04fb89a2014-06-09 15:05:36 -04001306 const unsigned char *vertexShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset();
Jamie Madillc5a83002014-02-14 16:41:25 -05001307 rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
Geoff Lang48dcae72014-02-05 16:28:24 -05001308 vertexShaderSize, rx::SHADER_VERTEX,
1309 mTransformFeedbackLinkedVaryings,
1310 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
Jamie Madillc5a83002014-02-14 16:41:25 -05001311 if (!shaderExecutable)
1312 {
1313 infoLog.append("Could not create vertex shader.");
1314 return false;
1315 }
1316
Jamie Madill7a29e4a2014-05-02 10:41:48 -04001317 // generated converted input layout
1318 GLenum signature[MAX_VERTEX_ATTRIBS];
1319 mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
1320
1321 // add new binary
Geoff Lang04fb89a2014-06-09 15:05:36 -04001322 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
Jamie Madillc5a83002014-02-14 16:41:25 -05001323
1324 stream.skip(vertexShaderSize);
1325 }
1326
Geoff Lang04fb89a2014-06-09 15:05:36 -04001327 stream.readString(&mPixelHLSL);
1328 stream.readInt(&mPixelWorkarounds);
1329 stream.readBool(&mUsesFragDepth);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001330
Geoff Lang04fb89a2014-06-09 15:05:36 -04001331 const size_t pixelShaderKeySize = stream.readInt<unsigned int>();
1332 mPixelShaderKey.resize(pixelShaderKeySize);
1333 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
Jamie Madillc5a83002014-02-14 16:41:25 -05001334 {
Geoff Lang04fb89a2014-06-09 15:05:36 -04001335 stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
1336 stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
1337 stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
1338 stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
Jamie Madillc5a83002014-02-14 16:41:25 -05001339 }
Geoff Lang04fb89a2014-06-09 15:05:36 -04001340
1341 const size_t pixelShaderCount = stream.readInt<unsigned int>();
1342 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
1343 {
1344 const size_t outputCount = stream.readInt<unsigned int>();
1345 std::vector<GLenum> outputs(outputCount);
1346 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
1347 {
1348 stream.readInt(&outputs[outputIndex]);
1349 }
1350
1351 const size_t pixelShaderSize = stream.readInt<unsigned int>();
1352 const unsigned char *pixelShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset();
1353 rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
1354 rx::SHADER_PIXEL,
1355 mTransformFeedbackLinkedVaryings,
1356 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
1357 if (!shaderExecutable)
1358 {
1359 infoLog.append("Could not create pixel shader.");
1360 return false;
1361 }
1362
1363 // add new binary
1364 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
1365
1366 stream.skip(pixelShaderSize);
1367 }
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001368
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001369 unsigned int geometryShaderSize = stream.readInt<unsigned int>();
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001370
Jamie Madillc5a83002014-02-14 16:41:25 -05001371 if (geometryShaderSize > 0)
1372 {
1373 const char *geometryShaderFunction = (const char*) binary + stream.offset();
1374 mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
Geoff Lang48dcae72014-02-05 16:28:24 -05001375 geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
1376 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
Jamie Madillc5a83002014-02-14 16:41:25 -05001377 if (!mGeometryExecutable)
1378 {
1379 infoLog.append("Could not create geometry shader.");
Jamie Madillc5a83002014-02-14 16:41:25 -05001380 return false;
1381 }
1382 stream.skip(geometryShaderSize);
1383 }
1384
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001385 const char *ptr = (const char*) binary + stream.offset();
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001386
daniel@transgaming.com36038542012-11-28 20:59:26 +00001387 const GUID *binaryIdentifier = (const GUID *) ptr;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001388 ptr += sizeof(GUID);
1389
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +00001390 GUID identifier = mRenderer->getAdapterIdentifier();
1391 if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001392 {
1393 infoLog.append("Invalid program binary.");
1394 return false;
1395 }
1396
Jamie Madill8ff21ae2014-02-04 16:04:05 -05001397 initializeUniformStorage();
1398
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001399 return true;
Jamie Madill9c4b24a2014-06-12 13:41:17 -04001400#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001401}
1402
Geoff Lang900013c2014-07-07 11:32:19 -04001403bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001404{
Geoff Lang900013c2014-07-07 11:32:19 -04001405 if (binaryFormat)
1406 {
1407 *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1408 }
1409
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001410 BinaryOutputStream stream;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001411
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001412 stream.writeInt(GL_PROGRAM_BINARY_ANGLE);
1413 stream.writeInt(ANGLE_MAJOR_VERSION);
1414 stream.writeInt(ANGLE_MINOR_VERSION);
Ehsan Akhgariaa7e1662014-07-05 21:13:11 -04001415 stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001416 stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001417
1418 for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
1419 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001420 stream.writeInt(mLinkedAttribute[i].type);
1421 stream.writeString(mLinkedAttribute[i].name);
1422 stream.writeInt(mShaderAttributes[i].type);
1423 stream.writeString(mShaderAttributes[i].name);
1424 stream.writeInt(mSemanticIndex[i]);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001425 }
1426
1427 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
1428 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001429 stream.writeInt(mSamplersPS[i].active);
1430 stream.writeInt(mSamplersPS[i].logicalTextureUnit);
1431 stream.writeInt(mSamplersPS[i].textureType);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001432 }
1433
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00001434 for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001435 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001436 stream.writeInt(mSamplersVS[i].active);
1437 stream.writeInt(mSamplersVS[i].logicalTextureUnit);
1438 stream.writeInt(mSamplersVS[i].textureType);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001439 }
1440
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001441 stream.writeInt(mUsedVertexSamplerRange);
1442 stream.writeInt(mUsedPixelSamplerRange);
1443 stream.writeInt(mUsesPointSize);
1444 stream.writeInt(mShaderVersion);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001445
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001446 stream.writeInt(mUniforms.size());
Jamie Madillc5a83002014-02-14 16:41:25 -05001447 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001448 {
Jamie Madill834e8b72014-04-11 13:33:58 -04001449 const LinkedUniform &uniform = *mUniforms[uniformIndex];
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001450
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001451 stream.writeInt(uniform.type);
1452 stream.writeInt(uniform.precision);
1453 stream.writeString(uniform.name);
1454 stream.writeInt(uniform.arraySize);
1455 stream.writeInt(uniform.blockIndex);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001456
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001457 stream.writeInt(uniform.blockInfo.offset);
1458 stream.writeInt(uniform.blockInfo.arrayStride);
1459 stream.writeInt(uniform.blockInfo.matrixStride);
1460 stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001461
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001462 stream.writeInt(uniform.psRegisterIndex);
1463 stream.writeInt(uniform.vsRegisterIndex);
1464 stream.writeInt(uniform.registerCount);
1465 stream.writeInt(uniform.registerElement);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001466 }
1467
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001468 stream.writeInt(mUniformBlocks.size());
Jamie Madillc5a83002014-02-14 16:41:25 -05001469 for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001470 {
1471 const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
1472
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001473 stream.writeString(uniformBlock.name);
1474 stream.writeInt(uniformBlock.elementIndex);
1475 stream.writeInt(uniformBlock.dataSize);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001476
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001477 stream.writeInt(uniformBlock.memberUniformIndexes.size());
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001478 for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
1479 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001480 stream.writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001481 }
1482
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001483 stream.writeInt(uniformBlock.psRegisterIndex);
1484 stream.writeInt(uniformBlock.vsRegisterIndex);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001485 }
1486
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001487 stream.writeInt(mUniformIndex.size());
Jamie Madillc5a83002014-02-14 16:41:25 -05001488 for (size_t i = 0; i < mUniformIndex.size(); ++i)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001489 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001490 stream.writeString(mUniformIndex[i].name);
1491 stream.writeInt(mUniformIndex[i].element);
1492 stream.writeInt(mUniformIndex[i].index);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001493 }
1494
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001495 stream.writeInt(mTransformFeedbackBufferMode);
1496 stream.writeInt(mTransformFeedbackLinkedVaryings.size());
Geoff Lang48dcae72014-02-05 16:28:24 -05001497 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
1498 {
1499 const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
1500
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001501 stream.writeString(varying.name);
1502 stream.writeInt(varying.type);
1503 stream.writeInt(varying.size);
1504 stream.writeString(varying.semanticName);
1505 stream.writeInt(varying.semanticIndex);
1506 stream.writeInt(varying.semanticIndexCount);
Geoff Lang48dcae72014-02-05 16:28:24 -05001507 }
1508
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001509 stream.writeString(mVertexHLSL);
1510 stream.writeInt(mVertexWorkarounds);
Jamie Madillc5a83002014-02-14 16:41:25 -05001511
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001512 stream.writeInt(mVertexExecutables.size());
Jamie Madillc5a83002014-02-14 16:41:25 -05001513 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
1514 {
1515 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
1516
1517 for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
1518 {
1519 const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001520 stream.writeInt(vertexInput.mType);
1521 stream.writeInt(vertexInput.mNormalized);
1522 stream.writeInt(vertexInput.mComponents);
1523 stream.writeInt(vertexInput.mPureInteger);
Jamie Madillc5a83002014-02-14 16:41:25 -05001524 }
1525
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001526 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1527 stream.writeInt(vertexShaderSize);
Jamie Madillc5a83002014-02-14 16:41:25 -05001528
Jamie Madillcafa2102014-07-23 16:43:22 -04001529 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001530 stream.writeBytes(vertexBlob, vertexShaderSize);
Jamie Madillc5a83002014-02-14 16:41:25 -05001531 }
1532
Geoff Lang04fb89a2014-06-09 15:05:36 -04001533 stream.writeString(mPixelHLSL);
1534 stream.writeInt(mPixelWorkarounds);
1535 stream.writeInt(mUsesFragDepth);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001536
Geoff Lang04fb89a2014-06-09 15:05:36 -04001537 stream.writeInt(mPixelShaderKey.size());
1538 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < mPixelShaderKey.size(); pixelShaderKeyIndex++)
1539 {
Jamie Madillf6be8d72014-09-05 10:38:07 -04001540 const rx::PixelShaderOutputVariable &variable = mPixelShaderKey[pixelShaderKeyIndex];
Geoff Lang04fb89a2014-06-09 15:05:36 -04001541 stream.writeInt(variable.type);
1542 stream.writeString(variable.name);
1543 stream.writeString(variable.source);
1544 stream.writeInt(variable.outputIndex);
1545 }
1546
1547 stream.writeInt(mPixelExecutables.size());
1548 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
1549 {
1550 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
1551
1552 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
1553 stream.writeInt(outputs.size());
1554 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1555 {
1556 stream.writeInt(outputs[outputIndex]);
1557 }
1558
1559 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1560 stream.writeInt(pixelShaderSize);
1561
Jamie Madillcafa2102014-07-23 16:43:22 -04001562 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
Geoff Lang04fb89a2014-06-09 15:05:36 -04001563 stream.writeBytes(pixelBlob, pixelShaderSize);
1564 }
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001565
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001566 size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
1567 stream.writeInt(geometryShaderSize);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001568
Jamie Madillc5a83002014-02-14 16:41:25 -05001569 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
1570 {
Jamie Madillcafa2102014-07-23 16:43:22 -04001571 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
Jamie Madill1b2a8f92014-05-14 13:09:39 -04001572 stream.writeBytes(geometryBlob, geometryShaderSize);
Jamie Madillc5a83002014-02-14 16:41:25 -05001573 }
1574
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +00001575 GUID identifier = mRenderer->getAdapterIdentifier();
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001576
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001577 GLsizei streamLength = stream.length();
1578 const void *streamData = stream.data();
1579
Jamie Madillc5a83002014-02-14 16:41:25 -05001580 GLsizei totalLength = streamLength + sizeof(GUID);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001581 if (totalLength > bufSize)
1582 {
1583 if (length)
1584 {
1585 *length = 0;
1586 }
1587
1588 return false;
1589 }
1590
1591 if (binary)
1592 {
1593 char *ptr = (char*) binary;
1594
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001595 memcpy(ptr, streamData, streamLength);
1596 ptr += streamLength;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001597
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +00001598 memcpy(ptr, &identifier, sizeof(GUID));
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001599 ptr += sizeof(GUID);
1600
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001601 ASSERT(ptr - totalLength == binary);
1602 }
1603
1604 if (length)
1605 {
1606 *length = totalLength;
1607 }
1608
1609 return true;
1610}
1611
1612GLint ProgramBinary::getLength()
1613{
1614 GLint length;
Geoff Lang900013c2014-07-07 11:32:19 -04001615 if (save(NULL, NULL, INT_MAX, &length))
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001616 {
1617 return length;
1618 }
1619 else
1620 {
1621 return 0;
1622 }
1623}
1624
Brandon Jones71620962014-08-20 14:04:59 -07001625bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
Brandon Jones43a53e22014-08-28 16:23:22 -07001626 const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001627{
1628 if (!fragmentShader || !fragmentShader->isCompiled())
1629 {
1630 return false;
1631 }
Brandon Jones71620962014-08-20 14:04:59 -07001632 ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001633
1634 if (!vertexShader || !vertexShader->isCompiled())
1635 {
1636 return false;
1637 }
Brandon Jones71620962014-08-20 14:04:59 -07001638 ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001639
Geoff Lang04fb89a2014-06-09 15:05:36 -04001640 reset();
1641
Geoff Lang48dcae72014-02-05 16:28:24 -05001642 mTransformFeedbackBufferMode = transformFeedbackBufferMode;
1643
Jamie Madill2ad1dc42014-09-03 09:40:45 -04001644 rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
1645 rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +00001646
Brandon Jonesf05cdee2014-08-27 15:24:07 -07001647 mShaderVersion = vertexShaderD3D->getShaderVersion();
Geoff Lang04fb89a2014-06-09 15:05:36 -04001648
Brandon Jonesf05cdee2014-08-27 15:24:07 -07001649 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
1650 mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
1651
1652 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
1653 mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001654
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +00001655 // Map the varyings to the register file
Brandon Jonesd8d72432014-08-22 15:11:23 -07001656 rx::VaryingPacking packing = { NULL };
Brandon Jones71620962014-08-20 14:04:59 -07001657 int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +00001658
1659 if (registers < 0)
1660 {
1661 return false;
1662 }
1663
Jamie Madill5f562732014-02-14 16:41:24 -05001664 if (!linkVaryings(infoLog, fragmentShader, vertexShader))
1665 {
1666 return false;
1667 }
1668
Brandon Jonesf05cdee2014-08-27 15:24:07 -07001669 mUsesPointSize = vertexShaderD3D->usesPointSize();
Geoff Lang48dcae72014-02-05 16:28:24 -05001670 std::vector<LinkedVarying> linkedVaryings;
Geoff Lang04fb89a2014-06-09 15:05:36 -04001671 if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, mPixelHLSL, mVertexHLSL,
Brandon Jones71620962014-08-20 14:04:59 -07001672 fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
Geoff Lang04fb89a2014-06-09 15:05:36 -04001673 &linkedVaryings, &mOutputVariables, &mPixelShaderKey, &mUsesFragDepth))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001674 {
1675 return false;
1676 }
1677
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00001678 bool success = true;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001679
Jamie Madilld15250e2014-09-03 09:40:44 -04001680 if (!linkAttributes(infoLog, attributeBindings, vertexShader))
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00001681 {
1682 success = false;
1683 }
1684
Brandon Jones43a53e22014-08-28 16:23:22 -07001685 if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps))
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00001686 {
daniel@transgaming.com68aaf932012-12-20 21:13:16 +00001687 success = false;
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00001688 }
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00001689
shannonwoods@chromium.org03299882013-05-30 00:05:26 +00001690 // special case for gl_DepthRange, the only built-in uniform (also a struct)
Brandon Jonesf05cdee2014-08-27 15:24:07 -07001691 if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange())
shannonwoods@chromium.org03299882013-05-30 00:05:26 +00001692 {
Jamie Madille04a5b72014-07-18 10:33:12 -04001693 const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo();
1694
1695 mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo));
1696 mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo));
1697 mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo));
shannonwoods@chromium.org03299882013-05-30 00:05:26 +00001698 }
1699
Brandon Jones43a53e22014-08-28 16:23:22 -07001700 if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps))
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00001701 {
1702 success = false;
1703 }
1704
Geoff Lang48dcae72014-02-05 16:28:24 -05001705 if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
Brandon Jones43a53e22014-08-28 16:23:22 -07001706 transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps))
Geoff Lang48dcae72014-02-05 16:28:24 -05001707 {
1708 success = false;
1709 }
1710
Jamie Madilld1ac3c92013-06-25 10:40:30 -04001711 if (success)
1712 {
Jamie Madillc5a83002014-02-14 16:41:25 -05001713 VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS];
Jamie Madill3f2e61d2014-09-05 10:38:05 -04001714 GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
Jamie Madillc5a83002014-02-14 16:41:25 -05001715 rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
Geoff Lang04fb89a2014-06-09 15:05:36 -04001716
Jamie Madill3f2e61d2014-09-05 10:38:05 -04001717 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(mPixelShaderKey);
Geoff Lang04fb89a2014-06-09 15:05:36 -04001718 rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput);
Jamie Madilld1ac3c92013-06-25 10:40:30 -04001719
1720 if (usesGeometryShader())
1721 {
Brandon Jones71620962014-08-20 14:04:59 -07001722 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
Geoff Lang48dcae72014-02-05 16:28:24 -05001723 mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY,
1724 mTransformFeedbackLinkedVaryings,
1725 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
1726 rx::ANGLE_D3D_WORKAROUND_NONE);
Jamie Madilld1ac3c92013-06-25 10:40:30 -04001727 }
1728
Geoff Lang04fb89a2014-06-09 15:05:36 -04001729 if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
Jamie Madilld1ac3c92013-06-25 10:40:30 -04001730 {
1731 infoLog.append("Failed to create D3D shaders.");
1732 success = false;
Geoff Lang04fb89a2014-06-09 15:05:36 -04001733 reset();
Jamie Madilld1ac3c92013-06-25 10:40:30 -04001734 }
1735 }
1736
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00001737 return success;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001738}
1739
1740// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
Jamie Madilld15250e2014-09-03 09:40:44 -04001741bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001742{
Jamie Madill2ad1dc42014-09-03 09:40:45 -04001743 const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
Brandon Jonesf05cdee2014-08-27 15:24:07 -07001744
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001745 unsigned int usedLocations = 0;
Jamie Madill54ad4f82014-09-03 09:40:46 -04001746 const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001747
1748 // Link attributes that have a binding location
Jamie Madill54ad4f82014-09-03 09:40:46 -04001749 for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001750 {
Jamie Madill54ad4f82014-09-03 09:40:46 -04001751 const sh::Attribute &attribute = shaderAttributes[attributeIndex];
1752
1753 ASSERT(attribute.staticUse);
1754
Jamie Madilleba4eff2013-06-20 11:55:51 -04001755 const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001756
Jamie Madill2c7d84a2014-02-14 16:41:26 -05001757 mShaderAttributes[attributeIndex] = attribute;
1758
Jamie Madilleba4eff2013-06-20 11:55:51 -04001759 if (location != -1) // Set by glBindAttribLocation or by location layout qualifier
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001760 {
Jamie Madillf2575982014-06-25 16:04:54 -04001761 const int rows = VariableRegisterCount(attribute.type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001762
1763 if (rows + location > MAX_VERTEX_ATTRIBS)
1764 {
Jamie Madilldefb6742013-06-20 11:55:51 -04001765 infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001766
1767 return false;
1768 }
1769
Jamie Madilleba4eff2013-06-20 11:55:51 -04001770 for (int row = 0; row < rows; row++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001771 {
Jamie Madilleba4eff2013-06-20 11:55:51 -04001772 const int rowLocation = location + row;
Jamie Madillf2575982014-06-25 16:04:54 -04001773 sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation];
Jamie Madilleba4eff2013-06-20 11:55:51 -04001774
1775 // In GLSL 3.00, attribute aliasing produces a link error
1776 // In GLSL 1.00, attribute aliasing is allowed
1777 if (mShaderVersion >= 300)
1778 {
1779 if (!linkedAttribute.name.empty())
1780 {
1781 infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation);
1782 return false;
1783 }
1784 }
1785
1786 linkedAttribute = attribute;
1787 usedLocations |= 1 << rowLocation;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001788 }
1789 }
1790 }
1791
1792 // Link attributes that don't have a binding location
Jamie Madill54ad4f82014-09-03 09:40:46 -04001793 for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001794 {
Jamie Madill54ad4f82014-09-03 09:40:46 -04001795 const sh::Attribute &attribute = shaderAttributes[attributeIndex];
1796
1797 ASSERT(attribute.staticUse);
1798
Jamie Madilleba4eff2013-06-20 11:55:51 -04001799 const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001800
Jamie Madilleba4eff2013-06-20 11:55:51 -04001801 if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001802 {
Jamie Madillf2575982014-06-25 16:04:54 -04001803 int rows = VariableRegisterCount(attribute.type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001804 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
1805
1806 if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
1807 {
Jamie Madilldefb6742013-06-20 11:55:51 -04001808 infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001809
1810 return false; // Fail to link
1811 }
1812
Jamie Madilldefb6742013-06-20 11:55:51 -04001813 mLinkedAttribute[availableIndex] = attribute;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001814 }
1815 }
1816
1817 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
1818 {
Brandon Jonesf05cdee2014-08-27 15:24:07 -07001819 int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
Jamie Madillf2575982014-06-25 16:04:54 -04001820 int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001821
1822 for (int r = 0; r < rows; r++)
1823 {
1824 mSemanticIndex[attributeIndex++] = index++;
1825 }
1826 }
1827
Al Patrick3f2daa82013-08-07 12:58:57 -07001828 initAttributesByLayout();
1829
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001830 return true;
1831}
1832
Jamie Madillf2575982014-06-25 16:04:54 -04001833bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
1834 const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001835{
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001836 if (vertexVariable.type != fragmentVariable.type)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001837 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001838 infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001839 return false;
1840 }
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001841 if (vertexVariable.arraySize != fragmentVariable.arraySize)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001842 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001843 infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001844 return false;
1845 }
Jamie Madill28167c62013-08-30 13:21:10 -04001846 if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001847 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001848 infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str());
Jamie Madill010fffa2013-06-20 11:55:53 -04001849 return false;
1850 }
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001851
Jamie Madill42bcf322014-08-25 16:20:46 -04001852 if (vertexVariable.fields.size() != fragmentVariable.fields.size())
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001853 {
Jamie Madill42bcf322014-08-25 16:20:46 -04001854 infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str());
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001855 return false;
1856 }
Jamie Madill42bcf322014-08-25 16:20:46 -04001857 const unsigned int numMembers = vertexVariable.fields.size();
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001858 for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
1859 {
Jamie Madill42bcf322014-08-25 16:20:46 -04001860 const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex];
1861 const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex];
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001862
1863 if (vertexMember.name != fragmentMember.name)
1864 {
Jamie Madill28167c62013-08-30 13:21:10 -04001865 infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')",
Jamie Madill42bcf322014-08-25 16:20:46 -04001866 memberIndex, variableName.c_str(),
1867 vertexMember.name.c_str(), fragmentMember.name.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001868 return false;
1869 }
1870
Jamie Madill42bcf322014-08-25 16:20:46 -04001871 const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." +
1872 vertexMember.name + "'";
1873
1874 if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision))
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001875 {
1876 return false;
1877 }
1878 }
1879
1880 return true;
1881}
1882
Jamie Madill42bcf322014-08-25 16:20:46 -04001883bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001884{
Jamie Madill28167c62013-08-30 13:21:10 -04001885 if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001886 {
1887 return false;
1888 }
1889
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001890 return true;
1891}
1892
Jamie Madill42bcf322014-08-25 16:20:46 -04001893bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
Jamie Madill28167c62013-08-30 13:21:10 -04001894{
1895 if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
1896 {
1897 return false;
1898 }
1899
1900 if (vertexVarying.interpolation != fragmentVarying.interpolation)
1901 {
1902 infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
1903 return false;
1904 }
1905
Jamie Madill28167c62013-08-30 13:21:10 -04001906 return true;
1907}
1908
Jamie Madill42bcf322014-08-25 16:20:46 -04001909bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001910{
Jamie Madill28167c62013-08-30 13:21:10 -04001911 if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001912 {
1913 return false;
1914 }
1915
Jamie Madilla6f267f2014-08-27 11:44:15 -04001916 if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001917 {
1918 infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
1919 return false;
1920 }
1921
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001922 return true;
1923}
1924
Brandon Jones43a53e22014-08-28 16:23:22 -07001925bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001926{
Jamie Madill2ad1dc42014-09-03 09:40:45 -04001927 const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation());
1928 const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation());
Brandon Jonesf05cdee2014-08-27 15:24:07 -07001929
Jamie Madilld15250e2014-09-03 09:40:44 -04001930 const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms();
1931 const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms();
Jamie Madillbf9cce22014-07-18 10:33:09 -04001932
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001933 // Check that uniforms defined in the vertex and fragment shaders are identical
Jamie Madillf2575982014-06-25 16:04:54 -04001934 typedef std::map<std::string, const sh::Uniform*> UniformMap;
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001935 UniformMap linkedUniforms;
1936
1937 for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++)
1938 {
Jamie Madillf2575982014-06-25 16:04:54 -04001939 const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex];
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001940 linkedUniforms[vertexUniform.name] = &vertexUniform;
1941 }
1942
1943 for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++)
1944 {
Jamie Madillf2575982014-06-25 16:04:54 -04001945 const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex];
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001946 UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name);
1947 if (entry != linkedUniforms.end())
1948 {
Jamie Madillf2575982014-06-25 16:04:54 -04001949 const sh::Uniform &vertexUniform = *entry->second;
Jamie Madill28167c62013-08-30 13:21:10 -04001950 const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
Jamie Madill42bcf322014-08-25 16:20:46 -04001951 if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00001952 {
1953 return false;
1954 }
1955 }
1956 }
1957
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00001958 for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001959 {
Jamie Madillbf9cce22014-07-18 10:33:09 -04001960 const sh::Uniform &uniform = vertexUniforms[uniformIndex];
Jamie Madill54ad4f82014-09-03 09:40:46 -04001961
1962 if (uniform.staticUse)
1963 {
1964 defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
1965 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001966 }
1967
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00001968 for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
daniel@transgaming.coma418ef12012-11-28 20:58:22 +00001969 {
Jamie Madillbf9cce22014-07-18 10:33:09 -04001970 const sh::Uniform &uniform = fragmentUniforms[uniformIndex];
Jamie Madill54ad4f82014-09-03 09:40:46 -04001971
1972 if (uniform.staticUse)
1973 {
1974 defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
1975 }
Jamie Madill66d43d22014-07-11 17:02:03 -04001976 }
1977
Brandon Jones43a53e22014-08-28 16:23:22 -07001978 if (!indexUniforms(infoLog, caps))
Jamie Madill66d43d22014-07-11 17:02:03 -04001979 {
1980 return false;
daniel@transgaming.coma418ef12012-11-28 20:58:22 +00001981 }
daniel@transgaming.com68aaf932012-12-20 21:13:16 +00001982
Jamie Madill8ff21ae2014-02-04 16:04:05 -05001983 initializeUniformStorage();
1984
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001985 return true;
1986}
1987
Jamie Madillbf9cce22014-07-18 10:33:09 -04001988void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister)
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00001989{
Brandon Jonesf05cdee2014-08-27 15:24:07 -07001990 ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader);
Jamie Madille04a5b72014-07-18 10:33:12 -04001991 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madillbf9cce22014-07-18 10:33:09 -04001992 encoder.skipRegisters(uniformRegister);
1993
1994 defineUniform(shader, uniform, uniform.name, &encoder);
Jamie Madill5b130dc2014-07-11 17:02:05 -04001995}
1996
Jamie Madill42bcf322014-08-25 16:20:46 -04001997void ProgramBinary::defineUniform(GLenum shader, const sh::ShaderVariable &uniform,
Jamie Madillbf9cce22014-07-18 10:33:09 -04001998 const std::string &fullName, sh::HLSLBlockEncoder *encoder)
Jamie Madill5b130dc2014-07-11 17:02:05 -04001999{
2000 if (uniform.isStruct())
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002001 {
Jamie Madillbf9cce22014-07-18 10:33:09 -04002002 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002003 {
Jamie Madillbf9cce22014-07-18 10:33:09 -04002004 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002005
Jamie Madillbf9cce22014-07-18 10:33:09 -04002006 encoder->enterAggregateType();
Jamie Madillc600c8c2014-05-16 11:22:21 -04002007
Jamie Madill5b130dc2014-07-11 17:02:05 -04002008 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002009 {
Jamie Madill42bcf322014-08-25 16:20:46 -04002010 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
Jamie Madillbf9cce22014-07-18 10:33:09 -04002011 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
2012
2013 defineUniform(shader, field, fieldFullName, encoder);
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002014 }
Jamie Madillbf9cce22014-07-18 10:33:09 -04002015
2016 encoder->exitAggregateType();
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002017 }
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002018 }
Jamie Madill66d43d22014-07-11 17:02:03 -04002019 else // Not a struct
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002020 {
Jamie Madillbf9cce22014-07-18 10:33:09 -04002021 // Arrays are treated as aggregate types
2022 if (uniform.isArray())
2023 {
2024 encoder->enterAggregateType();
2025 }
2026
Jamie Madill5b130dc2014-07-11 17:02:05 -04002027 LinkedUniform *linkedUniform = getUniformByName(fullName);
Jamie Madill1b2a8f92014-05-14 13:09:39 -04002028
Jamie Madill66d43d22014-07-11 17:02:03 -04002029 if (!linkedUniform)
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002030 {
Jamie Madill5b130dc2014-07-11 17:02:05 -04002031 linkedUniform = new LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
Jamie Madill66d43d22014-07-11 17:02:03 -04002032 -1, sh::BlockMemberInfo::getDefaultBlockInfo());
2033 ASSERT(linkedUniform);
Jamie Madillbf9cce22014-07-18 10:33:09 -04002034 linkedUniform->registerElement = encoder->getCurrentElement();
Jamie Madill66d43d22014-07-11 17:02:03 -04002035 mUniforms.push_back(linkedUniform);
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002036 }
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002037
Jamie Madillbf9cce22014-07-18 10:33:09 -04002038 ASSERT(linkedUniform->registerElement == encoder->getCurrentElement());
2039
Jamie Madill66d43d22014-07-11 17:02:03 -04002040 if (shader == GL_FRAGMENT_SHADER)
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002041 {
Jamie Madillbf9cce22014-07-18 10:33:09 -04002042 linkedUniform->psRegisterIndex = encoder->getCurrentRegister();
Jamie Madill66d43d22014-07-11 17:02:03 -04002043 }
2044 else if (shader == GL_VERTEX_SHADER)
2045 {
Jamie Madillbf9cce22014-07-18 10:33:09 -04002046 linkedUniform->vsRegisterIndex = encoder->getCurrentRegister();
Jamie Madill66d43d22014-07-11 17:02:03 -04002047 }
2048 else UNREACHABLE();
Jamie Madillbf9cce22014-07-18 10:33:09 -04002049
2050 // Advance the uniform offset, to track registers allocation for structs
2051 encoder->encodeType(uniform.type, uniform.arraySize, false);
2052
2053 // Arrays are treated as aggregate types
2054 if (uniform.isArray())
2055 {
2056 encoder->exitAggregateType();
2057 }
Jamie Madill66d43d22014-07-11 17:02:03 -04002058 }
2059}
2060
Brandon Jones43a53e22014-08-28 16:23:22 -07002061bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps)
Jamie Madill66d43d22014-07-11 17:02:03 -04002062{
2063 ASSERT(IsSampler(uniform.type));
2064 ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
2065
2066 if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
2067 {
2068 if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
Geoff Lang301d1612014-07-09 10:34:37 -04002069 &mUsedVertexSamplerRange, caps.maxVertexTextureImageUnits))
Jamie Madill66d43d22014-07-11 17:02:03 -04002070 {
2071 infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).",
Geoff Lang301d1612014-07-09 10:34:37 -04002072 caps.maxVertexTextureImageUnits);
Jamie Madill66d43d22014-07-11 17:02:03 -04002073 return false;
2074 }
2075
Geoff Lang301d1612014-07-09 10:34:37 -04002076 unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors;
Jamie Madill66d43d22014-07-11 17:02:03 -04002077 if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
2078 {
2079 infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)",
Geoff Lang301d1612014-07-09 10:34:37 -04002080 caps.maxVertexUniformVectors);
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002081 return false;
2082 }
2083 }
Jamie Madill66d43d22014-07-11 17:02:03 -04002084
2085 if (uniform.psRegisterIndex != GL_INVALID_INDEX)
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002086 {
Jamie Madill66d43d22014-07-11 17:02:03 -04002087 if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
Geoff Lang301d1612014-07-09 10:34:37 -04002088 &mUsedPixelSamplerRange, caps.maxTextureImageUnits))
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002089 {
Jamie Madill66d43d22014-07-11 17:02:03 -04002090 infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
Geoff Lang301d1612014-07-09 10:34:37 -04002091 caps.maxTextureImageUnits);
Jamie Madill66d43d22014-07-11 17:02:03 -04002092 return false;
2093 }
2094
Geoff Lang301d1612014-07-09 10:34:37 -04002095 unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors;
Jamie Madill66d43d22014-07-11 17:02:03 -04002096 if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
2097 {
2098 infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)",
Geoff Lang301d1612014-07-09 10:34:37 -04002099 caps.maxFragmentUniformVectors);
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002100 return false;
2101 }
2102 }
Jamie Madill66d43d22014-07-11 17:02:03 -04002103
2104 return true;
2105}
2106
Brandon Jones43a53e22014-08-28 16:23:22 -07002107bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps)
Jamie Madill66d43d22014-07-11 17:02:03 -04002108{
2109 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
2110 {
2111 const LinkedUniform &uniform = *mUniforms[uniformIndex];
2112
2113 if (IsSampler(uniform.type))
2114 {
Brandon Jones43a53e22014-08-28 16:23:22 -07002115 if (!indexSamplerUniform(uniform, infoLog, caps))
Jamie Madill66d43d22014-07-11 17:02:03 -04002116 {
2117 return false;
2118 }
2119 }
2120
2121 for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++)
2122 {
2123 mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex));
2124 }
2125 }
2126
2127 return true;
2128}
2129
2130bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex,
2131 GLenum samplerType,
2132 unsigned int samplerCount,
2133 Sampler *outArray,
2134 GLuint *usedRange,
2135 unsigned int limit)
2136{
2137 unsigned int samplerIndex = startSamplerIndex;
2138
2139 do
2140 {
2141 if (samplerIndex < limit)
2142 {
2143 outArray[samplerIndex].active = true;
2144 outArray[samplerIndex].textureType = GetTextureType(samplerType);
2145 outArray[samplerIndex].logicalTextureUnit = 0;
2146 *usedRange = std::max(samplerIndex + 1, *usedRange);
2147 }
2148 else
2149 {
2150 return false;
2151 }
2152
2153 samplerIndex++;
2154 } while (samplerIndex < startSamplerIndex + samplerCount);
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002155
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002156 return true;
2157}
2158
Jamie Madillf2575982014-06-25 16:04:54 -04002159bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002160{
2161 const char* blockName = vertexInterfaceBlock.name.c_str();
2162
2163 // validate blocks for the same member types
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002164 if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002165 {
2166 infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
2167 return false;
2168 }
2169
2170 if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
2171 {
2172 infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
2173 return false;
2174 }
2175
Jamie Madill9060a4e2013-08-12 16:22:57 -07002176 if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
2177 {
2178 infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
2179 return false;
2180 }
2181
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002182 const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002183 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
2184 {
Jamie Madillf2575982014-06-25 16:04:54 -04002185 const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
2186 const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002187
2188 if (vertexMember.name != fragmentMember.name)
2189 {
Jamie Madill28167c62013-08-30 13:21:10 -04002190 infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002191 blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
2192 return false;
2193 }
2194
Jamie Madill42bcf322014-08-25 16:20:46 -04002195 std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
2196 if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002197 {
2198 return false;
2199 }
2200 }
2201
2202 return true;
2203}
2204
Brandon Jones43a53e22014-08-28 16:23:22 -07002205bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002206{
Jamie Madilld15250e2014-09-03 09:40:44 -04002207 const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
2208 const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
Jamie Madilld4116ff2014-07-11 17:02:01 -04002209
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002210 // Check that interface blocks defined in the vertex and fragment shaders are identical
Jamie Madillf2575982014-06-25 16:04:54 -04002211 typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002212 UniformBlockMap linkedUniformBlocks;
2213
2214 for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
2215 {
Jamie Madillf2575982014-06-25 16:04:54 -04002216 const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002217 linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
2218 }
2219
2220 for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
2221 {
Jamie Madillf2575982014-06-25 16:04:54 -04002222 const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002223 UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
2224 if (entry != linkedUniformBlocks.end())
2225 {
Jamie Madillf2575982014-06-25 16:04:54 -04002226 const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002227 if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
2228 {
2229 return false;
2230 }
2231 }
2232 }
2233
2234 for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
2235 {
Jamie Madill54ad4f82014-09-03 09:40:46 -04002236 const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
2237
Jamie Madill04668672014-09-03 09:40:49 -04002238 // Note: shared and std140 layouts are always considered active
2239 if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002240 {
Jamie Madill54ad4f82014-09-03 09:40:46 -04002241 if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
2242 {
2243 return false;
2244 }
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002245 }
2246 }
2247
2248 for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
2249 {
Jamie Madill54ad4f82014-09-03 09:40:46 -04002250 const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
2251
Jamie Madill04668672014-09-03 09:40:49 -04002252 // Note: shared and std140 layouts are always considered active
2253 if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002254 {
Jamie Madill54ad4f82014-09-03 09:40:46 -04002255 if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
2256 {
2257 return false;
2258 }
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002259 }
2260 }
2261
2262 return true;
2263}
2264
Geoff Lang48dcae72014-02-05 16:28:24 -05002265bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
2266 const std::vector<std::string> &transformFeedbackVaryingNames,
2267 GLenum transformFeedbackBufferMode,
Brandon Jones43a53e22014-08-28 16:23:22 -07002268 std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
2269 const Caps &caps) const
Geoff Lang48dcae72014-02-05 16:28:24 -05002270{
2271 size_t totalComponents = 0;
Geoff Lang05881a02014-07-10 14:05:30 -04002272
Geoff Lang48dcae72014-02-05 16:28:24 -05002273 // Gather the linked varyings that are used for transform feedback, they should all exist.
2274 outTransformFeedbackLinkedVaryings->clear();
2275 for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++)
2276 {
2277 bool found = false;
2278 for (size_t j = 0; j < linkedVaryings.size(); j++)
2279 {
2280 if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name)
2281 {
2282 for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++)
2283 {
2284 if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name)
2285 {
2286 infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str());
2287 return false;
2288 }
2289 }
2290
2291 size_t componentCount = linkedVaryings[j].semanticIndexCount * 4;
2292 if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
Geoff Lang05881a02014-07-10 14:05:30 -04002293 componentCount > caps.maxTransformFeedbackSeparateComponents)
Geoff Lang48dcae72014-02-05 16:28:24 -05002294 {
2295 infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).",
Geoff Lang05881a02014-07-10 14:05:30 -04002296 linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents);
Geoff Lang48dcae72014-02-05 16:28:24 -05002297 return false;
2298 }
2299
2300 totalComponents += componentCount;
2301
2302 outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]);
2303 found = true;
2304 break;
2305 }
2306 }
2307
2308 // All transform feedback varyings are expected to exist since packVaryings checks for them.
2309 ASSERT(found);
2310 }
2311
Geoff Lang05881a02014-07-10 14:05:30 -04002312 if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents)
Geoff Lang48dcae72014-02-05 16:28:24 -05002313 {
2314 infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).",
Geoff Lang05881a02014-07-10 14:05:30 -04002315 totalComponents, caps.maxTransformFeedbackInterleavedComponents);
Geoff Lang48dcae72014-02-05 16:28:24 -05002316 return false;
2317 }
2318
2319 return true;
2320}
2321
Jamie Madill42bcf322014-08-25 16:20:46 -04002322template <typename VarT>
2323void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
Jamie Madilla6f267f2014-08-27 11:44:15 -04002324 sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
2325 bool inRowMajorLayout)
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002326{
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002327 for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002328 {
Jamie Madill42bcf322014-08-25 16:20:46 -04002329 const VarT &field = fields[uniformIndex];
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002330 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002331
Jamie Madille04a5b72014-07-18 10:33:12 -04002332 if (field.isStruct())
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002333 {
Jamie Madilla6f267f2014-08-27 11:44:15 -04002334 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
2335
Jamie Madille04a5b72014-07-18 10:33:12 -04002336 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +00002337 {
Jamie Madille04a5b72014-07-18 10:33:12 -04002338 encoder->enterAggregateType();
2339
2340 const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
Jamie Madilla6f267f2014-08-27 11:44:15 -04002341 defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout);
Jamie Madille04a5b72014-07-18 10:33:12 -04002342
2343 encoder->exitAggregateType();
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +00002344 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002345 }
2346 else
2347 {
Jamie Madilla6f267f2014-08-27 11:44:15 -04002348 bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout);
2349
2350 sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
Jamie Madille04a5b72014-07-18 10:33:12 -04002351
Jamie Madill834e8b72014-04-11 13:33:58 -04002352 LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
Jamie Madille04a5b72014-07-18 10:33:12 -04002353 blockIndex, memberInfo);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002354
2355 // add to uniform list, but not index, since uniform block uniforms have no location
2356 blockUniformIndexes->push_back(mUniforms.size());
2357 mUniforms.push_back(newUniform);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002358 }
2359 }
2360}
2361
Brandon Jones43a53e22014-08-28 16:23:22 -07002362bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002363{
Brandon Jonesf05cdee2014-08-27 15:24:07 -07002364 const rx::ShaderD3D* shaderD3D = rx::ShaderD3D::makeShaderD3D(shader.getImplementation());
2365
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002366 // create uniform block entries if they do not exist
2367 if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
2368 {
2369 std::vector<unsigned int> blockUniformIndexes;
2370 const unsigned int blockIndex = mUniformBlocks.size();
2371
2372 // define member uniforms
Jamie Madille04a5b72014-07-18 10:33:12 -04002373 sh::BlockLayoutEncoder *encoder = NULL;
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002374
Jamie Madille04a5b72014-07-18 10:33:12 -04002375 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
2376 {
2377 encoder = new sh::Std140BlockEncoder;
2378 }
2379 else
2380 {
2381 encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
2382 }
2383 ASSERT(encoder);
2384
Jamie Madilla6f267f2014-08-27 11:44:15 -04002385 defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout);
Jamie Madille04a5b72014-07-18 10:33:12 -04002386
2387 size_t dataSize = encoder->getBlockSize();
Jamie Madillfc43d272014-07-11 17:02:02 -04002388
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002389 // create all the uniform blocks
2390 if (interfaceBlock.arraySize > 0)
2391 {
2392 for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
2393 {
Jamie Madillfc43d272014-07-11 17:02:02 -04002394 UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize);
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002395 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
2396 mUniformBlocks.push_back(newUniformBlock);
2397 }
2398 }
2399 else
2400 {
Jamie Madillfc43d272014-07-11 17:02:02 -04002401 UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize);
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002402 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
2403 mUniformBlocks.push_back(newUniformBlock);
2404 }
2405 }
2406
Jamie Madill04668672014-09-03 09:40:49 -04002407 if (interfaceBlock.staticUse)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002408 {
Jamie Madill04668672014-09-03 09:40:49 -04002409 // Assign registers to the uniform blocks
2410 const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
2411 const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
2412 ASSERT(blockIndex != GL_INVALID_INDEX);
2413 ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002414
Jamie Madill04668672014-09-03 09:40:49 -04002415 unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
2416
2417 for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002418 {
Jamie Madill04668672014-09-03 09:40:49 -04002419 UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
2420 ASSERT(uniformBlock->name == interfaceBlock.name);
2421
2422 if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(),
2423 interfaceBlockRegister + uniformBlockElement, caps))
2424 {
2425 return false;
2426 }
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002427 }
2428 }
2429
2430 return true;
2431}
2432
Brandon Jones43a53e22014-08-28 16:23:22 -07002433bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002434{
2435 if (shader == GL_VERTEX_SHADER)
2436 {
2437 uniformBlock->vsRegisterIndex = registerIndex;
Geoff Lang301d1612014-07-09 10:34:37 -04002438 if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002439 {
Geoff Lang301d1612014-07-09 10:34:37 -04002440 infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002441 return false;
2442 }
2443 }
2444 else if (shader == GL_FRAGMENT_SHADER)
2445 {
2446 uniformBlock->psRegisterIndex = registerIndex;
Geoff Lang301d1612014-07-09 10:34:37 -04002447 if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002448 {
Geoff Lang301d1612014-07-09 10:34:37 -04002449 infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002450 return false;
2451 }
2452 }
2453 else UNREACHABLE();
2454
2455 return true;
2456}
2457
Jamie Madill1b2a8f92014-05-14 13:09:39 -04002458bool ProgramBinary::isValidated() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002459{
2460 return mValidated;
2461}
2462
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002463void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002464{
2465 // Skip over inactive attributes
2466 unsigned int activeAttribute = 0;
2467 unsigned int attribute;
2468 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2469 {
2470 if (mLinkedAttribute[attribute].name.empty())
2471 {
2472 continue;
2473 }
2474
2475 if (activeAttribute == index)
2476 {
2477 break;
2478 }
2479
2480 activeAttribute++;
2481 }
2482
2483 if (bufsize > 0)
2484 {
2485 const char *string = mLinkedAttribute[attribute].name.c_str();
2486
2487 strncpy(name, string, bufsize);
2488 name[bufsize - 1] = '\0';
2489
2490 if (length)
2491 {
2492 *length = strlen(name);
2493 }
2494 }
2495
2496 *size = 1; // Always a single 'type' instance
2497
2498 *type = mLinkedAttribute[attribute].type;
2499}
2500
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002501GLint ProgramBinary::getActiveAttributeCount() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002502{
2503 int count = 0;
2504
2505 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2506 {
2507 if (!mLinkedAttribute[attributeIndex].name.empty())
2508 {
2509 count++;
2510 }
2511 }
2512
2513 return count;
2514}
2515
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002516GLint ProgramBinary::getActiveAttributeMaxLength() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002517{
2518 int maxLength = 0;
2519
2520 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2521 {
2522 if (!mLinkedAttribute[attributeIndex].name.empty())
2523 {
2524 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2525 }
2526 }
2527
2528 return maxLength;
2529}
2530
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002531void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002532{
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002533 ASSERT(index < mUniforms.size()); // index must be smaller than getActiveUniformCount()
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002534
2535 if (bufsize > 0)
2536 {
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002537 std::string string = mUniforms[index]->name;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002538
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002539 if (mUniforms[index]->isArray())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002540 {
2541 string += "[0]";
2542 }
2543
2544 strncpy(name, string.c_str(), bufsize);
2545 name[bufsize - 1] = '\0';
2546
2547 if (length)
2548 {
2549 *length = strlen(name);
2550 }
2551 }
2552
daniel@transgaming.come6d12e92012-12-20 21:12:47 +00002553 *size = mUniforms[index]->elementCount();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002554
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002555 *type = mUniforms[index]->type;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002556}
2557
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002558GLint ProgramBinary::getActiveUniformCount() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002559{
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002560 return mUniforms.size();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002561}
2562
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002563GLint ProgramBinary::getActiveUniformMaxLength() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002564{
2565 int maxLength = 0;
2566
2567 unsigned int numUniforms = mUniforms.size();
2568 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
2569 {
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002570 if (!mUniforms[uniformIndex]->name.empty())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002571 {
2572 int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
2573 if (mUniforms[uniformIndex]->isArray())
2574 {
2575 length += 3; // Counting in "[0]".
2576 }
2577 maxLength = std::max(length, maxLength);
2578 }
2579 }
2580
2581 return maxLength;
2582}
2583
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00002584GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
2585{
Jamie Madill834e8b72014-04-11 13:33:58 -04002586 const gl::LinkedUniform& uniform = *mUniforms[index];
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00002587
2588 switch (pname)
2589 {
2590 case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
2591 case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount());
shannonwoods@chromium.orgb1dc1b62013-05-30 00:15:43 +00002592 case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0));
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00002593 case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex;
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00002594
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00002595 case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset;
2596 case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
2597 case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
2598 case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00002599
2600 default:
2601 UNREACHABLE();
2602 break;
2603 }
2604 return 0;
2605}
2606
Jamie Madill36398922014-05-20 14:51:53 -04002607bool ProgramBinary::isValidUniformLocation(GLint location) const
2608{
2609 ASSERT(rx::IsIntegerCastSafe<GLint>(mUniformIndex.size()));
2610 return (location >= 0 && location < static_cast<GLint>(mUniformIndex.size()));
2611}
2612
2613LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const
2614{
2615 ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformIndex.size());
2616 return mUniforms[mUniformIndex[location].index];
2617}
2618
Jamie Madill66d43d22014-07-11 17:02:03 -04002619LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const
2620{
2621 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
2622 {
2623 if (mUniforms[uniformIndex]->name == name)
2624 {
2625 return mUniforms[uniformIndex];
2626 }
2627 }
2628
2629 return NULL;
2630}
2631
shannonwoods@chromium.orgbeb02782013-05-30 00:07:28 +00002632void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
2633{
2634 ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
2635
2636 const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
2637
2638 if (bufSize > 0)
2639 {
2640 std::string string = uniformBlock.name;
2641
2642 if (uniformBlock.isArrayElement())
2643 {
Jamie Madill5f562732014-02-14 16:41:24 -05002644 string += ArrayString(uniformBlock.elementIndex);
shannonwoods@chromium.orgbeb02782013-05-30 00:07:28 +00002645 }
2646
2647 strncpy(uniformBlockName, string.c_str(), bufSize);
2648 uniformBlockName[bufSize - 1] = '\0';
2649
2650 if (length)
2651 {
2652 *length = strlen(uniformBlockName);
2653 }
2654 }
2655}
2656
shannonwoods@chromium.orge7317ca2013-05-30 00:07:35 +00002657void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
2658{
2659 ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
2660
2661 const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
2662
2663 switch (pname)
2664 {
2665 case GL_UNIFORM_BLOCK_DATA_SIZE:
2666 *params = static_cast<GLint>(uniformBlock.dataSize);
2667 break;
2668 case GL_UNIFORM_BLOCK_NAME_LENGTH:
shannonwoods@chromium.org932cc6b2013-05-30 00:15:37 +00002669 *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
shannonwoods@chromium.orge7317ca2013-05-30 00:07:35 +00002670 break;
2671 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
2672 *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
2673 break;
2674 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
2675 {
2676 for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
2677 {
2678 params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
2679 }
2680 }
2681 break;
2682 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
2683 *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
2684 break;
2685 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
2686 *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
2687 break;
2688 default: UNREACHABLE();
2689 }
2690}
2691
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +00002692GLuint ProgramBinary::getActiveUniformBlockCount() const
2693{
2694 return mUniformBlocks.size();
2695}
2696
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +00002697GLuint ProgramBinary::getActiveUniformBlockMaxLength() const
2698{
2699 unsigned int maxLength = 0;
2700
2701 unsigned int numUniformBlocks = mUniformBlocks.size();
2702 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
2703 {
2704 const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
2705 if (!uniformBlock.name.empty())
2706 {
2707 const unsigned int length = uniformBlock.name.length() + 1;
2708
2709 // Counting in "[0]".
2710 const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
2711
2712 maxLength = std::max(length + arrayLength, maxLength);
2713 }
2714 }
2715
2716 return maxLength;
2717}
2718
Brandon Jones43a53e22014-08-28 16:23:22 -07002719void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002720{
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002721 applyUniforms();
Brandon Jones43a53e22014-08-28 16:23:22 -07002722 if (!validateSamplers(&infoLog, caps))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002723 {
2724 mValidated = false;
2725 }
2726 else
2727 {
2728 mValidated = true;
2729 }
2730}
2731
Brandon Jones43a53e22014-08-28 16:23:22 -07002732bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002733{
2734 // if any two active samplers in a program are of different types, but refer to the same
2735 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2736 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
Jamie Madilld4cfa572014-07-08 10:00:32 -04002737 updateSamplerMapping();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002738
Brandon Jones43a53e22014-08-28 16:23:22 -07002739 const unsigned int maxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00002740 TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002741
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00002742 for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002743 {
2744 textureUnitType[i] = TEXTURE_UNKNOWN;
2745 }
2746
2747 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
2748 {
2749 if (mSamplersPS[i].active)
2750 {
2751 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
Jamie Madill1b2a8f92014-05-14 13:09:39 -04002752
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002753 if (unit >= maxCombinedTextureImageUnits)
2754 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002755 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002756 {
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00002757 infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002758 }
2759
2760 return false;
2761 }
2762
2763 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2764 {
2765 if (mSamplersPS[i].textureType != textureUnitType[unit])
2766 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002767 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002768 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002769 infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002770 }
2771
2772 return false;
2773 }
2774 }
2775 else
2776 {
2777 textureUnitType[unit] = mSamplersPS[i].textureType;
2778 }
2779 }
2780 }
2781
2782 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
2783 {
2784 if (mSamplersVS[i].active)
2785 {
2786 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
Jamie Madill1b2a8f92014-05-14 13:09:39 -04002787
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002788 if (unit >= maxCombinedTextureImageUnits)
2789 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002790 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002791 {
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00002792 infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002793 }
2794
2795 return false;
2796 }
2797
2798 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2799 {
2800 if (mSamplersVS[i].textureType != textureUnitType[unit])
2801 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002802 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002803 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002804 infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002805 }
2806
2807 return false;
2808 }
2809 }
2810 else
2811 {
2812 textureUnitType[unit] = mSamplersVS[i].textureType;
2813 }
2814 }
2815 }
2816
2817 return true;
2818}
2819
apatrick@chromium.org90080e32012-07-09 22:15:33 +00002820ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
2821{
2822}
2823
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00002824struct AttributeSorter
2825{
2826 AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
2827 : originalIndices(semanticIndices)
2828 {
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00002829 }
2830
2831 bool operator()(int a, int b)
2832 {
Jamie Madill03181ab2013-12-18 12:56:06 -05002833 if (originalIndices[a] == -1) return false;
2834 if (originalIndices[b] == -1) return true;
2835 return (originalIndices[a] < originalIndices[b]);
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00002836 }
2837
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00002838 const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
2839};
2840
Al Patrick3f2daa82013-08-07 12:58:57 -07002841void ProgramBinary::initAttributesByLayout()
2842{
2843 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
2844 {
2845 mAttributesByLayout[i] = i;
2846 }
2847
2848 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
2849}
2850
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00002851void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
2852{
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00002853 rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
2854
2855 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
2856 {
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00002857 oldTranslatedAttributes[i] = attributes[i];
2858 }
2859
2860 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
2861 {
Al Patrick3f2daa82013-08-07 12:58:57 -07002862 int oldIndex = mAttributesByLayout[i];
2863 sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00002864 attributes[i] = oldTranslatedAttributes[oldIndex];
2865 }
2866}
2867
Jamie Madill8ff21ae2014-02-04 16:04:05 -05002868void ProgramBinary::initializeUniformStorage()
2869{
2870 // Compute total default block size
2871 unsigned int vertexRegisters = 0;
2872 unsigned int fragmentRegisters = 0;
2873 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
2874 {
Jamie Madill834e8b72014-04-11 13:33:58 -04002875 const LinkedUniform &uniform = *mUniforms[uniformIndex];
Jamie Madill8ff21ae2014-02-04 16:04:05 -05002876
2877 if (!IsSampler(uniform.type))
2878 {
2879 if (uniform.isReferencedByVertexShader())
2880 {
2881 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
2882 }
2883 if (uniform.isReferencedByFragmentShader())
2884 {
2885 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
2886 }
2887 }
2888 }
2889
2890 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
2891 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
2892}
2893
Geoff Lang04fb89a2014-06-09 15:05:36 -04002894void ProgramBinary::reset()
2895{
2896 mVertexHLSL.clear();
2897 mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
2898 SafeDeleteContainer(mVertexExecutables);
2899
2900 mPixelHLSL.clear();
2901 mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
2902 mUsesFragDepth = false;
2903 mPixelShaderKey.clear();
2904 SafeDeleteContainer(mPixelExecutables);
2905
2906 SafeDelete(mGeometryExecutable);
2907
2908 mTransformFeedbackBufferMode = GL_NONE;
2909 mTransformFeedbackLinkedVaryings.clear();
2910
2911 for (size_t i = 0; i < ArraySize(mSamplersPS); i++)
2912 {
2913 mSamplersPS[i] = Sampler();
2914 }
2915 for (size_t i = 0; i < ArraySize(mSamplersVS); i++)
2916 {
2917 mSamplersVS[i] = Sampler();
2918 }
2919 mUsedVertexSamplerRange = 0;
2920 mUsedPixelSamplerRange = 0;
2921 mUsesPointSize = false;
2922 mShaderVersion = 0;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002923 mDirtySamplerMapping = true;
Geoff Lang04fb89a2014-06-09 15:05:36 -04002924
2925 SafeDeleteContainer(mUniforms);
2926 SafeDeleteContainer(mUniformBlocks);
2927 mUniformIndex.clear();
2928 mOutputVariables.clear();
2929 SafeDelete(mVertexUniformStorage);
2930 SafeDelete(mFragmentUniformStorage);
2931
2932 mValidated = false;
2933}
2934
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002935}