blob: e98487e306f3dd61e273b8b078536367c82abaa8 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002//
daniel@transgaming.coma390e1e2013-01-11 04:09:39 +00003// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00004// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// Program.cpp: Implements the gl::Program class. Implements GL program objects
9// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
10
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +000011#include "libGLESv2/BinaryStream.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000012#include "libGLESv2/ProgramBinary.h"
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000013#include "libGLESv2/renderer/ShaderExecutable.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000014
15#include "common/debug.h"
apatrick@chromium.org90080e32012-07-09 22:15:33 +000016#include "common/version.h"
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000017#include "common/utilities.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000018
19#include "libGLESv2/main.h"
20#include "libGLESv2/Shader.h"
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000021#include "libGLESv2/Program.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000022#include "libGLESv2/renderer/Renderer.h"
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +000023#include "libGLESv2/renderer/VertexDataManager.h"
Nicolas Capense6050882013-07-08 10:43:10 -040024#include "libGLESv2/Context.h"
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +000025#include "libGLESv2/Buffer.h"
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +000026
Geoff Lang17732822013-08-29 13:46:49 -040027#include "compiler/translator/HLSLLayoutEncoder.h"
Jamie Madillc2141fb2013-08-30 13:21:08 -040028
daniel@transgaming.com88853c52012-12-20 20:56:40 +000029#undef near
30#undef far
31
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000032namespace gl
33{
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000034std::string str(int i)
35{
36 char buffer[20];
37 snprintf(buffer, sizeof(buffer), "%d", i);
38 return buffer;
39}
40
Jamie Madill63491ea2013-06-06 11:56:45 -040041std::string arrayString(int i)
42{
43 return "[" + str(i) + "]";
44}
45
Jamie Madill46131a32013-06-20 11:55:50 -040046std::string arrayString(unsigned int i)
47{
48 return (i == GL_INVALID_INDEX ? "" : "[" + str(i) + "]");
49}
50
shannonwoods@chromium.orgb4e07b82013-05-30 00:19:31 +000051namespace gl_d3d
52{
53 std::string TypeString(GLenum type)
54 {
55 switch (type)
56 {
57 case GL_FLOAT: return "float";
58 case GL_FLOAT_VEC2: return "float2";
59 case GL_FLOAT_VEC3: return "float3";
60 case GL_FLOAT_VEC4: return "float4";
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +000061 case GL_INT: return "int";
62 case GL_INT_VEC2: return "int2";
63 case GL_INT_VEC3: return "int3";
64 case GL_INT_VEC4: return "int4";
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +000065 case GL_UNSIGNED_INT: return "uint";
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +000066 case GL_UNSIGNED_INT_VEC2: return "uint2";
67 case GL_UNSIGNED_INT_VEC3: return "uint3";
68 case GL_UNSIGNED_INT_VEC4: return "uint4";
shannonwoods@chromium.orgb4e07b82013-05-30 00:19:31 +000069 case GL_FLOAT_MAT2: return "float2x2";
70 case GL_FLOAT_MAT3: return "float3x3";
71 case GL_FLOAT_MAT4: return "float4x4";
72 case GL_FLOAT_MAT2x3: return "float2x3";
73 case GL_FLOAT_MAT3x2: return "float3x2";
74 case GL_FLOAT_MAT2x4: return "float2x4";
75 case GL_FLOAT_MAT4x2: return "float4x2";
76 case GL_FLOAT_MAT3x4: return "float3x4";
77 case GL_FLOAT_MAT4x3: return "float4x3";
78 default: UNREACHABLE(); return "invalid-gl-type";
79 }
80 }
81}
82
shannonwoods@chromium.org6d7b61c2013-05-30 00:06:38 +000083namespace
84{
85
Jamie Madill8ff21ae2014-02-04 16:04:05 -050086unsigned int ParseAndStripArrayIndex(std::string* name)
shannonwoods@chromium.org6d7b61c2013-05-30 00:06:38 +000087{
88 unsigned int subscript = GL_INVALID_INDEX;
89
90 // Strip any trailing array operator and retrieve the subscript
91 size_t open = name->find_last_of('[');
92 size_t close = name->find_last_of(']');
93 if (open != std::string::npos && close == name->length() - 1)
94 {
95 subscript = atoi(name->substr(open + 1).c_str());
96 name->erase(open);
97 }
98
99 return subscript;
100}
101
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500102static rx::D3DWorkaroundType DiscardWorkaround(bool usesDiscard)
103{
104 return (usesDiscard ? rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER : rx::ANGLE_D3D_WORKAROUND_NONE);
105}
106
shannonwoods@chromium.org6d7b61c2013-05-30 00:06:38 +0000107}
108
Jamie Madill63491ea2013-06-06 11:56:45 -0400109VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
daniel@transgaming.comdb019952012-12-20 21:13:32 +0000110 : name(name), element(element), index(index)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000111{
112}
113
daniel@transgaming.come87ca002012-07-24 18:30:43 +0000114unsigned int ProgramBinary::mCurrentSerial = 1;
115
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500116ProgramBinary::ProgramBinary(rx::Renderer *renderer)
117 : RefCountObject(0),
118 mRenderer(renderer),
119 mPixelExecutable(NULL),
120 mVertexExecutable(NULL),
121 mGeometryExecutable(NULL),
122 mUsedVertexSamplerRange(0),
123 mUsedPixelSamplerRange(0),
124 mUsesPointSize(false),
125 mShaderVersion(100),
126 mVertexUniformStorage(NULL),
127 mFragmentUniformStorage(NULL),
128 mValidated(false),
129 mSerial(issueSerial())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000130{
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000131 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
132 {
133 mSemanticIndex[index] = -1;
134 }
135
136 for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
137 {
138 mSamplersPS[index].active = false;
139 }
140
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000141 for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000142 {
143 mSamplersVS[index].active = false;
144 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000145}
146
147ProgramBinary::~ProgramBinary()
148{
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500149 SafeDelete(mPixelExecutable);
150 SafeDelete(mVertexExecutable);
151 SafeDelete(mGeometryExecutable);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000152
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000153 while (!mUniforms.empty())
154 {
155 delete mUniforms.back();
156 mUniforms.pop_back();
157 }
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +0000158
159 while (!mUniformBlocks.empty())
160 {
161 delete mUniformBlocks.back();
162 mUniformBlocks.pop_back();
163 }
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500164
165 SafeDelete(mVertexUniformStorage);
166 SafeDelete(mFragmentUniformStorage);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000167}
168
daniel@transgaming.come87ca002012-07-24 18:30:43 +0000169unsigned int ProgramBinary::getSerial() const
170{
171 return mSerial;
172}
173
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +0000174int ProgramBinary::getShaderVersion() const
175{
176 return mShaderVersion;
177}
178
daniel@transgaming.come87ca002012-07-24 18:30:43 +0000179unsigned int ProgramBinary::issueSerial()
180{
181 return mCurrentSerial++;
182}
183
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500184rx::ShaderExecutable *ProgramBinary::getPixelExecutable() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000185{
186 return mPixelExecutable;
187}
188
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500189rx::ShaderExecutable *ProgramBinary::getVertexExecutable() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000190{
191 return mVertexExecutable;
192}
193
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500194rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000195{
196 return mGeometryExecutable;
197}
198
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000199GLuint ProgramBinary::getAttributeLocation(const char *name)
200{
201 if (name)
202 {
203 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
204 {
205 if (mLinkedAttribute[index].name == std::string(name))
206 {
207 return index;
208 }
209 }
210 }
211
212 return -1;
213}
214
215int ProgramBinary::getSemanticIndex(int attributeIndex)
216{
217 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
218
219 return mSemanticIndex[attributeIndex];
220}
221
222// Returns one more than the highest sampler index used.
223GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
224{
225 switch (type)
226 {
227 case SAMPLER_PIXEL:
228 return mUsedPixelSamplerRange;
229 case SAMPLER_VERTEX:
230 return mUsedVertexSamplerRange;
231 default:
232 UNREACHABLE();
233 return 0;
234 }
235}
236
daniel@transgaming.com087e5782012-09-17 21:28:47 +0000237bool ProgramBinary::usesPointSize() const
238{
239 return mUsesPointSize;
240}
241
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000242bool ProgramBinary::usesPointSpriteEmulation() const
243{
244 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
245}
246
247bool ProgramBinary::usesGeometryShader() const
248{
249 return usesPointSpriteEmulation();
250}
251
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000252// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
253// index (0-15 for the pixel shader and 0-3 for the vertex shader).
254GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
255{
256 GLint logicalTextureUnit = -1;
257
258 switch (type)
259 {
260 case SAMPLER_PIXEL:
261 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
262
263 if (mSamplersPS[samplerIndex].active)
264 {
265 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
266 }
267 break;
268 case SAMPLER_VERTEX:
269 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
270
271 if (mSamplersVS[samplerIndex].active)
272 {
273 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
274 }
275 break;
276 default: UNREACHABLE();
277 }
278
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000279 if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000280 {
281 return logicalTextureUnit;
282 }
283
284 return -1;
285}
286
287// Returns the texture type for a given Direct3D 9 sampler type and
288// index (0-15 for the pixel shader and 0-3 for the vertex shader).
289TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
290{
291 switch (type)
292 {
293 case SAMPLER_PIXEL:
294 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
295 ASSERT(mSamplersPS[samplerIndex].active);
296 return mSamplersPS[samplerIndex].textureType;
297 case SAMPLER_VERTEX:
298 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
299 ASSERT(mSamplersVS[samplerIndex].active);
300 return mSamplersVS[samplerIndex].textureType;
301 default: UNREACHABLE();
302 }
303
304 return TEXTURE_2D;
305}
306
307GLint ProgramBinary::getUniformLocation(std::string name)
308{
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500309 unsigned int subscript = ParseAndStripArrayIndex(&name);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000310
311 unsigned int numUniforms = mUniformIndex.size();
312 for (unsigned int location = 0; location < numUniforms; location++)
313 {
shannonwoods@chromium.org0ee85f82013-05-30 00:05:47 +0000314 if (mUniformIndex[location].name == name)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000315 {
shannonwoods@chromium.org0ee85f82013-05-30 00:05:47 +0000316 const int index = mUniformIndex[location].index;
317 const bool isArray = mUniforms[index]->isArray();
318
319 if ((isArray && mUniformIndex[location].element == subscript) ||
320 (subscript == GL_INVALID_INDEX))
321 {
322 return location;
323 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000324 }
325 }
326
327 return -1;
328}
329
shannonwoods@chromium.orgc2ed9912013-05-30 00:05:33 +0000330GLuint ProgramBinary::getUniformIndex(std::string name)
331{
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500332 unsigned int subscript = ParseAndStripArrayIndex(&name);
shannonwoods@chromium.orgc2ed9912013-05-30 00:05:33 +0000333
334 // The app is not allowed to specify array indices other than 0 for arrays of basic types
335 if (subscript != 0 && subscript != GL_INVALID_INDEX)
336 {
337 return GL_INVALID_INDEX;
338 }
339
340 unsigned int numUniforms = mUniforms.size();
341 for (unsigned int index = 0; index < numUniforms; index++)
342 {
343 if (mUniforms[index]->name == name)
344 {
345 if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
346 {
347 return index;
348 }
349 }
350 }
351
352 return GL_INVALID_INDEX;
353}
354
shannonwoods@chromium.org42766252013-05-30 00:07:12 +0000355GLuint ProgramBinary::getUniformBlockIndex(std::string name)
356{
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500357 unsigned int subscript = ParseAndStripArrayIndex(&name);
shannonwoods@chromium.org42766252013-05-30 00:07:12 +0000358
359 unsigned int numUniformBlocks = mUniformBlocks.size();
360 for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
361 {
362 const UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
363 if (uniformBlock.name == name)
364 {
365 const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
366 if (subscript == uniformBlock.elementIndex || arrayElementZero)
367 {
368 return blockIndex;
369 }
370 }
371 }
372
373 return GL_INVALID_INDEX;
374}
375
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +0000376UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex)
377{
378 ASSERT(blockIndex < mUniformBlocks.size());
379 return mUniformBlocks[blockIndex];
380}
381
Jamie Madilld1e78c92013-06-20 11:55:50 -0400382GLint ProgramBinary::getFragDataLocation(const char *name) const
383{
384 std::string baseName(name);
385 unsigned int arrayIndex;
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500386 arrayIndex = ParseAndStripArrayIndex(&baseName);
Jamie Madilld1e78c92013-06-20 11:55:50 -0400387
388 for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
389 {
390 const VariableLocation &outputVariable = locationIt->second;
391
392 if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
393 {
394 return static_cast<GLint>(locationIt->first);
395 }
396 }
397
398 return -1;
399}
400
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000401template <typename T>
402bool ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000403{
404 if (location < 0 || location >= (int)mUniformIndex.size())
405 {
406 return false;
407 }
408
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000409 const int components = UniformComponentCount(targetUniformType);
410 const GLenum targetBoolType = UniformBoolVectorType(targetUniformType);
411
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000412 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
413 targetUniform->dirty = true;
414
shannon.woods@transgaming.com15de0f92013-02-28 23:10:31 +0000415 int elementCount = targetUniform->elementCount();
416
417 if (elementCount == 1 && count > 1)
418 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
419
420 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
421
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000422 if (targetUniform->type == targetUniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000423 {
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000424 T *target = (T*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000425
426 for (int i = 0; i < count; i++)
427 {
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000428 for (int c = 0; c < components; c++)
429 {
430 target[c] = v[c];
431 }
432 for (int c = components; c < 4; c++)
433 {
434 target[c] = 0;
435 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000436 target += 4;
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000437 v += components;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000438 }
439 }
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000440 else if (targetUniform->type == targetBoolType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000441 {
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000442 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000443
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000444 for (int i = 0; i < count; i++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000445 {
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000446 for (int c = 0; c < components; c++)
447 {
448 boolParams[c] = (v[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
449 }
450 for (int c = components; c < 4; c++)
451 {
452 boolParams[c] = GL_FALSE;
453 }
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000454 boolParams += 4;
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000455 v += components;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000456 }
457 }
458 else
459 {
460 return false;
461 }
462
463 return true;
464}
465
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000466bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
467{
468 return setUniform(location, count, v, GL_FLOAT);
469}
470
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000471bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
472{
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000473 return setUniform(location, count, v, GL_FLOAT_VEC2);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000474}
475
476bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
477{
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000478 return setUniform(location, count, v, GL_FLOAT_VEC3);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000479}
480
481bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
482{
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000483 return setUniform(location, count, v, GL_FLOAT_VEC4);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000484}
485
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000486template<typename T>
487void transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000488{
shannonwoods@chromium.org2c2b82b2013-05-30 00:15:12 +0000489 int copyWidth = std::min(targetHeight, srcWidth);
490 int copyHeight = std::min(targetWidth, srcHeight);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000491
492 for (int x = 0; x < copyWidth; x++)
493 {
494 for (int y = 0; y < copyHeight; y++)
495 {
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000496 target[x * targetWidth + y] = static_cast<T>(value[y * srcWidth + x]);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000497 }
498 }
499 // clear unfilled right side
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000500 for (int y = 0; y < copyWidth; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000501 {
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000502 for (int x = copyHeight; x < targetWidth; x++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000503 {
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000504 target[y * targetWidth + x] = static_cast<T>(0);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000505 }
506 }
507 // clear unfilled bottom.
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000508 for (int y = copyWidth; y < targetHeight; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000509 {
510 for (int x = 0; x < targetWidth; x++)
511 {
shannon.woods%transgaming.com@gtempaccount.comcc62fac2013-04-13 03:39:52 +0000512 target[y * targetWidth + x] = static_cast<T>(0);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000513 }
514 }
515}
516
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000517template<typename T>
518void expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
519{
520 int copyWidth = std::min(targetWidth, srcWidth);
521 int copyHeight = std::min(targetHeight, srcHeight);
522
523 for (int y = 0; y < copyHeight; y++)
524 {
525 for (int x = 0; x < copyWidth; x++)
526 {
527 target[y * targetWidth + x] = static_cast<T>(value[y * srcWidth + x]);
528 }
529 }
530 // clear unfilled right side
531 for (int y = 0; y < copyHeight; y++)
532 {
533 for (int x = copyWidth; x < targetWidth; x++)
534 {
535 target[y * targetWidth + x] = static_cast<T>(0);
536 }
537 }
538 // clear unfilled bottom.
539 for (int y = copyHeight; y < targetHeight; y++)
540 {
541 for (int x = 0; x < targetWidth; x++)
542 {
543 target[y * targetWidth + x] = static_cast<T>(0);
544 }
545 }
546}
547
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000548template <int cols, int rows>
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000549bool ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000550{
551 if (location < 0 || location >= (int)mUniformIndex.size())
552 {
553 return false;
554 }
555
556 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
557 targetUniform->dirty = true;
558
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000559 if (targetUniform->type != targetUniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000560 {
561 return false;
562 }
563
daniel@transgaming.come6d12e92012-12-20 21:12:47 +0000564 int elementCount = targetUniform->elementCount();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000565
daniel@transgaming.come6d12e92012-12-20 21:12:47 +0000566 if (elementCount == 1 && count > 1)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000567 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
568
daniel@transgaming.come6d12e92012-12-20 21:12:47 +0000569 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
shannonwoods@chromium.org2c2b82b2013-05-30 00:15:12 +0000570 const unsigned int targetMatrixStride = (4 * rows);
571 GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000572
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000573 for (int i = 0; i < count; i++)
574 {
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000575 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
576 if (transpose == GL_FALSE)
577 {
578 transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols);
579 }
580 else
581 {
582 expandMatrix<GLfloat>(target, value, 4, rows, cols, rows);
583 }
shannonwoods@chromium.org2c2b82b2013-05-30 00:15:12 +0000584 target += targetMatrixStride;
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000585 value += cols * rows;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000586 }
587
588 return true;
589}
590
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000591bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000592{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000593 return setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000594}
595
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000596bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000597{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000598 return setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000599}
600
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000601bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000602{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000603 return setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000604}
605
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000606bool ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000607{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000608 return setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000609}
610
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000611bool ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000612{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000613 return setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000614}
615
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000616bool ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000617{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000618 return setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000619}
620
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000621bool ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000622{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000623 return setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000624}
625
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000626bool ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000627{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000628 return setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000629}
630
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000631bool ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000632{
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000633 return setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000634}
635
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000636bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
637{
638 if (location < 0 || location >= (int)mUniformIndex.size())
639 {
640 return false;
641 }
642
643 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
644 targetUniform->dirty = true;
645
shannon.woods@transgaming.com15de0f92013-02-28 23:10:31 +0000646 int elementCount = targetUniform->elementCount();
647
648 if (elementCount == 1 && count > 1)
649 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
650
651 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
652
Nicolas Capense6050882013-07-08 10:43:10 -0400653 if (targetUniform->type == GL_INT || IsSampler(targetUniform->type))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000654 {
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000655 GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000656
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000657 for (int i = 0; i < count; i++)
658 {
659 target[0] = v[0];
660 target[1] = 0;
661 target[2] = 0;
662 target[3] = 0;
663 target += 4;
664 v += 1;
665 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000666 }
667 else if (targetUniform->type == GL_BOOL)
668 {
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000669 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000670
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000671 for (int i = 0; i < count; i++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000672 {
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000673 boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE;
674 boolParams[1] = GL_FALSE;
675 boolParams[2] = GL_FALSE;
676 boolParams[3] = GL_FALSE;
677 boolParams += 4;
678 v += 1;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000679 }
680 }
681 else
682 {
683 return false;
684 }
685
686 return true;
687}
688
689bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
690{
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000691 return setUniform(location, count, v, GL_INT_VEC2);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000692}
693
694bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
695{
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000696 return setUniform(location, count, v, GL_INT_VEC3);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000697}
698
699bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
700{
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000701 return setUniform(location, count, v, GL_INT_VEC4);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000702}
703
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000704bool ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
705{
706 return setUniform(location, count, v, GL_UNSIGNED_INT);
707}
708
709bool ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
710{
711 return setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
712}
713
714bool ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
715{
716 return setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
717}
718
719bool ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
720{
721 return setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
722}
723
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000724template <typename T>
725bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000726{
727 if (location < 0 || location >= (int)mUniformIndex.size())
728 {
729 return false;
730 }
731
732 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
733
734 // sized queries -- ensure the provided buffer is large enough
735 if (bufSize)
736 {
737 int requiredBytes = UniformExternalSize(targetUniform->type);
738 if (*bufSize < requiredBytes)
739 {
740 return false;
741 }
742 }
743
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000744 if (IsMatrixType(targetUniform->type))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000745 {
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000746 const int rows = VariableRowCount(targetUniform->type);
747 const int cols = VariableColumnCount(targetUniform->type);
Jamie Madillf07558a2013-10-31 11:16:22 -0400748 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 +0000749 }
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000750 else if (uniformType == UniformComponentType(targetUniform->type))
751 {
752 unsigned int size = UniformComponentCount(targetUniform->type);
753 memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
754 size * sizeof(T));
755 }
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000756 else
757 {
758 unsigned int size = UniformComponentCount(targetUniform->type);
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000759 switch (UniformComponentType(targetUniform->type))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000760 {
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000761 case GL_BOOL:
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000762 {
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000763 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000764
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000765 for (unsigned int i = 0; i < size; i++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000766 {
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000767 params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000768 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000769 }
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000770 break;
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000771
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000772 case GL_FLOAT:
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000773 {
774 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
775
776 for (unsigned int i = 0; i < size; i++)
777 {
778 params[i] = static_cast<T>(floatParams[i]);
779 }
780 }
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000781 break;
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000782
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000783 case GL_INT:
784 {
785 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
786
787 for (unsigned int i = 0; i < size; i++)
788 {
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000789 params[i] = static_cast<T>(intParams[i]);
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000790 }
791 }
792 break;
shannon.woods%transgaming.com@gtempaccount.come2290122013-04-13 03:41:07 +0000793
794 case GL_UNSIGNED_INT:
795 {
796 GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000797
shannon.woods%transgaming.com@gtempaccount.come2290122013-04-13 03:41:07 +0000798 for (unsigned int i = 0; i < size; i++)
799 {
800 params[i] = static_cast<T>(uintParams[i]);
801 }
802 }
803 break;
804
shannon.woods%transgaming.com@gtempaccount.comf4895612013-04-13 03:40:56 +0000805 default: UNREACHABLE();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000806 }
807 }
808
809 return true;
810}
811
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000812bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
813{
814 return getUniformv(location, bufSize, params, GL_FLOAT);
815}
816
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000817bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
818{
shannon.woods%transgaming.com@gtempaccount.com4590d892013-04-13 03:41:01 +0000819 return getUniformv(location, bufSize, params, GL_INT);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000820}
821
shannon.woods%transgaming.com@gtempaccount.come2290122013-04-13 03:41:07 +0000822bool ProgramBinary::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params)
823{
824 return getUniformv(location, bufSize, params, GL_UNSIGNED_INT);
825}
826
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000827void ProgramBinary::dirtyAllUniforms()
828{
829 unsigned int numUniforms = mUniforms.size();
830 for (unsigned int index = 0; index < numUniforms; index++)
831 {
832 mUniforms[index]->dirty = true;
833 }
834}
835
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000836// Applies all the uniforms set for this program object to the renderer
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000837void ProgramBinary::applyUniforms()
838{
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000839 // Retrieve sampler uniform values
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500840 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000841 {
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500842 Uniform *targetUniform = mUniforms[uniformIndex];
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000843
844 if (targetUniform->dirty)
845 {
Nicolas Capense6050882013-07-08 10:43:10 -0400846 if (IsSampler(targetUniform->type))
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000847 {
daniel@transgaming.come6d12e92012-12-20 21:12:47 +0000848 int count = targetUniform->elementCount();
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000849 GLint (*v)[4] = (GLint(*)[4])targetUniform->data;
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000850
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +0000851 if (targetUniform->isReferencedByFragmentShader())
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000852 {
daniel@transgaming.come76b64b2013-01-11 04:10:08 +0000853 unsigned int firstIndex = targetUniform->psRegisterIndex;
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000854
855 for (int i = 0; i < count; i++)
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000856 {
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000857 unsigned int samplerIndex = firstIndex + i;
858
859 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000860 {
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000861 ASSERT(mSamplersPS[samplerIndex].active);
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000862 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000863 }
864 }
865 }
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000866
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +0000867 if (targetUniform->isReferencedByVertexShader())
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000868 {
daniel@transgaming.come76b64b2013-01-11 04:10:08 +0000869 unsigned int firstIndex = targetUniform->vsRegisterIndex;
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000870
871 for (int i = 0; i < count; i++)
872 {
873 unsigned int samplerIndex = firstIndex + i;
874
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +0000875 if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000876 {
877 ASSERT(mSamplersVS[samplerIndex].active);
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000878 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
daniel@transgaming.comf9561862012-12-20 21:12:07 +0000879 }
880 }
881 }
daniel@transgaming.comb6e55102012-12-20 21:08:14 +0000882 }
883 }
884 }
885
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500886 mRenderer->applyUniforms(*this);
887
888 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
889 {
890 mUniforms[uniformIndex]->dirty = false;
891 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000892}
893
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +0000894bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers)
895{
896 const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
897 const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
898
899 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
900 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
901
902 ASSERT(boundBuffers.size() == mUniformBlocks.size());
903
904 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
905 {
906 gl::UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex);
907 gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
908
909 ASSERT(uniformBlock && uniformBuffer);
910
911 if (uniformBuffer->size() < uniformBlock->dataSize)
912 {
913 // undefined behaviour
914 return false;
915 }
916
917 ASSERT(uniformBlock->isReferencedByVertexShader() || uniformBlock->isReferencedByFragmentShader());
918
919 if (uniformBlock->isReferencedByVertexShader())
920 {
921 unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
922 ASSERT(vertexUniformBuffers[registerIndex] == NULL);
923 ASSERT(registerIndex < mRenderer->getMaxVertexShaderUniformBuffers());
924 vertexUniformBuffers[registerIndex] = uniformBuffer;
925 }
926
927 if (uniformBlock->isReferencedByFragmentShader())
928 {
929 unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
930 ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
931 ASSERT(registerIndex < mRenderer->getMaxFragmentShaderUniformBuffers());
932 fragmentUniformBuffers[registerIndex] = uniformBuffer;
933 }
934 }
935
936 return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
937}
938
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000939// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
940// Returns the number of used varying registers, or -1 if unsuccesful
Jamie Madilla6da33a2013-08-30 13:21:07 -0400941int ProgramBinary::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000942{
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +0000943 const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000944
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +0000945 fragmentShader->resetVaryingsRegisterAssignment();
946
Jamie Madillce79dda2013-08-30 13:21:06 -0400947 for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000948 {
Jamie Madilla6da33a2013-08-30 13:21:07 -0400949 sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000950 GLenum transposedType = TransposeMatrixType(varying->type);
Jamie Madill28167c62013-08-30 13:21:10 -0400951
952 // matrices within varying structs are not transposed
953 int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
954 int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000955 bool success = false;
956
Jamie Madill28167c62013-08-30 13:21:10 -0400957 if (elements == 2 || elements == 3 || elements == 4)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000958 {
Jamie Madill28167c62013-08-30 13:21:10 -0400959 for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000960 {
961 bool available = true;
962
Jamie Madill28167c62013-08-30 13:21:10 -0400963 for (int y = 0; y < registers && available; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000964 {
Jamie Madill28167c62013-08-30 13:21:10 -0400965 for (int x = 0; x < elements && available; x++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000966 {
967 if (packing[r + y][x])
968 {
969 available = false;
970 }
971 }
972 }
973
974 if (available)
975 {
Jamie Madill139b9092013-08-30 13:21:06 -0400976 varying->registerIndex = r;
977 varying->elementIndex = 0;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000978
Jamie Madill28167c62013-08-30 13:21:10 -0400979 for (int y = 0; y < registers; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000980 {
Jamie Madill28167c62013-08-30 13:21:10 -0400981 for (int x = 0; x < elements; x++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000982 {
983 packing[r + y][x] = &*varying;
984 }
985 }
986
987 success = true;
988 }
989 }
990
Jamie Madill28167c62013-08-30 13:21:10 -0400991 if (!success && elements == 2)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000992 {
Jamie Madill28167c62013-08-30 13:21:10 -0400993 for (int r = maxVaryingVectors - registers; r >= 0 && !success; r--)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000994 {
995 bool available = true;
996
Jamie Madill28167c62013-08-30 13:21:10 -0400997 for (int y = 0; y < registers && available; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000998 {
999 for (int x = 2; x < 4 && available; x++)
1000 {
1001 if (packing[r + y][x])
1002 {
1003 available = false;
1004 }
1005 }
1006 }
1007
1008 if (available)
1009 {
Jamie Madill139b9092013-08-30 13:21:06 -04001010 varying->registerIndex = r;
1011 varying->elementIndex = 2;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001012
Jamie Madill28167c62013-08-30 13:21:10 -04001013 for (int y = 0; y < registers; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001014 {
1015 for (int x = 2; x < 4; x++)
1016 {
1017 packing[r + y][x] = &*varying;
1018 }
1019 }
1020
1021 success = true;
1022 }
1023 }
1024 }
1025 }
Jamie Madill28167c62013-08-30 13:21:10 -04001026 else if (elements == 1)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001027 {
1028 int space[4] = {0};
1029
1030 for (int y = 0; y < maxVaryingVectors; y++)
1031 {
1032 for (int x = 0; x < 4; x++)
1033 {
1034 space[x] += packing[y][x] ? 0 : 1;
1035 }
1036 }
1037
1038 int column = 0;
1039
1040 for (int x = 0; x < 4; x++)
1041 {
Jamie Madill28167c62013-08-30 13:21:10 -04001042 if (space[x] >= registers && space[x] < space[column])
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001043 {
1044 column = x;
1045 }
1046 }
1047
Jamie Madill28167c62013-08-30 13:21:10 -04001048 if (space[column] >= registers)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001049 {
1050 for (int r = 0; r < maxVaryingVectors; r++)
1051 {
1052 if (!packing[r][column])
1053 {
Jamie Madill139b9092013-08-30 13:21:06 -04001054 varying->registerIndex = r;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001055
Jamie Madill28167c62013-08-30 13:21:10 -04001056 for (int y = r; y < r + registers; y++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001057 {
1058 packing[y][column] = &*varying;
1059 }
1060
1061 break;
1062 }
1063 }
1064
Jamie Madill139b9092013-08-30 13:21:06 -04001065 varying->elementIndex = column;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001066
1067 success = true;
1068 }
1069 }
1070 else UNREACHABLE();
1071
1072 if (!success)
1073 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001074 infoLog.append("Could not pack varying %s", varying->name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001075
1076 return -1;
1077 }
1078 }
1079
1080 // Return the number of used registers
1081 int registers = 0;
1082
1083 for (int r = 0; r < maxVaryingVectors; r++)
1084 {
1085 if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
1086 {
1087 registers++;
1088 }
1089 }
1090
1091 return registers;
1092}
1093
Jamie Madill46131a32013-06-20 11:55:50 -04001094void ProgramBinary::defineOutputVariables(FragmentShader *fragmentShader)
1095{
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001096 const std::vector<sh::Attribute> &outputVars = fragmentShader->getOutputVariables();
Jamie Madill46131a32013-06-20 11:55:50 -04001097
1098 for (unsigned int outputVariableIndex = 0; outputVariableIndex < outputVars.size(); outputVariableIndex++)
1099 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001100 const sh::Attribute &outputVariable = outputVars[outputVariableIndex];
Jamie Madill46131a32013-06-20 11:55:50 -04001101 const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
1102
1103 if (outputVariable.arraySize > 0)
1104 {
1105 for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
1106 {
1107 const int location = baseLocation + elementIndex;
1108 ASSERT(mOutputVariables.count(location) == 0);
1109 mOutputVariables[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
1110 }
1111 }
1112 else
1113 {
1114 ASSERT(mOutputVariables.count(baseLocation) == 0);
1115 mOutputVariables[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
1116 }
1117 }
1118}
1119
Jamie Madilla6da33a2013-08-30 13:21:07 -04001120bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +00001121 std::string& pixelHLSL, std::string& vertexHLSL,
1122 FragmentShader *fragmentShader, VertexShader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001123{
1124 if (pixelHLSL.empty() || vertexHLSL.empty())
1125 {
1126 return false;
1127 }
1128
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001129 bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
1130 bool usesFragColor = fragmentShader->mUsesFragColor;
1131 bool usesFragData = fragmentShader->mUsesFragData;
shannon.woods%transgaming.com@gtempaccount.come3fe5dad2013-04-13 03:42:07 +00001132 if (usesFragColor && usesFragData)
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001133 {
1134 infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
1135 return false;
1136 }
1137
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001138 // Write the HLSL input/output declarations
daniel@transgaming.comb37cd2d2013-01-11 04:10:31 +00001139 const int shaderModel = mRenderer->getMajorShaderModel();
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +00001140 const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001141
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001142 const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
1143
shannon.woods%transgaming.com@gtempaccount.come3fe5dad2013-04-13 03:42:07 +00001144 // Two cases when writing to gl_FragColor and using ESSL 1.0:
1145 // - with a 3.0 context, the output color is copied to channel 0
1146 // - with a 2.0 context, the output color is broadcast to all channels
1147 const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
1148 const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
1149
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001150 if (registersNeeded > maxVaryingVectors)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001151 {
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001152 infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001153
1154 return false;
1155 }
1156
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +00001157 vertexShader->resetVaryingsRegisterAssignment();
1158
Jamie Madillce79dda2013-08-30 13:21:06 -04001159 for (unsigned int fragVaryingIndex = 0; fragVaryingIndex < fragmentShader->mVaryings.size(); fragVaryingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001160 {
Jamie Madilla6da33a2013-08-30 13:21:07 -04001161 sh::Varying *input = &fragmentShader->mVaryings[fragVaryingIndex];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001162 bool matched = false;
1163
Jamie Madillce79dda2013-08-30 13:21:06 -04001164 for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexShader->mVaryings.size(); vertVaryingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001165 {
Jamie Madilla6da33a2013-08-30 13:21:07 -04001166 sh::Varying *output = &vertexShader->mVaryings[vertVaryingIndex];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001167 if (output->name == input->name)
1168 {
Jamie Madill28167c62013-08-30 13:21:10 -04001169 if (!linkValidateVariables(infoLog, output->name, *input, *output))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001170 {
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001171 return false;
1172 }
1173
Jamie Madill139b9092013-08-30 13:21:06 -04001174 output->registerIndex = input->registerIndex;
1175 output->elementIndex = input->elementIndex;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001176
1177 matched = true;
1178 break;
1179 }
1180 }
1181
1182 if (!matched)
1183 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001184 infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001185
1186 return false;
1187 }
1188 }
1189
daniel@transgaming.com087e5782012-09-17 21:28:47 +00001190 mUsesPointSize = vertexShader->mUsesPointSize;
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001191 std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
daniel@transgaming.comb37cd2d2013-01-11 04:10:31 +00001192 std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001193 std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
Jamie Madill2aeb26a2013-07-08 14:02:55 -04001194 std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001195
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001196 std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
1197
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001198 // special varyings that use reserved registers
1199 int reservedRegisterIndex = registers;
1200 std::string fragCoordSemantic;
1201 std::string pointCoordSemantic;
1202
1203 if (fragmentShader->mUsesFragCoord)
1204 {
1205 fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
1206 }
1207
1208 if (fragmentShader->mUsesPointCoord)
1209 {
1210 // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
1211 // In DX11 we compute this in the GS.
1212 if (shaderModel == 3)
1213 {
1214 pointCoordSemantic = "TEXCOORD0";
1215 }
1216 else if (shaderModel >= 4)
1217 {
1218 pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
1219 }
1220 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001221
1222 vertexHLSL += "struct VS_INPUT\n"
shannon.woods@transgaming.com5f77c552013-01-25 21:51:44 +00001223 "{\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001224
1225 int semanticIndex = 0;
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001226 const std::vector<sh::Attribute> &activeAttributes = vertexShader->mActiveAttributes;
Jamie Madilldefb6742013-06-20 11:55:51 -04001227 for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001228 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001229 const sh::Attribute &attribute = activeAttributes[attributeIndex];
Jamie Madilldefb6742013-06-20 11:55:51 -04001230 vertexHLSL += " " + gl_d3d::TypeString(TransposeMatrixType(attribute.type)) + " ";
1231 vertexHLSL += decorateAttribute(attribute.name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001232
Jamie Madilldefb6742013-06-20 11:55:51 -04001233 semanticIndex += AttributeRegisterCount(attribute.type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001234 }
1235
1236 vertexHLSL += "};\n"
shannon.woods@transgaming.com5f77c552013-01-25 21:51:44 +00001237 "\n"
1238 "struct VS_OUTPUT\n"
1239 "{\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001240
shannon.woods%transgaming.com@gtempaccount.comee8d3c82013-04-13 03:27:26 +00001241 if (shaderModel < 4)
1242 {
1243 vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
1244 }
1245
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001246 vertexHLSL += varyingHLSL;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001247
1248 if (fragmentShader->mUsesFragCoord)
1249 {
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001250 vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001251 }
1252
daniel@transgaming.comb37cd2d2013-01-11 04:10:31 +00001253 if (vertexShader->mUsesPointSize && shaderModel >= 3)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001254 {
1255 vertexHLSL += " float gl_PointSize : PSIZE;\n";
1256 }
1257
shannon.woods%transgaming.com@gtempaccount.comee8d3c82013-04-13 03:27:26 +00001258 if (shaderModel >= 4)
1259 {
1260 vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
1261 }
1262
1263 vertexHLSL += "};\n"
daniel@transgaming.com9c4a6252013-01-11 04:07:18 +00001264 "\n"
1265 "VS_OUTPUT main(VS_INPUT input)\n"
1266 "{\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001267
Jamie Madilldefb6742013-06-20 11:55:51 -04001268 for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001269 {
Jamie Madilldefb6742013-06-20 11:55:51 -04001270 const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
1271 vertexHLSL += " " + decorateAttribute(attribute.name) + " = ";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001272
Jamie Madilldefb6742013-06-20 11:55:51 -04001273 if (IsMatrixType(attribute.type)) // Matrix
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001274 {
1275 vertexHLSL += "transpose";
1276 }
1277
Jamie Madilldefb6742013-06-20 11:55:51 -04001278 vertexHLSL += "(input." + decorateAttribute(attribute.name) + ");\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001279 }
1280
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +00001281 if (shaderModel >= 4)
1282 {
1283 vertexHLSL += "\n"
1284 " gl_main();\n"
1285 "\n"
1286 " VS_OUTPUT output;\n"
1287 " output.gl_Position.x = gl_Position.x;\n"
1288 " output.gl_Position.y = -gl_Position.y;\n"
1289 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
1290 " output.gl_Position.w = gl_Position.w;\n";
1291 }
1292 else
1293 {
1294 vertexHLSL += "\n"
1295 " gl_main();\n"
1296 "\n"
1297 " VS_OUTPUT output;\n"
shannon.woods@transgaming.com42832a62013-02-28 23:18:38 +00001298 " output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
1299 " output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +00001300 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
1301 " output.gl_Position.w = gl_Position.w;\n";
1302 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001303
daniel@transgaming.comb37cd2d2013-01-11 04:10:31 +00001304 if (vertexShader->mUsesPointSize && shaderModel >= 3)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001305 {
daniel@transgaming.com13be3e42012-07-04 19:16:24 +00001306 vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001307 }
1308
1309 if (fragmentShader->mUsesFragCoord)
1310 {
1311 vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
1312 }
1313
Jamie Madillce79dda2013-08-30 13:21:06 -04001314 for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexShader->mVaryings.size(); vertVaryingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001315 {
Jamie Madilla6da33a2013-08-30 13:21:07 -04001316 sh::Varying *varying = &vertexShader->mVaryings[vertVaryingIndex];
Jamie Madill139b9092013-08-30 13:21:06 -04001317 if (varying->registerAssigned())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001318 {
Jamie Madill139b9092013-08-30 13:21:06 -04001319 for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001320 {
Jamie Madill28167c62013-08-30 13:21:10 -04001321 int variableRows = (varying->isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying->type)));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001322
Jamie Madill139b9092013-08-30 13:21:06 -04001323 for (int row = 0; row < variableRows; row++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001324 {
Jamie Madill139b9092013-08-30 13:21:06 -04001325 int r = varying->registerIndex + elementIndex * variableRows + row;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001326 vertexHLSL += " output.v" + str(r);
1327
1328 bool sharedRegister = false; // Register used by multiple varyings
1329
1330 for (int x = 0; x < 4; x++)
1331 {
1332 if (packing[r][x] && packing[r][x] != packing[r][0])
1333 {
1334 sharedRegister = true;
1335 break;
1336 }
1337 }
1338
1339 if(sharedRegister)
1340 {
1341 vertexHLSL += ".";
1342
1343 for (int x = 0; x < 4; x++)
1344 {
1345 if (packing[r][x] == &*varying)
1346 {
1347 switch(x)
1348 {
1349 case 0: vertexHLSL += "x"; break;
1350 case 1: vertexHLSL += "y"; break;
1351 case 2: vertexHLSL += "z"; break;
1352 case 3: vertexHLSL += "w"; break;
1353 }
1354 }
1355 }
1356 }
1357
Jamie Madill139b9092013-08-30 13:21:06 -04001358 vertexHLSL += " = _" + varying->name;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001359
Jamie Madill139b9092013-08-30 13:21:06 -04001360 if (varying->isArray())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001361 {
Jamie Madill139b9092013-08-30 13:21:06 -04001362 vertexHLSL += arrayString(elementIndex);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001363 }
1364
Jamie Madill139b9092013-08-30 13:21:06 -04001365 if (variableRows > 1)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001366 {
Jamie Madill139b9092013-08-30 13:21:06 -04001367 vertexHLSL += arrayString(row);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001368 }
1369
1370 vertexHLSL += ";\n";
1371 }
1372 }
1373 }
1374 }
1375
1376 vertexHLSL += "\n"
shannon.woods@transgaming.com5f77c552013-01-25 21:51:44 +00001377 " return output;\n"
1378 "}\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001379
1380 pixelHLSL += "struct PS_INPUT\n"
shannon.woods@transgaming.com5f77c552013-01-25 21:51:44 +00001381 "{\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001382
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001383 pixelHLSL += varyingHLSL;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001384
1385 if (fragmentShader->mUsesFragCoord)
1386 {
shannon.woods@transgaming.come0e89872013-01-25 21:55:40 +00001387 pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
shannon.woods@transgaming.com0693fc32013-02-28 23:18:03 +00001388 }
daniel@transgaming.com74471e02013-01-11 04:10:26 +00001389
shannon.woods@transgaming.com0693fc32013-02-28 23:18:03 +00001390 if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
1391 {
1392 pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
1393 }
shannon.woods@transgaming.com276337c2013-02-28 23:15:16 +00001394
shannon.woods@transgaming.com0693fc32013-02-28 23:18:03 +00001395 // Must consume the PSIZE element if the geometry shader is not active
1396 // We won't know if we use a GS until we draw
1397 if (vertexShader->mUsesPointSize && shaderModel >= 4)
1398 {
1399 pixelHLSL += " float gl_PointSize : PSIZE;\n";
1400 }
1401
1402 if (fragmentShader->mUsesFragCoord)
1403 {
daniel@transgaming.comb37cd2d2013-01-11 04:10:31 +00001404 if (shaderModel >= 4)
daniel@transgaming.com74471e02013-01-11 04:10:26 +00001405 {
1406 pixelHLSL += " float4 dx_VPos : SV_Position;\n";
1407 }
daniel@transgaming.comb37cd2d2013-01-11 04:10:31 +00001408 else if (shaderModel >= 3)
daniel@transgaming.com74471e02013-01-11 04:10:26 +00001409 {
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001410 pixelHLSL += " float2 dx_VPos : VPOS;\n";
1411 }
1412 }
1413
shannon.woods@transgaming.com41ba5e02013-01-25 21:51:20 +00001414 pixelHLSL += "};\n"
1415 "\n"
1416 "struct PS_OUTPUT\n"
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001417 "{\n";
1418
Jamie Madill46131a32013-06-20 11:55:50 -04001419 if (mShaderVersion < 300)
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001420 {
Jamie Madill46131a32013-06-20 11:55:50 -04001421 for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
1422 {
1423 pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
1424 }
Jamie Madill2aeb26a2013-07-08 14:02:55 -04001425
1426 if (fragmentShader->mUsesFragDepth)
1427 {
1428 pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
1429 }
Jamie Madill46131a32013-06-20 11:55:50 -04001430 }
1431 else
1432 {
1433 defineOutputVariables(fragmentShader);
1434
Jamie Madill9d2ffb12013-08-30 13:21:04 -04001435 const std::vector<sh::Attribute> &outputVars = fragmentShader->getOutputVariables();
Jamie Madill46131a32013-06-20 11:55:50 -04001436 for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
1437 {
1438 const VariableLocation &outputLocation = locationIt->second;
1439 const sh::ShaderVariable &outputVariable = outputVars[outputLocation.index];
1440 const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : str(outputLocation.element));
1441
1442 pixelHLSL += " " + gl_d3d::TypeString(outputVariable.type) +
1443 " out_" + outputLocation.name + elementString +
1444 " : " + targetSemantic + str(locationIt->first) + ";\n";
1445 }
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001446 }
1447
1448 pixelHLSL += "};\n"
shannon.woods@transgaming.com41ba5e02013-01-25 21:51:20 +00001449 "\n";
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001450
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001451 if (fragmentShader->mUsesFrontFacing)
1452 {
shannon.woods@transgaming.com5f77c552013-01-25 21:51:44 +00001453 if (shaderModel >= 4)
1454 {
1455 pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n"
1456 "{\n";
1457 }
1458 else
1459 {
1460 pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n"
1461 "{\n";
1462 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001463 }
shannon.woods@transgaming.com41ba5e02013-01-25 21:51:20 +00001464 else
1465 {
1466 pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n"
1467 "{\n";
1468 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001469
1470 if (fragmentShader->mUsesFragCoord)
1471 {
1472 pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
1473
daniel@transgaming.comb37cd2d2013-01-11 04:10:31 +00001474 if (shaderModel >= 4)
daniel@transgaming.com74471e02013-01-11 04:10:26 +00001475 {
1476 pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n"
1477 " gl_FragCoord.y = input.dx_VPos.y;\n";
1478 }
daniel@transgaming.comb37cd2d2013-01-11 04:10:31 +00001479 else if (shaderModel >= 3)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001480 {
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001481 pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
daniel@transgaming.com74471e02013-01-11 04:10:26 +00001482 " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001483 }
1484 else
1485 {
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +00001486 // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport()
1487 pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n"
1488 " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001489 }
1490
daniel@transgaming.com12985182012-12-20 20:56:31 +00001491 pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n"
daniel@transgaming.com74471e02013-01-11 04:10:26 +00001492 " gl_FragCoord.w = rhw;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001493 }
1494
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001495 if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001496 {
apatrick@chromium.org9616e582012-06-22 18:27:01 +00001497 pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
1498 pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001499 }
1500
1501 if (fragmentShader->mUsesFrontFacing)
1502 {
shannon.woods@transgaming.com41ba5e02013-01-25 21:51:20 +00001503 if (shaderModel <= 3)
1504 {
1505 pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
1506 }
1507 else
1508 {
1509 pixelHLSL += " gl_FrontFacing = isFrontFace;\n";
1510 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001511 }
1512
Jamie Madillce79dda2013-08-30 13:21:06 -04001513 for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001514 {
Jamie Madilla6da33a2013-08-30 13:21:07 -04001515 sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
Jamie Madill139b9092013-08-30 13:21:06 -04001516 if (varying->registerAssigned())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001517 {
Jamie Madill139b9092013-08-30 13:21:06 -04001518 for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001519 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001520 GLenum transposedType = TransposeMatrixType(varying->type);
Jamie Madill28167c62013-08-30 13:21:10 -04001521 int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
Jamie Madill139b9092013-08-30 13:21:06 -04001522 for (int row = 0; row < variableRows; row++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001523 {
Jamie Madill139b9092013-08-30 13:21:06 -04001524 std::string n = str(varying->registerIndex + elementIndex * variableRows + row);
1525 pixelHLSL += " _" + varying->name;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001526
Jamie Madill139b9092013-08-30 13:21:06 -04001527 if (varying->isArray())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001528 {
Jamie Madill139b9092013-08-30 13:21:06 -04001529 pixelHLSL += arrayString(elementIndex);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001530 }
1531
Jamie Madill139b9092013-08-30 13:21:06 -04001532 if (variableRows > 1)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001533 {
Jamie Madill139b9092013-08-30 13:21:06 -04001534 pixelHLSL += arrayString(row);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001535 }
1536
Jamie Madill28167c62013-08-30 13:21:10 -04001537 if (varying->isStruct())
daniel@transgaming.comf5a2ae52012-12-20 20:52:03 +00001538 {
Jamie Madill28167c62013-08-30 13:21:10 -04001539 pixelHLSL += " = input.v" + n + ";\n"; break;
1540 }
1541 else
1542 {
1543 switch (VariableColumnCount(transposedType))
1544 {
1545 case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break;
1546 case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break;
1547 case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break;
1548 case 4: pixelHLSL += " = input.v" + n + ";\n"; break;
1549 default: UNREACHABLE();
1550 }
daniel@transgaming.comf5a2ae52012-12-20 20:52:03 +00001551 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001552 }
1553 }
1554 }
1555 else UNREACHABLE();
1556 }
1557
1558 pixelHLSL += "\n"
shannon.woods@transgaming.com5f77c552013-01-25 21:51:44 +00001559 " gl_main();\n"
1560 "\n"
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001561 " PS_OUTPUT output;\n";
1562
Jamie Madill46131a32013-06-20 11:55:50 -04001563 if (mShaderVersion < 300)
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001564 {
Jamie Madill46131a32013-06-20 11:55:50 -04001565 for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
1566 {
1567 unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001568
Jamie Madill46131a32013-06-20 11:55:50 -04001569 pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
1570 }
Jamie Madill2aeb26a2013-07-08 14:02:55 -04001571
1572 if (fragmentShader->mUsesFragDepth)
1573 {
1574 pixelHLSL += " output.gl_Depth = gl_Depth;\n";
1575 }
Jamie Madill46131a32013-06-20 11:55:50 -04001576 }
1577 else
1578 {
1579 for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
1580 {
1581 const VariableLocation &outputLocation = locationIt->second;
1582 const std::string &variableName = "out_" + outputLocation.name;
1583 const std::string &outVariableName = variableName + (outputLocation.element == GL_INVALID_INDEX ? "" : str(outputLocation.element));
1584 const std::string &staticVariableName = variableName + arrayString(outputLocation.element);
1585
1586 pixelHLSL += " output." + outVariableName + " = " + staticVariableName + ";\n";
1587 }
shannon.woods%transgaming.com@gtempaccount.coma28864c2013-04-13 03:32:03 +00001588 }
1589
1590 pixelHLSL += "\n"
shannon.woods@transgaming.com5f77c552013-01-25 21:51:44 +00001591 " return output;\n"
1592 "}\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001593
1594 return true;
1595}
1596
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001597std::string ProgramBinary::generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const
1598{
1599 std::string varyingHLSL;
1600
Jamie Madillce79dda2013-08-30 13:21:06 -04001601 for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001602 {
Jamie Madilla6da33a2013-08-30 13:21:07 -04001603 sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
Jamie Madill139b9092013-08-30 13:21:06 -04001604 if (varying->registerAssigned())
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001605 {
Jamie Madill139b9092013-08-30 13:21:06 -04001606 for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001607 {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001608 GLenum transposedType = TransposeMatrixType(varying->type);
Jamie Madill28167c62013-08-30 13:21:10 -04001609 int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
Jamie Madill139b9092013-08-30 13:21:06 -04001610 for (int row = 0; row < variableRows; row++)
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001611 {
1612 switch (varying->interpolation)
1613 {
Jamie Madill139b9092013-08-30 13:21:06 -04001614 case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break;
1615 case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break;
1616 case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break;
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001617 default: UNREACHABLE();
1618 }
1619
Jamie Madill139b9092013-08-30 13:21:06 -04001620 std::string n = str(varying->registerIndex + elementIndex * variableRows + row);
Jamie Madill28167c62013-08-30 13:21:10 -04001621
1622 // matrices within structs are not transposed, hence we do not use the special struct prefix "rm"
1623 std::string typeString = varying->isStruct() ? "_" + varying->structName :
1624 gl_d3d::TypeString(UniformComponentType(transposedType)) + str(VariableColumnCount(transposedType));
shannonwoods@chromium.orgb4e07b82013-05-30 00:19:31 +00001625
shannonwoods@chromium.org5703d882013-05-30 00:19:38 +00001626 varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00001627 }
1628 }
1629 }
1630 else UNREACHABLE();
1631 }
1632
1633 return varyingHLSL;
1634}
1635
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001636bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
1637{
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001638 BinaryInputStream stream(binary, length);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001639
1640 int format = 0;
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001641 stream.read(&format);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001642 if (format != GL_PROGRAM_BINARY_ANGLE)
1643 {
1644 infoLog.append("Invalid program binary format.");
1645 return false;
1646 }
1647
Jamie Madill049108d2013-11-19 10:41:49 -05001648 int majorVersion = 0;
1649 int minorVersion = 0;
1650 stream.read(&majorVersion);
1651 stream.read(&minorVersion);
Jamie Madill0aa84f62014-02-13 13:17:23 -05001652 if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
Jamie Madill049108d2013-11-19 10:41:49 -05001653 {
1654 infoLog.append("Invalid program binary version.");
1655 return false;
1656 }
1657
Jamie Madill0aa84f62014-02-13 13:17:23 -05001658 unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
1659 stream.read(commitString, ANGLE_COMMIT_HASH_SIZE);
1660 if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001661 {
1662 infoLog.append("Invalid program binary version.");
1663 return false;
1664 }
1665
shannonwoods@chromium.orgf97a0842013-05-30 00:10:33 +00001666 int compileFlags = 0;
1667 stream.read(&compileFlags);
1668 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
1669 {
1670 infoLog.append("Mismatched compilation flags.");
1671 return false;
1672 }
1673
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001674 for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
1675 {
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001676 stream.read(&mLinkedAttribute[i].type);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001677 std::string name;
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001678 stream.read(&name);
1679 mLinkedAttribute[i].name = name;
1680 stream.read(&mSemanticIndex[i]);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001681 }
1682
Al Patrick3f2daa82013-08-07 12:58:57 -07001683 initAttributesByLayout();
1684
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001685 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
1686 {
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001687 stream.read(&mSamplersPS[i].active);
1688 stream.read(&mSamplersPS[i].logicalTextureUnit);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001689
1690 int textureType;
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001691 stream.read(&textureType);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001692 mSamplersPS[i].textureType = (TextureType) textureType;
1693 }
1694
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00001695 for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001696 {
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001697 stream.read(&mSamplersVS[i].active);
1698 stream.read(&mSamplersVS[i].logicalTextureUnit);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001699
1700 int textureType;
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001701 stream.read(&textureType);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001702 mSamplersVS[i].textureType = (TextureType) textureType;
1703 }
1704
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001705 stream.read(&mUsedVertexSamplerRange);
1706 stream.read(&mUsedPixelSamplerRange);
daniel@transgaming.com9aa6fe12012-12-20 21:13:39 +00001707 stream.read(&mUsesPointSize);
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +00001708 stream.read(&mShaderVersion);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001709
shannon.woods@transgaming.com45886d62013-02-28 23:19:20 +00001710 size_t size;
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001711 stream.read(&size);
1712 if (stream.error())
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001713 {
1714 infoLog.append("Invalid program binary.");
1715 return false;
1716 }
1717
1718 mUniforms.resize(size);
1719 for (unsigned int i = 0; i < size; ++i)
1720 {
1721 GLenum type;
shannon.woods@transgaming.comd5a91b92013-02-28 23:17:30 +00001722 GLenum precision;
daniel@transgaming.comdb019952012-12-20 21:13:32 +00001723 std::string name;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001724 unsigned int arraySize;
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001725 int blockIndex;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001726
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001727 stream.read(&type);
shannon.woods@transgaming.comd5a91b92013-02-28 23:17:30 +00001728 stream.read(&precision);
daniel@transgaming.comdb019952012-12-20 21:13:32 +00001729 stream.read(&name);
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001730 stream.read(&arraySize);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001731 stream.read(&blockIndex);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001732
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001733 int offset;
1734 int arrayStride;
1735 int matrixStride;
1736 bool isRowMajorMatrix;
1737
1738 stream.read(&offset);
1739 stream.read(&arrayStride);
1740 stream.read(&matrixStride);
1741 stream.read(&isRowMajorMatrix);
1742
1743 const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
1744
1745 mUniforms[i] = new Uniform(type, precision, name, arraySize, blockIndex, blockInfo);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001746
daniel@transgaming.come76b64b2013-01-11 04:10:08 +00001747 stream.read(&mUniforms[i]->psRegisterIndex);
1748 stream.read(&mUniforms[i]->vsRegisterIndex);
1749 stream.read(&mUniforms[i]->registerCount);
Jamie Madill5b085dc2013-08-30 13:21:11 -04001750 stream.read(&mUniforms[i]->registerElement);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001751 }
1752
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001753 stream.read(&size);
1754 if (stream.error())
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001755 {
1756 infoLog.append("Invalid program binary.");
1757 return false;
1758 }
1759
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001760 mUniformBlocks.resize(size);
1761 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < size; ++uniformBlockIndex)
1762 {
1763 std::string name;
1764 unsigned int elementIndex;
1765 unsigned int dataSize;
1766
1767 stream.read(&name);
1768 stream.read(&elementIndex);
1769 stream.read(&dataSize);
1770
1771 mUniformBlocks[uniformBlockIndex] = new UniformBlock(name, elementIndex, dataSize);
1772
1773 UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
1774 stream.read(&uniformBlock.psRegisterIndex);
1775 stream.read(&uniformBlock.vsRegisterIndex);
1776
1777 size_t numMembers;
1778 stream.read(&numMembers);
1779 uniformBlock.memberUniformIndexes.resize(numMembers);
1780 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
1781 {
1782 stream.read(&uniformBlock.memberUniformIndexes[blockMemberIndex]);
1783 }
1784 }
1785
1786 stream.read(&size);
1787 if (stream.error())
1788 {
1789 infoLog.append("Invalid program binary.");
1790 return false;
1791 }
1792
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001793 mUniformIndex.resize(size);
1794 for (unsigned int i = 0; i < size; ++i)
1795 {
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001796 stream.read(&mUniformIndex[i].name);
1797 stream.read(&mUniformIndex[i].element);
1798 stream.read(&mUniformIndex[i].index);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001799 }
1800
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001801 unsigned int pixelShaderSize;
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001802 stream.read(&pixelShaderSize);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001803
1804 unsigned int vertexShaderSize;
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001805 stream.read(&vertexShaderSize);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001806
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001807 unsigned int geometryShaderSize;
1808 stream.read(&geometryShaderSize);
1809
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001810 const char *ptr = (const char*) binary + stream.offset();
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001811
daniel@transgaming.com36038542012-11-28 20:59:26 +00001812 const GUID *binaryIdentifier = (const GUID *) ptr;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001813 ptr += sizeof(GUID);
1814
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +00001815 GUID identifier = mRenderer->getAdapterIdentifier();
1816 if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001817 {
1818 infoLog.append("Invalid program binary.");
1819 return false;
1820 }
1821
1822 const char *pixelShaderFunction = ptr;
1823 ptr += pixelShaderSize;
1824
1825 const char *vertexShaderFunction = ptr;
1826 ptr += vertexShaderSize;
1827
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001828 const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL;
1829 ptr += geometryShaderSize;
1830
daniel@transgaming.com4f0f65e2012-11-28 21:00:00 +00001831 mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction),
shannon.woods@transgaming.com69ff7762013-01-25 21:55:24 +00001832 pixelShaderSize, rx::SHADER_PIXEL);
daniel@transgaming.com4f0f65e2012-11-28 21:00:00 +00001833 if (!mPixelExecutable)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001834 {
1835 infoLog.append("Could not create pixel shader.");
1836 return false;
1837 }
1838
daniel@transgaming.com4f0f65e2012-11-28 21:00:00 +00001839 mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
shannon.woods@transgaming.com69ff7762013-01-25 21:55:24 +00001840 vertexShaderSize, rx::SHADER_VERTEX);
daniel@transgaming.com4f0f65e2012-11-28 21:00:00 +00001841 if (!mVertexExecutable)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001842 {
1843 infoLog.append("Could not create vertex shader.");
daniel@transgaming.com95892412012-11-28 20:59:09 +00001844 delete mPixelExecutable;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001845 mPixelExecutable = NULL;
1846 return false;
1847 }
1848
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001849 if (geometryShaderFunction != NULL && geometryShaderSize > 0)
1850 {
1851 mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
1852 geometryShaderSize, rx::SHADER_GEOMETRY);
1853 if (!mGeometryExecutable)
1854 {
1855 infoLog.append("Could not create geometry shader.");
1856 delete mPixelExecutable;
1857 mPixelExecutable = NULL;
1858 delete mVertexExecutable;
1859 mVertexExecutable = NULL;
1860 return false;
1861 }
1862 }
1863 else
1864 {
1865 mGeometryExecutable = NULL;
1866 }
1867
Jamie Madill8ff21ae2014-02-04 16:04:05 -05001868 initializeUniformStorage();
1869
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001870 return true;
1871}
1872
1873bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
1874{
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001875 BinaryOutputStream stream;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001876
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001877 stream.write(GL_PROGRAM_BINARY_ANGLE);
Jamie Madill0aa84f62014-02-13 13:17:23 -05001878 stream.write(ANGLE_MAJOR_VERSION);
1879 stream.write(ANGLE_MINOR_VERSION);
1880 stream.write(ANGLE_COMMIT_HASH, ANGLE_COMMIT_HASH_SIZE);
shannonwoods@chromium.orgf97a0842013-05-30 00:10:33 +00001881 stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001882
1883 for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
1884 {
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001885 stream.write(mLinkedAttribute[i].type);
1886 stream.write(mLinkedAttribute[i].name);
1887 stream.write(mSemanticIndex[i]);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001888 }
1889
1890 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
1891 {
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001892 stream.write(mSamplersPS[i].active);
1893 stream.write(mSamplersPS[i].logicalTextureUnit);
1894 stream.write((int) mSamplersPS[i].textureType);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001895 }
1896
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00001897 for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001898 {
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001899 stream.write(mSamplersVS[i].active);
1900 stream.write(mSamplersVS[i].logicalTextureUnit);
1901 stream.write((int) mSamplersVS[i].textureType);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001902 }
1903
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001904 stream.write(mUsedVertexSamplerRange);
1905 stream.write(mUsedPixelSamplerRange);
daniel@transgaming.com9aa6fe12012-12-20 21:13:39 +00001906 stream.write(mUsesPointSize);
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +00001907 stream.write(mShaderVersion);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001908
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001909 stream.write(mUniforms.size());
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001910 for (unsigned int uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001911 {
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001912 const Uniform &uniform = *mUniforms[uniformIndex];
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001913
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001914 stream.write(uniform.type);
1915 stream.write(uniform.precision);
1916 stream.write(uniform.name);
1917 stream.write(uniform.arraySize);
1918 stream.write(uniform.blockIndex);
1919
1920 stream.write(uniform.blockInfo.offset);
1921 stream.write(uniform.blockInfo.arrayStride);
1922 stream.write(uniform.blockInfo.matrixStride);
1923 stream.write(uniform.blockInfo.isRowMajorMatrix);
1924
1925 stream.write(uniform.psRegisterIndex);
1926 stream.write(uniform.vsRegisterIndex);
1927 stream.write(uniform.registerCount);
Jamie Madill5b085dc2013-08-30 13:21:11 -04001928 stream.write(uniform.registerElement);
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001929 }
1930
1931 stream.write(mUniformBlocks.size());
1932 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
1933 {
1934 const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
1935
1936 stream.write(uniformBlock.name);
1937 stream.write(uniformBlock.elementIndex);
1938 stream.write(uniformBlock.dataSize);
1939
1940 stream.write(uniformBlock.memberUniformIndexes.size());
1941 for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
1942 {
1943 stream.write(uniformBlock.memberUniformIndexes[blockMemberIndex]);
1944 }
1945
1946 stream.write(uniformBlock.psRegisterIndex);
1947 stream.write(uniformBlock.vsRegisterIndex);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001948 }
1949
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001950 stream.write(mUniformIndex.size());
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001951 for (unsigned int i = 0; i < mUniformIndex.size(); ++i)
1952 {
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001953 stream.write(mUniformIndex[i].name);
1954 stream.write(mUniformIndex[i].element);
1955 stream.write(mUniformIndex[i].index);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001956 }
1957
daniel@transgaming.com7b18d0c2012-11-28 21:04:10 +00001958 UINT pixelShaderSize = mPixelExecutable->getLength();
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001959 stream.write(pixelShaderSize);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001960
daniel@transgaming.com7b18d0c2012-11-28 21:04:10 +00001961 UINT vertexShaderSize = mVertexExecutable->getLength();
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001962 stream.write(vertexShaderSize);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001963
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001964 UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
1965 stream.write(geometryShaderSize);
1966
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +00001967 GUID identifier = mRenderer->getAdapterIdentifier();
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001968
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001969 GLsizei streamLength = stream.length();
1970 const void *streamData = stream.data();
1971
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001972 GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001973 if (totalLength > bufSize)
1974 {
1975 if (length)
1976 {
1977 *length = 0;
1978 }
1979
1980 return false;
1981 }
1982
1983 if (binary)
1984 {
1985 char *ptr = (char*) binary;
1986
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +00001987 memcpy(ptr, streamData, streamLength);
1988 ptr += streamLength;
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001989
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +00001990 memcpy(ptr, &identifier, sizeof(GUID));
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001991 ptr += sizeof(GUID);
1992
daniel@transgaming.com7b18d0c2012-11-28 21:04:10 +00001993 memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001994 ptr += pixelShaderSize;
1995
daniel@transgaming.com7b18d0c2012-11-28 21:04:10 +00001996 memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001997 ptr += vertexShaderSize;
1998
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00001999 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
2000 {
2001 memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize);
2002 ptr += geometryShaderSize;
2003 }
2004
apatrick@chromium.org90080e32012-07-09 22:15:33 +00002005 ASSERT(ptr - totalLength == binary);
2006 }
2007
2008 if (length)
2009 {
2010 *length = totalLength;
2011 }
2012
2013 return true;
2014}
2015
2016GLint ProgramBinary::getLength()
2017{
2018 GLint length;
2019 if (save(NULL, INT_MAX, &length))
2020 {
2021 return length;
2022 }
2023 else
2024 {
2025 return 0;
2026 }
2027}
2028
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002029bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002030{
2031 if (!fragmentShader || !fragmentShader->isCompiled())
2032 {
2033 return false;
2034 }
2035
2036 if (!vertexShader || !vertexShader->isCompiled())
2037 {
2038 return false;
2039 }
2040
shannonwoods@chromium.org83ac5e82013-05-30 00:15:29 +00002041 mShaderVersion = vertexShader->getShaderVersion();
2042
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002043 std::string pixelHLSL = fragmentShader->getHLSL();
2044 std::string vertexHLSL = vertexShader->getHLSL();
2045
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +00002046 // Map the varyings to the register file
Jamie Madilla6da33a2013-08-30 13:21:07 -04002047 const sh::ShaderVariable *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL};
shannon.woods@transgaming.com5bcf7df2013-01-25 21:55:33 +00002048 int registers = packVaryings(infoLog, packing, fragmentShader);
2049
2050 if (registers < 0)
2051 {
2052 return false;
2053 }
2054
2055 if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002056 {
2057 return false;
2058 }
2059
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00002060 bool success = true;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002061
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00002062 if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
2063 {
2064 success = false;
2065 }
2066
daniel@transgaming.com68aaf932012-12-20 21:13:16 +00002067 if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms()))
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00002068 {
daniel@transgaming.com68aaf932012-12-20 21:13:16 +00002069 success = false;
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002070 }
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00002071
shannonwoods@chromium.org03299882013-05-30 00:05:26 +00002072 // special case for gl_DepthRange, the only built-in uniform (also a struct)
2073 if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
2074 {
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00002075 mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, sh::BlockMemberInfo::defaultBlockInfo));
2076 mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, sh::BlockMemberInfo::defaultBlockInfo));
2077 mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, sh::BlockMemberInfo::defaultBlockInfo));
shannonwoods@chromium.org03299882013-05-30 00:05:26 +00002078 }
2079
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002080 if (!linkUniformBlocks(infoLog, vertexShader->getInterfaceBlocks(), fragmentShader->getInterfaceBlocks()))
2081 {
2082 success = false;
2083 }
2084
Jamie Madilld1ac3c92013-06-25 10:40:30 -04002085 if (success)
2086 {
Jamie Madill3c9eeb92013-11-04 11:09:26 -05002087 mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, DiscardWorkaround(vertexShader->mUsesDiscardRewriting));
2088 mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, DiscardWorkaround(fragmentShader->mUsesDiscardRewriting));
Jamie Madilld1ac3c92013-06-25 10:40:30 -04002089
2090 if (usesGeometryShader())
2091 {
2092 std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
Jamie Madill3c9eeb92013-11-04 11:09:26 -05002093 mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE);
Jamie Madilld1ac3c92013-06-25 10:40:30 -04002094 }
2095
2096 if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
2097 {
2098 infoLog.append("Failed to create D3D shaders.");
2099 success = false;
2100
2101 delete mVertexExecutable;
2102 mVertexExecutable = NULL;
2103 delete mPixelExecutable;
2104 mPixelExecutable = NULL;
2105 delete mGeometryExecutable;
2106 mGeometryExecutable = NULL;
2107 }
2108 }
2109
daniel@transgaming.comc68fa872012-11-28 20:58:32 +00002110 return success;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002111}
2112
2113// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002114bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002115{
2116 unsigned int usedLocations = 0;
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002117 const std::vector<sh::Attribute> &activeAttributes = vertexShader->mActiveAttributes;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002118
2119 // Link attributes that have a binding location
Jamie Madilldefb6742013-06-20 11:55:51 -04002120 for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002121 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002122 const sh::Attribute &attribute = activeAttributes[attributeIndex];
Jamie Madilleba4eff2013-06-20 11:55:51 -04002123 const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002124
Jamie Madilleba4eff2013-06-20 11:55:51 -04002125 if (location != -1) // Set by glBindAttribLocation or by location layout qualifier
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002126 {
Jamie Madilleba4eff2013-06-20 11:55:51 -04002127 const int rows = AttributeRegisterCount(attribute.type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002128
2129 if (rows + location > MAX_VERTEX_ATTRIBS)
2130 {
Jamie Madilldefb6742013-06-20 11:55:51 -04002131 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 +00002132
2133 return false;
2134 }
2135
Jamie Madilleba4eff2013-06-20 11:55:51 -04002136 for (int row = 0; row < rows; row++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002137 {
Jamie Madilleba4eff2013-06-20 11:55:51 -04002138 const int rowLocation = location + row;
2139 sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation];
2140
2141 // In GLSL 3.00, attribute aliasing produces a link error
2142 // In GLSL 1.00, attribute aliasing is allowed
2143 if (mShaderVersion >= 300)
2144 {
2145 if (!linkedAttribute.name.empty())
2146 {
2147 infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation);
2148 return false;
2149 }
2150 }
2151
2152 linkedAttribute = attribute;
2153 usedLocations |= 1 << rowLocation;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002154 }
2155 }
2156 }
2157
2158 // Link attributes that don't have a binding location
Jamie Madilldefb6742013-06-20 11:55:51 -04002159 for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002160 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002161 const sh::Attribute &attribute = activeAttributes[attributeIndex];
Jamie Madilleba4eff2013-06-20 11:55:51 -04002162 const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002163
Jamie Madilleba4eff2013-06-20 11:55:51 -04002164 if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002165 {
Jamie Madilldefb6742013-06-20 11:55:51 -04002166 int rows = AttributeRegisterCount(attribute.type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002167 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
2168
2169 if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
2170 {
Jamie Madilldefb6742013-06-20 11:55:51 -04002171 infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002172
2173 return false; // Fail to link
2174 }
2175
Jamie Madilldefb6742013-06-20 11:55:51 -04002176 mLinkedAttribute[availableIndex] = attribute;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002177 }
2178 }
2179
2180 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
2181 {
2182 int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
Jamie Madillbb22e502013-06-20 11:55:51 -04002183 int rows = AttributeRegisterCount(mLinkedAttribute[attributeIndex].type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002184
2185 for (int r = 0; r < rows; r++)
2186 {
2187 mSemanticIndex[attributeIndex++] = index++;
2188 }
2189 }
2190
Al Patrick3f2daa82013-08-07 12:58:57 -07002191 initAttributesByLayout();
2192
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002193 return true;
2194}
2195
Jamie Madill28167c62013-08-30 13:21:10 -04002196bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002197{
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002198 if (vertexVariable.type != fragmentVariable.type)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002199 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002200 infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002201 return false;
2202 }
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002203 if (vertexVariable.arraySize != fragmentVariable.arraySize)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002204 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002205 infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002206 return false;
2207 }
Jamie Madill28167c62013-08-30 13:21:10 -04002208 if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002209 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002210 infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str());
Jamie Madill010fffa2013-06-20 11:55:53 -04002211 return false;
2212 }
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002213
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002214 return true;
2215}
2216
2217template <class ShaderVarType>
2218bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar)
2219{
2220 if (vertexVar.fields.size() != fragmentVar.fields.size())
2221 {
2222 infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", varName.c_str());
2223 return false;
2224 }
2225 const unsigned int numMembers = vertexVar.fields.size();
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002226 for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
2227 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002228 const ShaderVarType &vertexMember = vertexVar.fields[memberIndex];
2229 const ShaderVarType &fragmentMember = fragmentVar.fields[memberIndex];
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002230
2231 if (vertexMember.name != fragmentMember.name)
2232 {
Jamie Madill28167c62013-08-30 13:21:10 -04002233 infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')",
2234 memberIndex, varName.c_str(), vertexMember.name.c_str(), fragmentMember.name.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002235 return false;
2236 }
2237
Jamie Madill28167c62013-08-30 13:21:10 -04002238 const std::string memberName = varName.substr(0, varName.length()-1) + "." + vertexVar.name + "'";
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002239 if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember))
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002240 {
2241 return false;
2242 }
2243 }
2244
2245 return true;
2246}
2247
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002248bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
2249{
Jamie Madill28167c62013-08-30 13:21:10 -04002250 if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002251 {
2252 return false;
2253 }
2254
2255 if (!linkValidateFields<sh::Uniform>(infoLog, uniformName, vertexUniform, fragmentUniform))
2256 {
2257 return false;
2258 }
2259
2260 return true;
2261}
2262
Jamie Madill28167c62013-08-30 13:21:10 -04002263bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
2264{
2265 if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
2266 {
2267 return false;
2268 }
2269
2270 if (vertexVarying.interpolation != fragmentVarying.interpolation)
2271 {
2272 infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
2273 return false;
2274 }
2275
2276 if (!linkValidateFields<sh::Varying>(infoLog, varyingName, vertexVarying, fragmentVarying))
2277 {
2278 return false;
2279 }
2280
2281 return true;
2282}
2283
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002284bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
2285{
Jamie Madill28167c62013-08-30 13:21:10 -04002286 if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002287 {
2288 return false;
2289 }
2290
2291 if (vertexUniform.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix)
2292 {
2293 infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
2294 return false;
2295 }
2296
2297 if (!linkValidateFields<sh::InterfaceBlockField>(infoLog, uniformName, vertexUniform, fragmentUniform))
2298 {
2299 return false;
2300 }
2301
2302 return true;
2303}
2304
2305bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform> &vertexUniforms, const std::vector<sh::Uniform> &fragmentUniforms)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002306{
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002307 // Check that uniforms defined in the vertex and fragment shaders are identical
2308 typedef std::map<std::string, const sh::Uniform*> UniformMap;
2309 UniformMap linkedUniforms;
2310
2311 for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++)
2312 {
2313 const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex];
2314 linkedUniforms[vertexUniform.name] = &vertexUniform;
2315 }
2316
2317 for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++)
2318 {
2319 const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex];
2320 UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name);
2321 if (entry != linkedUniforms.end())
2322 {
2323 const sh::Uniform &vertexUniform = *entry->second;
Jamie Madill28167c62013-08-30 13:21:10 -04002324 const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002325 if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform))
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002326 {
2327 return false;
2328 }
2329 }
2330 }
2331
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002332 for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002333 {
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002334 if (!defineUniform(GL_VERTEX_SHADER, vertexUniforms[uniformIndex], infoLog))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002335 {
2336 return false;
2337 }
2338 }
2339
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002340 for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
daniel@transgaming.coma418ef12012-11-28 20:58:22 +00002341 {
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002342 if (!defineUniform(GL_FRAGMENT_SHADER, fragmentUniforms[uniformIndex], infoLog))
daniel@transgaming.coma418ef12012-11-28 20:58:22 +00002343 {
2344 return false;
2345 }
2346 }
daniel@transgaming.com68aaf932012-12-20 21:13:16 +00002347
Jamie Madill8ff21ae2014-02-04 16:04:05 -05002348 initializeUniformStorage();
2349
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002350 return true;
2351}
2352
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002353int totalRegisterCount(const sh::Uniform &uniform)
2354{
2355 int registerCount = 0;
2356
2357 if (!uniform.fields.empty())
2358 {
2359 for (unsigned int fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
2360 {
2361 registerCount += totalRegisterCount(uniform.fields[fieldIndex]);
2362 }
2363 }
2364 else
2365 {
2366 registerCount = 1;
2367 }
2368
2369 return (uniform.arraySize > 0) ? uniform.arraySize * registerCount : registerCount;
2370}
2371
Nicolas Capens43e8ba82013-07-09 10:35:15 -04002372TextureType ProgramBinary::getTextureType(GLenum samplerType, InfoLog &infoLog)
2373{
2374 switch(samplerType)
2375 {
2376 case GL_SAMPLER_2D:
2377 case GL_INT_SAMPLER_2D:
2378 case GL_UNSIGNED_INT_SAMPLER_2D:
Nicolas Capenscb127d32013-07-15 17:26:18 -04002379 case GL_SAMPLER_2D_SHADOW:
Nicolas Capens43e8ba82013-07-09 10:35:15 -04002380 return TEXTURE_2D;
2381 case GL_SAMPLER_3D:
2382 case GL_INT_SAMPLER_3D:
2383 case GL_UNSIGNED_INT_SAMPLER_3D:
2384 return TEXTURE_3D;
2385 case GL_SAMPLER_CUBE:
Nicolas Capenscb127d32013-07-15 17:26:18 -04002386 case GL_SAMPLER_CUBE_SHADOW:
Nicolas Capens43e8ba82013-07-09 10:35:15 -04002387 return TEXTURE_CUBE;
2388 case GL_INT_SAMPLER_CUBE:
2389 case GL_UNSIGNED_INT_SAMPLER_CUBE:
2390 //UNIMPLEMENTED();
2391 infoLog.append("Integer cube texture sampling is currently not supported by ANGLE and returns a black color.");
2392 return TEXTURE_CUBE;
2393 case GL_SAMPLER_2D_ARRAY:
2394 case GL_INT_SAMPLER_2D_ARRAY:
2395 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
Nicolas Capenscb127d32013-07-15 17:26:18 -04002396 case GL_SAMPLER_2D_ARRAY_SHADOW:
Nicolas Capens43e8ba82013-07-09 10:35:15 -04002397 return TEXTURE_2D_ARRAY;
2398 default: UNREACHABLE();
2399 }
2400
2401 return TEXTURE_2D;
2402}
2403
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002404bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog)
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002405{
Jamie Madillfcef3362013-11-13 19:37:19 -05002406 if (constant.isStruct())
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002407 {
2408 if (constant.arraySize > 0)
2409 {
2410 unsigned int elementRegisterIndex = constant.registerIndex;
2411
2412 for (unsigned int elementIndex = 0; elementIndex < constant.arraySize; elementIndex++)
2413 {
2414 for (size_t fieldIndex = 0; fieldIndex < constant.fields.size(); fieldIndex++)
2415 {
2416 const sh::Uniform &field = constant.fields[fieldIndex];
Jamie Madill63491ea2013-06-06 11:56:45 -04002417 const std::string &uniformName = constant.name + arrayString(elementIndex) + "." + field.name;
Jamie Madillfcef3362013-11-13 19:37:19 -05002418 sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize,
2419 elementRegisterIndex, field.elementIndex);
2420
2421 fieldUniform.fields = field.fields;
2422
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002423 if (!defineUniform(shader, fieldUniform, infoLog))
2424 {
2425 return false;
2426 }
2427 elementRegisterIndex += totalRegisterCount(field);
2428 }
2429 }
2430 }
2431 else
2432 {
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002433 for (size_t fieldIndex = 0; fieldIndex < constant.fields.size(); fieldIndex++)
2434 {
2435 const sh::Uniform &field = constant.fields[fieldIndex];
2436 const std::string &uniformName = constant.name + "." + field.name;
2437
Jamie Madill56093782013-08-30 13:21:11 -04002438 sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize,
2439 field.registerIndex, field.elementIndex);
2440
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002441 fieldUniform.fields = field.fields;
2442
2443 if (!defineUniform(shader, fieldUniform, infoLog))
2444 {
2445 return false;
2446 }
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +00002447 }
2448 }
2449
2450 return true;
2451 }
2452
Nicolas Capense6050882013-07-08 10:43:10 -04002453 if (IsSampler(constant.type))
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002454 {
2455 unsigned int samplerIndex = constant.registerIndex;
2456
2457 do
2458 {
2459 if (shader == GL_VERTEX_SHADER)
2460 {
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00002461 if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits())
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002462 {
2463 mSamplersVS[samplerIndex].active = true;
Nicolas Capens43e8ba82013-07-09 10:35:15 -04002464 mSamplersVS[samplerIndex].textureType = getTextureType(constant.type, infoLog);
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002465 mSamplersVS[samplerIndex].logicalTextureUnit = 0;
2466 mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
2467 }
2468 else
2469 {
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00002470 infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits());
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002471 return false;
2472 }
2473 }
2474 else if (shader == GL_FRAGMENT_SHADER)
2475 {
2476 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
2477 {
2478 mSamplersPS[samplerIndex].active = true;
Nicolas Capens43e8ba82013-07-09 10:35:15 -04002479 mSamplersPS[samplerIndex].textureType = getTextureType(constant.type, infoLog);
daniel@transgaming.comda8d3802012-12-20 21:12:55 +00002480 mSamplersPS[samplerIndex].logicalTextureUnit = 0;
2481 mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
2482 }
2483 else
2484 {
2485 infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
2486 return false;
2487 }
2488 }
2489 else UNREACHABLE();
2490
2491 samplerIndex++;
2492 }
2493 while (samplerIndex < constant.registerIndex + constant.arraySize);
2494 }
2495
daniel@transgaming.come6d12e92012-12-20 21:12:47 +00002496 Uniform *uniform = NULL;
2497 GLint location = getUniformLocation(constant.name);
2498
shannon.woods@transgaming.comd5a91b92013-02-28 23:17:30 +00002499 if (location >= 0) // Previously defined, type and precision must match
daniel@transgaming.come6d12e92012-12-20 21:12:47 +00002500 {
2501 uniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.come6d12e92012-12-20 21:12:47 +00002502 }
2503 else
2504 {
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00002505 uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize, -1, sh::BlockMemberInfo::defaultBlockInfo);
Jamie Madill56093782013-08-30 13:21:11 -04002506 uniform->registerElement = constant.elementIndex;
daniel@transgaming.come6d12e92012-12-20 21:12:47 +00002507 }
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002508
2509 if (!uniform)
2510 {
2511 return false;
2512 }
2513
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002514 if (shader == GL_FRAGMENT_SHADER)
2515 {
daniel@transgaming.come76b64b2013-01-11 04:10:08 +00002516 uniform->psRegisterIndex = constant.registerIndex;
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002517 }
2518 else if (shader == GL_VERTEX_SHADER)
2519 {
daniel@transgaming.come76b64b2013-01-11 04:10:08 +00002520 uniform->vsRegisterIndex = constant.registerIndex;
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002521 }
2522 else UNREACHABLE();
2523
2524 if (location >= 0)
2525 {
daniel@transgaming.come6d12e92012-12-20 21:12:47 +00002526 return uniform->type == constant.type;
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002527 }
2528
2529 mUniforms.push_back(uniform);
2530 unsigned int uniformIndex = mUniforms.size() - 1;
2531
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002532 for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform->elementCount(); arrayElementIndex++)
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002533 {
Jamie Madill63491ea2013-06-06 11:56:45 -04002534 mUniformIndex.push_back(VariableLocation(uniform->name, arrayElementIndex, uniformIndex));
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002535 }
2536
shannon.woods@transgaming.comd8136cb2013-02-28 23:14:44 +00002537 if (shader == GL_VERTEX_SHADER)
2538 {
2539 if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors())
2540 {
2541 infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors());
2542 return false;
2543 }
2544 }
2545 else if (shader == GL_FRAGMENT_SHADER)
2546 {
2547 if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors())
2548 {
2549 infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors());
2550 return false;
2551 }
2552 }
2553 else UNREACHABLE();
2554
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +00002555 return true;
2556}
2557
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002558bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock)
2559{
2560 const char* blockName = vertexInterfaceBlock.name.c_str();
2561
2562 // validate blocks for the same member types
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002563 if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002564 {
2565 infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
2566 return false;
2567 }
2568
2569 if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
2570 {
2571 infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
2572 return false;
2573 }
2574
Jamie Madill9060a4e2013-08-12 16:22:57 -07002575 if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
2576 {
2577 infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
2578 return false;
2579 }
2580
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002581 const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002582 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
2583 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002584 const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
2585 const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002586
2587 if (vertexMember.name != fragmentMember.name)
2588 {
Jamie Madill28167c62013-08-30 13:21:10 -04002589 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 +00002590 blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
2591 return false;
2592 }
2593
Jamie Madill28167c62013-08-30 13:21:10 -04002594 std::string uniformName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002595 if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember))
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002596 {
2597 return false;
2598 }
2599 }
2600
2601 return true;
2602}
2603
2604bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const sh::ActiveInterfaceBlocks &vertexInterfaceBlocks, const sh::ActiveInterfaceBlocks &fragmentInterfaceBlocks)
2605{
2606 // Check that interface blocks defined in the vertex and fragment shaders are identical
2607 typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
2608 UniformBlockMap linkedUniformBlocks;
2609
2610 for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
2611 {
2612 const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
2613 linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
2614 }
2615
2616 for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
2617 {
2618 const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
2619 UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
2620 if (entry != linkedUniformBlocks.end())
2621 {
2622 const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
2623 if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
2624 {
2625 return false;
2626 }
2627 }
2628 }
2629
2630 for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
2631 {
2632 if (!defineUniformBlock(infoLog, GL_VERTEX_SHADER, vertexInterfaceBlocks[blockIndex]))
2633 {
2634 return false;
2635 }
2636 }
2637
2638 for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
2639 {
2640 if (!defineUniformBlock(infoLog, GL_FRAGMENT_SHADER, fragmentInterfaceBlocks[blockIndex]))
2641 {
2642 return false;
2643 }
2644 }
2645
2646 return true;
2647}
2648
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002649void ProgramBinary::defineUniformBlockMembers(const std::vector<sh::InterfaceBlockField> &fields, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector<unsigned int> *blockUniformIndexes)
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002650{
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002651 for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002652 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002653 const sh::InterfaceBlockField &field = fields[uniformIndex];
2654 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002655
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002656 if (!field.fields.empty())
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002657 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002658 if (field.arraySize > 0)
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +00002659 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002660 for (unsigned int arrayElement = 0; arrayElement < field.arraySize; arrayElement++)
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +00002661 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002662 const std::string uniformElementName = fieldName + arrayString(arrayElement);
2663 defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, blockInfoItr, blockUniformIndexes);
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +00002664 }
2665 }
2666 else
2667 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002668 defineUniformBlockMembers(field.fields, fieldName, blockIndex, blockInfoItr, blockUniformIndexes);
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +00002669 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002670 }
2671 else
2672 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002673 Uniform *newUniform = new Uniform(field.type, field.precision, fieldName, field.arraySize,
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002674 blockIndex, **blockInfoItr);
2675
2676 // add to uniform list, but not index, since uniform block uniforms have no location
2677 blockUniformIndexes->push_back(mUniforms.size());
2678 mUniforms.push_back(newUniform);
2679 (*blockInfoItr)++;
2680 }
2681 }
2682}
2683
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002684bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh::InterfaceBlock &interfaceBlock)
2685{
2686 // create uniform block entries if they do not exist
2687 if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
2688 {
2689 std::vector<unsigned int> blockUniformIndexes;
2690 const unsigned int blockIndex = mUniformBlocks.size();
2691
2692 // define member uniforms
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +00002693 BlockInfoItr blockInfoItr = interfaceBlock.blockInfo.cbegin();
Jamie Madill9d2ffb12013-08-30 13:21:04 -04002694 defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, &blockInfoItr, &blockUniformIndexes);
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002695
2696 // create all the uniform blocks
2697 if (interfaceBlock.arraySize > 0)
2698 {
2699 for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
2700 {
2701 gl::UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, interfaceBlock.dataSize);
2702 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
2703 mUniformBlocks.push_back(newUniformBlock);
2704 }
2705 }
2706 else
2707 {
2708 gl::UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, interfaceBlock.dataSize);
2709 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
2710 mUniformBlocks.push_back(newUniformBlock);
2711 }
2712 }
2713
2714 // Assign registers to the uniform blocks
2715 const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
2716 const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
2717 ASSERT(blockIndex != GL_INVALID_INDEX);
2718 ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
2719
2720 for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
2721 {
2722 gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
2723 ASSERT(uniformBlock->name == interfaceBlock.name);
2724
2725 if (!assignUniformBlockRegister(infoLog, uniformBlock, shader, interfaceBlock.registerIndex + uniformBlockElement))
2726 {
2727 return false;
2728 }
2729 }
2730
2731 return true;
2732}
2733
2734bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex)
2735{
2736 if (shader == GL_VERTEX_SHADER)
2737 {
2738 uniformBlock->vsRegisterIndex = registerIndex;
2739 unsigned int maximumBlocks = mRenderer->getMaxVertexShaderUniformBuffers();
2740
2741 if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= maximumBlocks)
2742 {
2743 infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", maximumBlocks);
2744 return false;
2745 }
2746 }
2747 else if (shader == GL_FRAGMENT_SHADER)
2748 {
2749 uniformBlock->psRegisterIndex = registerIndex;
2750 unsigned int maximumBlocks = mRenderer->getMaxFragmentShaderUniformBuffers();
2751
2752 if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= maximumBlocks)
2753 {
Jamie Madill6fb09f62013-06-21 09:15:31 -04002754 infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", maximumBlocks);
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +00002755 return false;
2756 }
2757 }
2758 else UNREACHABLE();
2759
2760 return true;
2761}
2762
Jamie Madilla6da33a2013-08-30 13:21:07 -04002763std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002764{
2765 // for now we only handle point sprite emulation
2766 ASSERT(usesPointSpriteEmulation());
2767 return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader);
2768}
2769
Jamie Madilla6da33a2013-08-30 13:21:07 -04002770std::string ProgramBinary::generatePointSpriteHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002771{
2772 ASSERT(registers >= 0);
2773 ASSERT(vertexShader->mUsesPointSize);
2774 ASSERT(mRenderer->getMajorShaderModel() >= 4);
2775
2776 std::string geomHLSL;
2777
2778 std::string varyingSemantic = "TEXCOORD";
2779
2780 std::string fragCoordSemantic;
2781 std::string pointCoordSemantic;
2782
2783 int reservedRegisterIndex = registers;
2784
2785 if (fragmentShader->mUsesFragCoord)
2786 {
2787 fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
2788 }
2789
2790 if (fragmentShader->mUsesPointCoord)
2791 {
2792 pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++);
2793 }
2794
shannon.woods@transgaming.coma14ecf32013-02-28 23:09:42 +00002795 geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n"
2796 "\n"
2797 "struct GS_INPUT\n"
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002798 "{\n";
2799
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00002800 std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002801
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00002802 geomHLSL += varyingHLSL;
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002803
2804 if (fragmentShader->mUsesFragCoord)
2805 {
2806 geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
2807 }
2808
2809 geomHLSL += " float gl_PointSize : PSIZE;\n"
2810 " float4 gl_Position : SV_Position;\n"
shannon.woods@transgaming.com276337c2013-02-28 23:15:16 +00002811 "};\n"
2812 "\n"
2813 "struct GS_OUTPUT\n"
2814 "{\n";
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002815
shannon.woods%transgaming.com@gtempaccount.com7bc65f22013-04-13 03:41:39 +00002816 geomHLSL += varyingHLSL;
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002817
2818 if (fragmentShader->mUsesFragCoord)
2819 {
2820 geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
2821 }
2822
2823 if (fragmentShader->mUsesPointCoord)
2824 {
2825 geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
2826 }
2827
shannon.woods@transgaming.com276337c2013-02-28 23:15:16 +00002828 geomHLSL += " float gl_PointSize : PSIZE;\n"
2829 " float4 gl_Position : SV_Position;\n"
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002830 "};\n"
2831 "\n"
2832 "static float2 pointSpriteCorners[] = \n"
2833 "{\n"
2834 " float2( 0.5f, -0.5f),\n"
2835 " float2( 0.5f, 0.5f),\n"
2836 " float2(-0.5f, -0.5f),\n"
2837 " float2(-0.5f, 0.5f)\n"
2838 "};\n"
2839 "\n"
2840 "static float2 pointSpriteTexcoords[] = \n"
2841 "{\n"
2842 " float2(1.0f, 1.0f),\n"
2843 " float2(1.0f, 0.0f),\n"
2844 " float2(0.0f, 1.0f),\n"
2845 " float2(0.0f, 0.0f)\n"
2846 "};\n"
2847 "\n"
2848 "static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n"
2849 "static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n"
2850 "\n"
2851 "[maxvertexcount(4)]\n"
2852 "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
2853 "{\n"
shannon.woods@transgaming.com276337c2013-02-28 23:15:16 +00002854 " GS_OUTPUT output = (GS_OUTPUT)0;\n"
2855 " output.gl_PointSize = input[0].gl_PointSize;\n";
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002856
2857 for (int r = 0; r < registers; r++)
2858 {
2859 geomHLSL += " output.v" + str(r) + " = input[0].v" + str(r) + ";\n";
2860 }
2861
2862 if (fragmentShader->mUsesFragCoord)
2863 {
2864 geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n";
2865 }
2866
2867 geomHLSL += " \n"
2868 " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n"
2869 " float4 gl_Position = input[0].gl_Position;\n"
shannon.woods@transgaming.com771ca2a2013-02-28 23:14:52 +00002870 " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n";
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +00002871
2872 for (int corner = 0; corner < 4; corner++)
2873 {
2874 geomHLSL += " \n"
2875 " output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
2876
2877 if (fragmentShader->mUsesPointCoord)
2878 {
2879 geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n";
2880 }
2881
2882 geomHLSL += " outStream.Append(output);\n";
2883 }
2884
2885 geomHLSL += " \n"
2886 " outStream.RestartStrip();\n"
2887 "}\n";
2888
2889 return geomHLSL;
2890}
2891
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002892// This method needs to match OutputHLSL::decorate
2893std::string ProgramBinary::decorateAttribute(const std::string &name)
2894{
2895 if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
2896 {
2897 return "_" + name;
2898 }
2899
2900 return name;
2901}
2902
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002903bool ProgramBinary::isValidated() const
2904{
2905 return mValidated;
2906}
2907
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002908void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002909{
2910 // Skip over inactive attributes
2911 unsigned int activeAttribute = 0;
2912 unsigned int attribute;
2913 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2914 {
2915 if (mLinkedAttribute[attribute].name.empty())
2916 {
2917 continue;
2918 }
2919
2920 if (activeAttribute == index)
2921 {
2922 break;
2923 }
2924
2925 activeAttribute++;
2926 }
2927
2928 if (bufsize > 0)
2929 {
2930 const char *string = mLinkedAttribute[attribute].name.c_str();
2931
2932 strncpy(name, string, bufsize);
2933 name[bufsize - 1] = '\0';
2934
2935 if (length)
2936 {
2937 *length = strlen(name);
2938 }
2939 }
2940
2941 *size = 1; // Always a single 'type' instance
2942
2943 *type = mLinkedAttribute[attribute].type;
2944}
2945
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002946GLint ProgramBinary::getActiveAttributeCount() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002947{
2948 int count = 0;
2949
2950 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2951 {
2952 if (!mLinkedAttribute[attributeIndex].name.empty())
2953 {
2954 count++;
2955 }
2956 }
2957
2958 return count;
2959}
2960
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002961GLint ProgramBinary::getActiveAttributeMaxLength() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002962{
2963 int maxLength = 0;
2964
2965 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2966 {
2967 if (!mLinkedAttribute[attributeIndex].name.empty())
2968 {
2969 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2970 }
2971 }
2972
2973 return maxLength;
2974}
2975
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00002976void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002977{
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002978 ASSERT(index < mUniforms.size()); // index must be smaller than getActiveUniformCount()
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002979
2980 if (bufsize > 0)
2981 {
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002982 std::string string = mUniforms[index]->name;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002983
daniel@transgaming.com8320a282012-12-20 21:08:08 +00002984 if (mUniforms[index]->isArray())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002985 {
2986 string += "[0]";
2987 }
2988
2989 strncpy(name, string.c_str(), bufsize);
2990 name[bufsize - 1] = '\0';
2991
2992 if (length)
2993 {
2994 *length = strlen(name);
2995 }
2996 }
2997
daniel@transgaming.come6d12e92012-12-20 21:12:47 +00002998 *size = mUniforms[index]->elementCount();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002999
daniel@transgaming.com8320a282012-12-20 21:08:08 +00003000 *type = mUniforms[index]->type;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003001}
3002
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00003003GLint ProgramBinary::getActiveUniformCount() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003004{
daniel@transgaming.com8320a282012-12-20 21:08:08 +00003005 return mUniforms.size();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003006}
3007
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00003008GLint ProgramBinary::getActiveUniformMaxLength() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003009{
3010 int maxLength = 0;
3011
3012 unsigned int numUniforms = mUniforms.size();
3013 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
3014 {
daniel@transgaming.com8320a282012-12-20 21:08:08 +00003015 if (!mUniforms[uniformIndex]->name.empty())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003016 {
3017 int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
3018 if (mUniforms[uniformIndex]->isArray())
3019 {
3020 length += 3; // Counting in "[0]".
3021 }
3022 maxLength = std::max(length, maxLength);
3023 }
3024 }
3025
3026 return maxLength;
3027}
3028
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00003029GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
3030{
3031 const gl::Uniform& uniform = *mUniforms[index];
3032
3033 switch (pname)
3034 {
3035 case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
3036 case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount());
shannonwoods@chromium.orgb1dc1b62013-05-30 00:15:43 +00003037 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 +00003038 case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex;
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00003039
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00003040 case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset;
3041 case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
3042 case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
3043 case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00003044
3045 default:
3046 UNREACHABLE();
3047 break;
3048 }
3049 return 0;
3050}
3051
shannonwoods@chromium.orgbeb02782013-05-30 00:07:28 +00003052void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
3053{
3054 ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
3055
3056 const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
3057
3058 if (bufSize > 0)
3059 {
3060 std::string string = uniformBlock.name;
3061
3062 if (uniformBlock.isArrayElement())
3063 {
Jamie Madill63491ea2013-06-06 11:56:45 -04003064 string += arrayString(uniformBlock.elementIndex);
shannonwoods@chromium.orgbeb02782013-05-30 00:07:28 +00003065 }
3066
3067 strncpy(uniformBlockName, string.c_str(), bufSize);
3068 uniformBlockName[bufSize - 1] = '\0';
3069
3070 if (length)
3071 {
3072 *length = strlen(uniformBlockName);
3073 }
3074 }
3075}
3076
shannonwoods@chromium.orge7317ca2013-05-30 00:07:35 +00003077void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
3078{
3079 ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
3080
3081 const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
3082
3083 switch (pname)
3084 {
3085 case GL_UNIFORM_BLOCK_DATA_SIZE:
3086 *params = static_cast<GLint>(uniformBlock.dataSize);
3087 break;
3088 case GL_UNIFORM_BLOCK_NAME_LENGTH:
shannonwoods@chromium.org932cc6b2013-05-30 00:15:37 +00003089 *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
shannonwoods@chromium.orge7317ca2013-05-30 00:07:35 +00003090 break;
3091 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
3092 *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
3093 break;
3094 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
3095 {
3096 for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
3097 {
3098 params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
3099 }
3100 }
3101 break;
3102 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
3103 *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
3104 break;
3105 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
3106 *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
3107 break;
3108 default: UNREACHABLE();
3109 }
3110}
3111
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +00003112GLuint ProgramBinary::getActiveUniformBlockCount() const
3113{
3114 return mUniformBlocks.size();
3115}
3116
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +00003117GLuint ProgramBinary::getActiveUniformBlockMaxLength() const
3118{
3119 unsigned int maxLength = 0;
3120
3121 unsigned int numUniformBlocks = mUniformBlocks.size();
3122 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
3123 {
3124 const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
3125 if (!uniformBlock.name.empty())
3126 {
3127 const unsigned int length = uniformBlock.name.length() + 1;
3128
3129 // Counting in "[0]".
3130 const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
3131
3132 maxLength = std::max(length + arrayLength, maxLength);
3133 }
3134 }
3135
3136 return maxLength;
3137}
3138
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003139void ProgramBinary::validate(InfoLog &infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003140{
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003141 applyUniforms();
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003142 if (!validateSamplers(&infoLog))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003143 {
3144 mValidated = false;
3145 }
3146 else
3147 {
3148 mValidated = true;
3149 }
3150}
3151
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003152bool ProgramBinary::validateSamplers(InfoLog *infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003153{
3154 // if any two active samplers in a program are of different types, but refer to the same
3155 // texture image unit, and this is the current program, then ValidateProgram will fail, and
3156 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
3157
shannon.woods@transgaming.com76cd88c2013-01-25 21:54:36 +00003158 const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00003159 TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003160
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00003161 for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003162 {
3163 textureUnitType[i] = TEXTURE_UNKNOWN;
3164 }
3165
3166 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
3167 {
3168 if (mSamplersPS[i].active)
3169 {
3170 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
3171
3172 if (unit >= maxCombinedTextureImageUnits)
3173 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003174 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003175 {
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00003176 infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003177 }
3178
3179 return false;
3180 }
3181
3182 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
3183 {
3184 if (mSamplersPS[i].textureType != textureUnitType[unit])
3185 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003186 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003187 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003188 infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003189 }
3190
3191 return false;
3192 }
3193 }
3194 else
3195 {
3196 textureUnitType[unit] = mSamplersPS[i].textureType;
3197 }
3198 }
3199 }
3200
3201 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
3202 {
3203 if (mSamplersVS[i].active)
3204 {
3205 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
3206
3207 if (unit >= maxCombinedTextureImageUnits)
3208 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003209 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003210 {
shannon.woods@transgaming.com233fe952013-01-25 21:51:57 +00003211 infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003212 }
3213
3214 return false;
3215 }
3216
3217 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
3218 {
3219 if (mSamplersVS[i].textureType != textureUnitType[unit])
3220 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003221 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003222 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00003223 infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003224 }
3225
3226 return false;
3227 }
3228 }
3229 else
3230 {
3231 textureUnitType[unit] = mSamplersVS[i].textureType;
3232 }
3233 }
3234 }
3235
3236 return true;
3237}
3238
apatrick@chromium.org90080e32012-07-09 22:15:33 +00003239ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
3240{
3241}
3242
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00003243struct AttributeSorter
3244{
3245 AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
3246 : originalIndices(semanticIndices)
3247 {
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00003248 }
3249
3250 bool operator()(int a, int b)
3251 {
Jamie Madill03181ab2013-12-18 12:56:06 -05003252 if (originalIndices[a] == -1) return false;
3253 if (originalIndices[b] == -1) return true;
3254 return (originalIndices[a] < originalIndices[b]);
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00003255 }
3256
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00003257 const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
3258};
3259
Al Patrick3f2daa82013-08-07 12:58:57 -07003260void ProgramBinary::initAttributesByLayout()
3261{
3262 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
3263 {
3264 mAttributesByLayout[i] = i;
3265 }
3266
3267 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
3268}
3269
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00003270void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
3271{
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00003272 rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
3273
3274 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
3275 {
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00003276 oldTranslatedAttributes[i] = attributes[i];
3277 }
3278
3279 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
3280 {
Al Patrick3f2daa82013-08-07 12:58:57 -07003281 int oldIndex = mAttributesByLayout[i];
3282 sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00003283 attributes[i] = oldTranslatedAttributes[oldIndex];
3284 }
3285}
3286
Jamie Madill8ff21ae2014-02-04 16:04:05 -05003287void ProgramBinary::initializeUniformStorage()
3288{
3289 // Compute total default block size
3290 unsigned int vertexRegisters = 0;
3291 unsigned int fragmentRegisters = 0;
3292 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
3293 {
3294 const Uniform &uniform = *mUniforms[uniformIndex];
3295
3296 if (!IsSampler(uniform.type))
3297 {
3298 if (uniform.isReferencedByVertexShader())
3299 {
3300 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
3301 }
3302 if (uniform.isReferencedByFragmentShader())
3303 {
3304 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
3305 }
3306 }
3307 }
3308
3309 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
3310 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
3311}
3312
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003313}