blob: 6b94b7a4d8ed18544d3766c98c963e6f5936283c [file] [log] [blame]
Brandon Jonesc9610c52014-08-25 17:02:59 -07001//
2// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/renderer/d3d/ProgramD3D.h"
Geoff Lang22072132014-11-20 15:15:01 -050010#include "libANGLE/features.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Framebuffer.h"
12#include "libANGLE/FramebufferAttachment.h"
13#include "libANGLE/Program.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/renderer/ShaderExecutable.h"
15#include "libANGLE/renderer/d3d/DynamicHLSL.h"
16#include "libANGLE/renderer/d3d/RendererD3D.h"
17#include "libANGLE/renderer/d3d/ShaderD3D.h"
Brandon Jonesc9610c52014-08-25 17:02:59 -070018
Geoff Lang22072132014-11-20 15:15:01 -050019#include "common/utilities.h"
20
Brandon Jonesc9610c52014-08-25 17:02:59 -070021namespace rx
22{
23
Brandon Joneseb994362014-09-24 10:27:28 -070024namespace
25{
26
Brandon Jones1a8a7e32014-10-01 12:49:30 -070027GLenum GetTextureType(GLenum samplerType)
28{
29 switch (samplerType)
30 {
31 case GL_SAMPLER_2D:
32 case GL_INT_SAMPLER_2D:
33 case GL_UNSIGNED_INT_SAMPLER_2D:
34 case GL_SAMPLER_2D_SHADOW:
35 return GL_TEXTURE_2D;
36 case GL_SAMPLER_3D:
37 case GL_INT_SAMPLER_3D:
38 case GL_UNSIGNED_INT_SAMPLER_3D:
39 return GL_TEXTURE_3D;
40 case GL_SAMPLER_CUBE:
41 case GL_SAMPLER_CUBE_SHADOW:
42 return GL_TEXTURE_CUBE_MAP;
43 case GL_INT_SAMPLER_CUBE:
44 case GL_UNSIGNED_INT_SAMPLER_CUBE:
45 return GL_TEXTURE_CUBE_MAP;
46 case GL_SAMPLER_2D_ARRAY:
47 case GL_INT_SAMPLER_2D_ARRAY:
48 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
49 case GL_SAMPLER_2D_ARRAY_SHADOW:
50 return GL_TEXTURE_2D_ARRAY;
51 default: UNREACHABLE();
52 }
53
54 return GL_TEXTURE_2D;
55}
56
Brandon Joneseb994362014-09-24 10:27:28 -070057void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
58{
59 size_t layoutIndex = 0;
60 for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
61 {
62 ASSERT(layoutIndex < gl::MAX_VERTEX_ATTRIBS);
63
64 const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex];
65
66 if (shaderAttr.type != GL_NONE)
67 {
68 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
69
70 for (size_t rowIndex = 0; static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); rowIndex++, layoutIndex++)
71 {
72 gl::VertexFormat *defaultFormat = &inputLayout[layoutIndex];
73
74 defaultFormat->mType = gl::VariableComponentType(transposedType);
75 defaultFormat->mNormalized = false;
76 defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
77 defaultFormat->mComponents = gl::VariableColumnCount(transposedType);
78 }
79 }
80 }
81}
82
83std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
84{
85 std::vector<GLenum> defaultPixelOutput(1);
86
87 ASSERT(!shaderOutputVars.empty());
88 defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex;
89
90 return defaultPixelOutput;
91}
92
Brandon Jones1a8a7e32014-10-01 12:49:30 -070093bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
94{
95 return var.isRowMajorLayout;
96}
97
98bool IsRowMajorLayout(const sh::ShaderVariable &var)
99{
100 return false;
101}
102
Brandon Joneseb994362014-09-24 10:27:28 -0700103}
104
105ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[],
106 const GLenum signature[],
107 ShaderExecutable *shaderExecutable)
108 : mShaderExecutable(shaderExecutable)
109{
110 for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
111 {
112 mInputs[attributeIndex] = inputLayout[attributeIndex];
113 mSignature[attributeIndex] = signature[attributeIndex];
114 }
115}
116
117ProgramD3D::VertexExecutable::~VertexExecutable()
118{
119 SafeDelete(mShaderExecutable);
120}
121
122bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) const
123{
124 for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
125 {
126 if (mSignature[attributeIndex] != signature[attributeIndex])
127 {
128 return false;
129 }
130 }
131
132 return true;
133}
134
135ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutable *shaderExecutable)
136 : mOutputSignature(outputSignature),
137 mShaderExecutable(shaderExecutable)
138{
139}
140
141ProgramD3D::PixelExecutable::~PixelExecutable()
142{
143 SafeDelete(mShaderExecutable);
144}
145
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700146ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
147{
148}
149
Geoff Lang7dd2e102014-11-10 15:19:26 -0500150unsigned int ProgramD3D::mCurrentSerial = 1;
151
Jamie Madill93e13fb2014-11-06 15:27:25 -0500152ProgramD3D::ProgramD3D(RendererD3D *renderer)
Brandon Jonesc9610c52014-08-25 17:02:59 -0700153 : ProgramImpl(),
154 mRenderer(renderer),
155 mDynamicHLSL(NULL),
Brandon Joneseb994362014-09-24 10:27:28 -0700156 mGeometryExecutable(NULL),
157 mVertexWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
158 mPixelWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
Brandon Jones44151a92014-09-10 11:32:25 -0700159 mUsesPointSize(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700160 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700161 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700162 mUsedVertexSamplerRange(0),
163 mUsedPixelSamplerRange(0),
164 mDirtySamplerMapping(true),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500165 mShaderVersion(100),
166 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700167{
Brandon Joneseb994362014-09-24 10:27:28 -0700168 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700169}
170
171ProgramD3D::~ProgramD3D()
172{
173 reset();
174 SafeDelete(mDynamicHLSL);
175}
176
177ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl)
178{
179 ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl));
180 return static_cast<ProgramD3D*>(impl);
181}
182
183const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl)
184{
185 ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl));
186 return static_cast<const ProgramD3D*>(impl);
187}
188
Brandon Jones44151a92014-09-10 11:32:25 -0700189bool ProgramD3D::usesPointSpriteEmulation() const
190{
191 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
192}
193
194bool ProgramD3D::usesGeometryShader() const
195{
196 return usesPointSpriteEmulation();
197}
198
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700199GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const
200{
201 GLint logicalTextureUnit = -1;
202
203 switch (type)
204 {
205 case gl::SAMPLER_PIXEL:
206 ASSERT(samplerIndex < caps.maxTextureImageUnits);
207 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
208 {
209 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
210 }
211 break;
212 case gl::SAMPLER_VERTEX:
213 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
214 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
215 {
216 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
217 }
218 break;
219 default: UNREACHABLE();
220 }
221
222 if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
223 {
224 return logicalTextureUnit;
225 }
226
227 return -1;
228}
229
230// Returns the texture type for a given Direct3D 9 sampler type and
231// index (0-15 for the pixel shader and 0-3 for the vertex shader).
232GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
233{
234 switch (type)
235 {
236 case gl::SAMPLER_PIXEL:
237 ASSERT(samplerIndex < mSamplersPS.size());
238 ASSERT(mSamplersPS[samplerIndex].active);
239 return mSamplersPS[samplerIndex].textureType;
240 case gl::SAMPLER_VERTEX:
241 ASSERT(samplerIndex < mSamplersVS.size());
242 ASSERT(mSamplersVS[samplerIndex].active);
243 return mSamplersVS[samplerIndex].textureType;
244 default: UNREACHABLE();
245 }
246
247 return GL_TEXTURE_2D;
248}
249
250GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
251{
252 switch (type)
253 {
254 case gl::SAMPLER_PIXEL:
255 return mUsedPixelSamplerRange;
256 case gl::SAMPLER_VERTEX:
257 return mUsedVertexSamplerRange;
258 default:
259 UNREACHABLE();
260 return 0;
261 }
262}
263
264void ProgramD3D::updateSamplerMapping()
265{
266 if (!mDirtySamplerMapping)
267 {
268 return;
269 }
270
271 mDirtySamplerMapping = false;
272
273 // Retrieve sampler uniform values
274 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
275 {
276 gl::LinkedUniform *targetUniform = mUniforms[uniformIndex];
277
278 if (targetUniform->dirty)
279 {
280 if (gl::IsSampler(targetUniform->type))
281 {
282 int count = targetUniform->elementCount();
283 GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data);
284
285 if (targetUniform->isReferencedByFragmentShader())
286 {
287 unsigned int firstIndex = targetUniform->psRegisterIndex;
288
289 for (int i = 0; i < count; i++)
290 {
291 unsigned int samplerIndex = firstIndex + i;
292
293 if (samplerIndex < mSamplersPS.size())
294 {
295 ASSERT(mSamplersPS[samplerIndex].active);
296 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
297 }
298 }
299 }
300
301 if (targetUniform->isReferencedByVertexShader())
302 {
303 unsigned int firstIndex = targetUniform->vsRegisterIndex;
304
305 for (int i = 0; i < count; i++)
306 {
307 unsigned int samplerIndex = firstIndex + i;
308
309 if (samplerIndex < mSamplersVS.size())
310 {
311 ASSERT(mSamplersVS[samplerIndex].active);
312 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
313 }
314 }
315 }
316 }
317 }
318 }
319}
320
321bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
322{
323 // if any two active samplers in a program are of different types, but refer to the same
324 // texture image unit, and this is the current program, then ValidateProgram will fail, and
325 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
326 updateSamplerMapping();
327
328 std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE);
329
330 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
331 {
332 if (mSamplersPS[i].active)
333 {
334 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
335
336 if (unit >= textureUnitTypes.size())
337 {
338 if (infoLog)
339 {
340 infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
341 }
342
343 return false;
344 }
345
346 if (textureUnitTypes[unit] != GL_NONE)
347 {
348 if (mSamplersPS[i].textureType != textureUnitTypes[unit])
349 {
350 if (infoLog)
351 {
352 infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
353 }
354
355 return false;
356 }
357 }
358 else
359 {
360 textureUnitTypes[unit] = mSamplersPS[i].textureType;
361 }
362 }
363 }
364
365 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
366 {
367 if (mSamplersVS[i].active)
368 {
369 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
370
371 if (unit >= textureUnitTypes.size())
372 {
373 if (infoLog)
374 {
375 infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
376 }
377
378 return false;
379 }
380
381 if (textureUnitTypes[unit] != GL_NONE)
382 {
383 if (mSamplersVS[i].textureType != textureUnitTypes[unit])
384 {
385 if (infoLog)
386 {
387 infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
388 }
389
390 return false;
391 }
392 }
393 else
394 {
395 textureUnitTypes[unit] = mSamplersVS[i].textureType;
396 }
397 }
398 }
399
400 return true;
401}
402
Geoff Lang7dd2e102014-11-10 15:19:26 -0500403LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700404{
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500405 int compileFlags = stream->readInt<int>();
406 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
407 {
408 infoLog.append("Mismatched compilation flags.");
409 return LinkResult(false, gl::Error(GL_NO_ERROR));
410 }
411
Brandon Jones44151a92014-09-10 11:32:25 -0700412 stream->readInt(&mShaderVersion);
413
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700414 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
415 for (unsigned int i = 0; i < psSamplerCount; ++i)
416 {
417 Sampler sampler;
418 stream->readBool(&sampler.active);
419 stream->readInt(&sampler.logicalTextureUnit);
420 stream->readInt(&sampler.textureType);
421 mSamplersPS.push_back(sampler);
422 }
423 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
424 for (unsigned int i = 0; i < vsSamplerCount; ++i)
425 {
426 Sampler sampler;
427 stream->readBool(&sampler.active);
428 stream->readInt(&sampler.logicalTextureUnit);
429 stream->readInt(&sampler.textureType);
430 mSamplersVS.push_back(sampler);
431 }
432
433 stream->readInt(&mUsedVertexSamplerRange);
434 stream->readInt(&mUsedPixelSamplerRange);
435
436 const unsigned int uniformCount = stream->readInt<unsigned int>();
437 if (stream->error())
438 {
439 infoLog.append("Invalid program binary.");
Geoff Lang7dd2e102014-11-10 15:19:26 -0500440 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700441 }
442
443 mUniforms.resize(uniformCount);
444 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
445 {
446 GLenum type = stream->readInt<GLenum>();
447 GLenum precision = stream->readInt<GLenum>();
448 std::string name = stream->readString();
449 unsigned int arraySize = stream->readInt<unsigned int>();
450 int blockIndex = stream->readInt<int>();
451
452 int offset = stream->readInt<int>();
453 int arrayStride = stream->readInt<int>();
454 int matrixStride = stream->readInt<int>();
455 bool isRowMajorMatrix = stream->readBool();
456
457 const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
458
459 gl::LinkedUniform *uniform = new gl::LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo);
460
461 stream->readInt(&uniform->psRegisterIndex);
462 stream->readInt(&uniform->vsRegisterIndex);
463 stream->readInt(&uniform->registerCount);
464 stream->readInt(&uniform->registerElement);
465
466 mUniforms[uniformIndex] = uniform;
467 }
468
469 const unsigned int uniformIndexCount = stream->readInt<unsigned int>();
470 if (stream->error())
471 {
472 infoLog.append("Invalid program binary.");
Geoff Lang7dd2e102014-11-10 15:19:26 -0500473 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700474 }
475
476 mUniformIndex.resize(uniformIndexCount);
477 for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
478 {
479 stream->readString(&mUniformIndex[uniformIndexIndex].name);
480 stream->readInt(&mUniformIndex[uniformIndexIndex].element);
481 stream->readInt(&mUniformIndex[uniformIndexIndex].index);
482 }
483
484 unsigned int uniformBlockCount = stream->readInt<unsigned int>();
485 if (stream->error())
486 {
487 infoLog.append("Invalid program binary.");
Geoff Lang7dd2e102014-11-10 15:19:26 -0500488 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700489 }
490
491 mUniformBlocks.resize(uniformBlockCount);
492 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
493 {
494 std::string name = stream->readString();
495 unsigned int elementIndex = stream->readInt<unsigned int>();
496 unsigned int dataSize = stream->readInt<unsigned int>();
497
498 gl::UniformBlock *uniformBlock = new gl::UniformBlock(name, elementIndex, dataSize);
499
500 stream->readInt(&uniformBlock->psRegisterIndex);
501 stream->readInt(&uniformBlock->vsRegisterIndex);
502
503 unsigned int numMembers = stream->readInt<unsigned int>();
504 uniformBlock->memberUniformIndexes.resize(numMembers);
505 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
506 {
507 stream->readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]);
508 }
509
510 mUniformBlocks[uniformBlockIndex] = uniformBlock;
511 }
512
Brandon Joneseb994362014-09-24 10:27:28 -0700513 stream->readInt(&mTransformFeedbackBufferMode);
514 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
515 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
516 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
517 {
518 gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
519
520 stream->readString(&varying.name);
521 stream->readInt(&varying.type);
522 stream->readInt(&varying.size);
523 stream->readString(&varying.semanticName);
524 stream->readInt(&varying.semanticIndex);
525 stream->readInt(&varying.semanticIndexCount);
526 }
527
Brandon Jones22502d52014-08-29 16:58:36 -0700528 stream->readString(&mVertexHLSL);
529 stream->readInt(&mVertexWorkarounds);
530 stream->readString(&mPixelHLSL);
531 stream->readInt(&mPixelWorkarounds);
532 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700533 stream->readBool(&mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700534
535 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
536 mPixelShaderKey.resize(pixelShaderKeySize);
537 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
538 {
539 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
540 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
541 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
542 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
543 }
544
Brandon Joneseb994362014-09-24 10:27:28 -0700545 const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data());
546
547 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
548 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
549 {
550 gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
551
552 for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
553 {
554 gl::VertexFormat *vertexInput = &inputLayout[inputIndex];
555 stream->readInt(&vertexInput->mType);
556 stream->readInt(&vertexInput->mNormalized);
557 stream->readInt(&vertexInput->mComponents);
558 stream->readBool(&vertexInput->mPureInteger);
559 }
560
561 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
562 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400563
564 ShaderExecutable *shaderExecutable = NULL;
565 gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
566 SHADER_VERTEX,
567 mTransformFeedbackLinkedVaryings,
568 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
569 &shaderExecutable);
570 if (error.isError())
571 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500572 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400573 }
574
Brandon Joneseb994362014-09-24 10:27:28 -0700575 if (!shaderExecutable)
576 {
577 infoLog.append("Could not create vertex shader.");
Geoff Lang7dd2e102014-11-10 15:19:26 -0500578 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700579 }
580
581 // generated converted input layout
582 GLenum signature[gl::MAX_VERTEX_ATTRIBS];
583 getInputLayoutSignature(inputLayout, signature);
584
585 // add new binary
586 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
587
588 stream->skip(vertexShaderSize);
589 }
590
591 const size_t pixelShaderCount = stream->readInt<unsigned int>();
592 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
593 {
594 const size_t outputCount = stream->readInt<unsigned int>();
595 std::vector<GLenum> outputs(outputCount);
596 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
597 {
598 stream->readInt(&outputs[outputIndex]);
599 }
600
601 const size_t pixelShaderSize = stream->readInt<unsigned int>();
602 const unsigned char *pixelShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400603 ShaderExecutable *shaderExecutable = NULL;
604 gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
605 mTransformFeedbackLinkedVaryings,
606 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
607 &shaderExecutable);
608 if (error.isError())
609 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500610 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400611 }
Brandon Joneseb994362014-09-24 10:27:28 -0700612
613 if (!shaderExecutable)
614 {
615 infoLog.append("Could not create pixel shader.");
Geoff Lang7dd2e102014-11-10 15:19:26 -0500616 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700617 }
618
619 // add new binary
620 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
621
622 stream->skip(pixelShaderSize);
623 }
624
625 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
626
627 if (geometryShaderSize > 0)
628 {
629 const unsigned char *geometryShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400630 gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
631 mTransformFeedbackLinkedVaryings,
632 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
633 &mGeometryExecutable);
634 if (error.isError())
635 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500636 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400637 }
Brandon Joneseb994362014-09-24 10:27:28 -0700638
639 if (!mGeometryExecutable)
640 {
641 infoLog.append("Could not create geometry shader.");
Geoff Lang7dd2e102014-11-10 15:19:26 -0500642 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700643 }
644 stream->skip(geometryShaderSize);
645 }
646
Brandon Jones18bd4102014-09-22 14:21:44 -0700647 GUID binaryIdentifier = {0};
648 stream->readBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
649
650 GUID identifier = mRenderer->getAdapterIdentifier();
651 if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0)
652 {
653 infoLog.append("Invalid program binary.");
Geoff Lang7dd2e102014-11-10 15:19:26 -0500654 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -0700655 }
656
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700657 initializeUniformStorage();
658
Geoff Lang7dd2e102014-11-10 15:19:26 -0500659 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700660}
661
Geoff Langb543aff2014-09-30 14:52:54 -0400662gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700663{
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500664 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
665
Brandon Jones44151a92014-09-10 11:32:25 -0700666 stream->writeInt(mShaderVersion);
667
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700668 stream->writeInt(mSamplersPS.size());
669 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
670 {
671 stream->writeInt(mSamplersPS[i].active);
672 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
673 stream->writeInt(mSamplersPS[i].textureType);
674 }
675
676 stream->writeInt(mSamplersVS.size());
677 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
678 {
679 stream->writeInt(mSamplersVS[i].active);
680 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
681 stream->writeInt(mSamplersVS[i].textureType);
682 }
683
684 stream->writeInt(mUsedVertexSamplerRange);
685 stream->writeInt(mUsedPixelSamplerRange);
686
687 stream->writeInt(mUniforms.size());
688 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
689 {
690 const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
691
692 stream->writeInt(uniform.type);
693 stream->writeInt(uniform.precision);
694 stream->writeString(uniform.name);
695 stream->writeInt(uniform.arraySize);
696 stream->writeInt(uniform.blockIndex);
697
698 stream->writeInt(uniform.blockInfo.offset);
699 stream->writeInt(uniform.blockInfo.arrayStride);
700 stream->writeInt(uniform.blockInfo.matrixStride);
701 stream->writeInt(uniform.blockInfo.isRowMajorMatrix);
702
703 stream->writeInt(uniform.psRegisterIndex);
704 stream->writeInt(uniform.vsRegisterIndex);
705 stream->writeInt(uniform.registerCount);
706 stream->writeInt(uniform.registerElement);
707 }
708
709 stream->writeInt(mUniformIndex.size());
710 for (size_t i = 0; i < mUniformIndex.size(); ++i)
711 {
712 stream->writeString(mUniformIndex[i].name);
713 stream->writeInt(mUniformIndex[i].element);
714 stream->writeInt(mUniformIndex[i].index);
715 }
716
717 stream->writeInt(mUniformBlocks.size());
718 for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
719 {
720 const gl::UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
721
722 stream->writeString(uniformBlock.name);
723 stream->writeInt(uniformBlock.elementIndex);
724 stream->writeInt(uniformBlock.dataSize);
725
726 stream->writeInt(uniformBlock.memberUniformIndexes.size());
727 for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
728 {
729 stream->writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]);
730 }
731
732 stream->writeInt(uniformBlock.psRegisterIndex);
733 stream->writeInt(uniformBlock.vsRegisterIndex);
734 }
735
Brandon Joneseb994362014-09-24 10:27:28 -0700736 stream->writeInt(mTransformFeedbackBufferMode);
737 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
738 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
739 {
740 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
741
742 stream->writeString(varying.name);
743 stream->writeInt(varying.type);
744 stream->writeInt(varying.size);
745 stream->writeString(varying.semanticName);
746 stream->writeInt(varying.semanticIndex);
747 stream->writeInt(varying.semanticIndexCount);
748 }
749
Brandon Jones22502d52014-08-29 16:58:36 -0700750 stream->writeString(mVertexHLSL);
751 stream->writeInt(mVertexWorkarounds);
752 stream->writeString(mPixelHLSL);
753 stream->writeInt(mPixelWorkarounds);
754 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700755 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700756
Brandon Joneseb994362014-09-24 10:27:28 -0700757 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700758 stream->writeInt(pixelShaderKey.size());
759 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
760 {
Brandon Joneseb994362014-09-24 10:27:28 -0700761 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700762 stream->writeInt(variable.type);
763 stream->writeString(variable.name);
764 stream->writeString(variable.source);
765 stream->writeInt(variable.outputIndex);
766 }
767
Brandon Joneseb994362014-09-24 10:27:28 -0700768 stream->writeInt(mVertexExecutables.size());
769 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
770 {
771 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
772
773 for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
774 {
775 const gl::VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
776 stream->writeInt(vertexInput.mType);
777 stream->writeInt(vertexInput.mNormalized);
778 stream->writeInt(vertexInput.mComponents);
779 stream->writeInt(vertexInput.mPureInteger);
780 }
781
782 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
783 stream->writeInt(vertexShaderSize);
784
785 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
786 stream->writeBytes(vertexBlob, vertexShaderSize);
787 }
788
789 stream->writeInt(mPixelExecutables.size());
790 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
791 {
792 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
793
794 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
795 stream->writeInt(outputs.size());
796 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
797 {
798 stream->writeInt(outputs[outputIndex]);
799 }
800
801 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
802 stream->writeInt(pixelShaderSize);
803
804 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
805 stream->writeBytes(pixelBlob, pixelShaderSize);
806 }
807
808 size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
809 stream->writeInt(geometryShaderSize);
810
811 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
812 {
813 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
814 stream->writeBytes(geometryBlob, geometryShaderSize);
815 }
816
Brandon Jones18bd4102014-09-22 14:21:44 -0700817 GUID binaryIdentifier = mRenderer->getAdapterIdentifier();
Geoff Langb543aff2014-09-30 14:52:54 -0400818 stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
Brandon Jones18bd4102014-09-22 14:21:44 -0700819
Geoff Langb543aff2014-09-30 14:52:54 -0400820 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700821}
822
Geoff Langb543aff2014-09-30 14:52:54 -0400823gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700824{
Brandon Joneseb994362014-09-24 10:27:28 -0700825 std::vector<GLenum> outputs;
826
Jamie Madill48faf802014-11-06 15:27:22 -0500827 const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(mRenderer->getWorkarounds());
Brandon Joneseb994362014-09-24 10:27:28 -0700828
829 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
830 {
831 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
832
833 if (colorbuffer)
834 {
835 outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
836 }
837 else
838 {
839 outputs.push_back(GL_NONE);
840 }
841 }
842
Geoff Langb543aff2014-09-30 14:52:54 -0400843 return getPixelExecutableForOutputLayout(outputs, outExecutable);
Brandon Joneseb994362014-09-24 10:27:28 -0700844}
845
Geoff Langb543aff2014-09-30 14:52:54 -0400846gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature, ShaderExecutable **outExectuable)
Brandon Joneseb994362014-09-24 10:27:28 -0700847{
848 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
849 {
850 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
851 {
Geoff Langb543aff2014-09-30 14:52:54 -0400852 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
853 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700854 }
855 }
856
Brandon Jones22502d52014-08-29 16:58:36 -0700857 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
858 outputSignature);
859
860 // Generate new pixel executable
Brandon Joneseb994362014-09-24 10:27:28 -0700861 gl::InfoLog tempInfoLog;
Geoff Langb543aff2014-09-30 14:52:54 -0400862 ShaderExecutable *pixelExecutable = NULL;
863 gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL,
864 mTransformFeedbackLinkedVaryings,
865 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
866 mPixelWorkarounds, &pixelExecutable);
867 if (error.isError())
868 {
869 return error;
870 }
Brandon Joneseb994362014-09-24 10:27:28 -0700871
872 if (!pixelExecutable)
873 {
874 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
875 tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
876 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
877 }
878 else
879 {
880 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
881 }
Brandon Jones22502d52014-08-29 16:58:36 -0700882
Geoff Langb543aff2014-09-30 14:52:54 -0400883 *outExectuable = pixelExecutable;
884 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700885}
886
Geoff Langb543aff2014-09-30 14:52:54 -0400887gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable)
Brandon Jones22502d52014-08-29 16:58:36 -0700888{
Brandon Joneseb994362014-09-24 10:27:28 -0700889 GLenum signature[gl::MAX_VERTEX_ATTRIBS];
890 getInputLayoutSignature(inputLayout, signature);
891
892 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
893 {
894 if (mVertexExecutables[executableIndex]->matchesSignature(signature))
895 {
Geoff Langb543aff2014-09-30 14:52:54 -0400896 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
897 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700898 }
899 }
900
Brandon Jones22502d52014-08-29 16:58:36 -0700901 // Generate new dynamic layout with attribute conversions
Brandon Joneseb994362014-09-24 10:27:28 -0700902 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes);
Brandon Jones22502d52014-08-29 16:58:36 -0700903
904 // Generate new vertex executable
Brandon Joneseb994362014-09-24 10:27:28 -0700905 gl::InfoLog tempInfoLog;
Geoff Langb543aff2014-09-30 14:52:54 -0400906 ShaderExecutable *vertexExecutable = NULL;
907 gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX,
908 mTransformFeedbackLinkedVaryings,
909 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
910 mVertexWorkarounds, &vertexExecutable);
911 if (error.isError())
912 {
913 return error;
914 }
915
Brandon Joneseb994362014-09-24 10:27:28 -0700916 if (!vertexExecutable)
917 {
918 std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
919 tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
920 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
921 }
922 else
923 {
924 mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
925 }
Brandon Jones22502d52014-08-29 16:58:36 -0700926
Geoff Langb543aff2014-09-30 14:52:54 -0400927 *outExectuable = vertexExecutable;
928 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700929}
930
Geoff Lang7dd2e102014-11-10 15:19:26 -0500931LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
932 int registers)
Brandon Jones44151a92014-09-10 11:32:25 -0700933{
Brandon Jones18bd4102014-09-22 14:21:44 -0700934 ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
935 ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
Brandon Jones44151a92014-09-10 11:32:25 -0700936
Brandon Joneseb994362014-09-24 10:27:28 -0700937 gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS];
938 GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
Geoff Langb543aff2014-09-30 14:52:54 -0400939 ShaderExecutable *defaultVertexExecutable = NULL;
940 gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable);
941 if (error.isError())
942 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500943 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400944 }
Brandon Jones44151a92014-09-10 11:32:25 -0700945
Brandon Joneseb994362014-09-24 10:27:28 -0700946 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Langb543aff2014-09-30 14:52:54 -0400947 ShaderExecutable *defaultPixelExecutable = NULL;
948 error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable);
949 if (error.isError())
950 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500951 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400952 }
Brandon Jones44151a92014-09-10 11:32:25 -0700953
Brandon Joneseb994362014-09-24 10:27:28 -0700954 if (usesGeometryShader())
955 {
956 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
Brandon Jones44151a92014-09-10 11:32:25 -0700957
Geoff Langb543aff2014-09-30 14:52:54 -0400958
959 error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
960 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
961 ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable);
962 if (error.isError())
963 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500964 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400965 }
Brandon Joneseb994362014-09-24 10:27:28 -0700966 }
967
Brandon Jones091540d2014-10-29 11:32:04 -0700968#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Tibor den Ouden97049c62014-10-06 21:39:16 +0200969 if (usesGeometryShader() && mGeometryExecutable)
970 {
971 // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
972 // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch
973 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
974 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
975 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
976 }
977
978 if (defaultVertexExecutable)
979 {
980 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
981 }
982
983 if (defaultPixelExecutable)
984 {
985 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
986 }
987#endif
988
Geoff Langb543aff2014-09-30 14:52:54 -0400989 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
Geoff Lang7dd2e102014-11-10 15:19:26 -0500990 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -0700991}
992
Geoff Lang7dd2e102014-11-10 15:19:26 -0500993LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog,
994 gl::Shader *fragmentShader, gl::Shader *vertexShader,
995 const std::vector<std::string> &transformFeedbackVaryings,
996 GLenum transformFeedbackBufferMode,
997 int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
998 std::map<int, gl::VariableLocation> *outputVariables)
Brandon Jones22502d52014-08-29 16:58:36 -0700999{
Brandon Joneseb994362014-09-24 10:27:28 -07001000 ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
1001 ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
1002
Jamie Madillde8892b2014-11-11 13:00:22 -05001003 mSamplersPS.resize(data.caps->maxTextureImageUnits);
1004 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001005
Brandon Joneseb994362014-09-24 10:27:28 -07001006 mTransformFeedbackBufferMode = transformFeedbackBufferMode;
Brandon Jones22502d52014-08-29 16:58:36 -07001007
1008 mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
1009 mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
1010
1011 mVertexHLSL = vertexShaderD3D->getTranslatedSource();
1012 mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
Brandon Jones44151a92014-09-10 11:32:25 -07001013 mShaderVersion = vertexShaderD3D->getShaderVersion();
Brandon Jones22502d52014-08-29 16:58:36 -07001014
1015 // Map the varyings to the register file
Brandon Joneseb994362014-09-24 10:27:28 -07001016 VaryingPacking packing = { NULL };
Brandon Jones22502d52014-08-29 16:58:36 -07001017 *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
1018
Geoff Langbdee2d52014-09-17 11:02:51 -04001019 if (*registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -07001020 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001021 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001022 }
1023
Geoff Lang7dd2e102014-11-10 15:19:26 -05001024 if (!gl::Program::linkVaryings(infoLog, fragmentShader, vertexShader))
Brandon Jones22502d52014-08-29 16:58:36 -07001025 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001026 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001027 }
1028
Jamie Madillde8892b2014-11-11 13:00:22 -05001029 if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
Brandon Jones22502d52014-08-29 16:58:36 -07001030 fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
1031 linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
1032 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001033 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001034 }
1035
Brandon Jones44151a92014-09-10 11:32:25 -07001036 mUsesPointSize = vertexShaderD3D->usesPointSize();
1037
Geoff Lang7dd2e102014-11-10 15:19:26 -05001038 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001039}
1040
Brandon Jones44151a92014-09-10 11:32:25 -07001041void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const
1042{
1043 mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
1044}
1045
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001046void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001047{
1048 // Compute total default block size
1049 unsigned int vertexRegisters = 0;
1050 unsigned int fragmentRegisters = 0;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001051 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001052 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001053 const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
Brandon Jonesc9610c52014-08-25 17:02:59 -07001054
1055 if (!gl::IsSampler(uniform.type))
1056 {
1057 if (uniform.isReferencedByVertexShader())
1058 {
1059 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
1060 }
1061 if (uniform.isReferencedByFragmentShader())
1062 {
1063 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
1064 }
1065 }
1066 }
1067
1068 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
1069 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1070}
1071
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001072gl::Error ProgramD3D::applyUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001073{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001074 updateSamplerMapping();
1075
1076 gl::Error error = mRenderer->applyUniforms(*this, mUniforms);
1077 if (error.isError())
1078 {
1079 return error;
1080 }
1081
1082 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
1083 {
1084 mUniforms[uniformIndex]->dirty = false;
1085 }
1086
1087 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001088}
1089
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001090gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps)
Brandon Jones18bd4102014-09-22 14:21:44 -07001091{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001092 ASSERT(boundBuffers.size() == mUniformBlocks.size());
1093
Brandon Jones18bd4102014-09-22 14:21:44 -07001094 const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
1095 const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
1096
1097 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1098 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1099
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001100 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001101 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001102 gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex];
Brandon Jones18bd4102014-09-22 14:21:44 -07001103 gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
1104
1105 ASSERT(uniformBlock && uniformBuffer);
1106
1107 if (uniformBuffer->getSize() < uniformBlock->dataSize)
1108 {
1109 // undefined behaviour
1110 return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.");
1111 }
1112
1113 // Unnecessary to apply an unreferenced standard or shared UBO
1114 if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
1115 {
1116 continue;
1117 }
1118
1119 if (uniformBlock->isReferencedByVertexShader())
1120 {
1121 unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
1122 ASSERT(vertexUniformBuffers[registerIndex] == NULL);
1123 ASSERT(registerIndex < caps.maxVertexUniformBlocks);
1124 vertexUniformBuffers[registerIndex] = uniformBuffer;
1125 }
1126
1127 if (uniformBlock->isReferencedByFragmentShader())
1128 {
1129 unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
1130 ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
1131 ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
1132 fragmentUniformBuffers[registerIndex] = uniformBuffer;
1133 }
1134 }
1135
1136 return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
1137}
1138
1139bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
1140 unsigned int registerIndex, const gl::Caps &caps)
1141{
1142 if (shader == GL_VERTEX_SHADER)
1143 {
1144 uniformBlock->vsRegisterIndex = registerIndex;
1145 if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
1146 {
1147 infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
1148 return false;
1149 }
1150 }
1151 else if (shader == GL_FRAGMENT_SHADER)
1152 {
1153 uniformBlock->psRegisterIndex = registerIndex;
1154 if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
1155 {
1156 infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
1157 return false;
1158 }
1159 }
1160 else UNREACHABLE();
1161
1162 return true;
1163}
1164
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001165void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001166{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001167 unsigned int numUniforms = mUniforms.size();
1168 for (unsigned int index = 0; index < numUniforms; index++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001169 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001170 mUniforms[index]->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001171 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001172}
1173
1174void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
1175{
1176 setUniform(location, count, v, GL_FLOAT);
1177}
1178
1179void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1180{
1181 setUniform(location, count, v, GL_FLOAT_VEC2);
1182}
1183
1184void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1185{
1186 setUniform(location, count, v, GL_FLOAT_VEC3);
1187}
1188
1189void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1190{
1191 setUniform(location, count, v, GL_FLOAT_VEC4);
1192}
1193
1194void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1195{
1196 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1197}
1198
1199void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1200{
1201 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1202}
1203
1204void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1205{
1206 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1207}
1208
1209void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1210{
1211 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1212}
1213
1214void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1215{
1216 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1217}
1218
1219void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1220{
1221 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1222}
1223
1224void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1225{
1226 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1227}
1228
1229void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1230{
1231 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1232}
1233
1234void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1235{
1236 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1237}
1238
1239void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1240{
1241 setUniform(location, count, v, GL_INT);
1242}
1243
1244void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1245{
1246 setUniform(location, count, v, GL_INT_VEC2);
1247}
1248
1249void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1250{
1251 setUniform(location, count, v, GL_INT_VEC3);
1252}
1253
1254void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1255{
1256 setUniform(location, count, v, GL_INT_VEC4);
1257}
1258
1259void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1260{
1261 setUniform(location, count, v, GL_UNSIGNED_INT);
1262}
1263
1264void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1265{
1266 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1267}
1268
1269void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1270{
1271 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1272}
1273
1274void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1275{
1276 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1277}
1278
1279void ProgramD3D::getUniformfv(GLint location, GLfloat *params)
1280{
1281 getUniformv(location, params, GL_FLOAT);
1282}
1283
1284void ProgramD3D::getUniformiv(GLint location, GLint *params)
1285{
1286 getUniformv(location, params, GL_INT);
1287}
1288
1289void ProgramD3D::getUniformuiv(GLint location, GLuint *params)
1290{
1291 getUniformv(location, params, GL_UNSIGNED_INT);
1292}
1293
1294bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
1295 const gl::Caps &caps)
1296{
Jamie Madill30d6c252014-11-13 10:03:33 -05001297 const ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader.getImplementation());
1298 const ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader.getImplementation());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001299
1300 const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms();
1301 const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms();
1302
1303 // Check that uniforms defined in the vertex and fragment shaders are identical
1304 typedef std::map<std::string, const sh::Uniform*> UniformMap;
1305 UniformMap linkedUniforms;
1306
1307 for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001308 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001309 const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex];
1310 linkedUniforms[vertexUniform.name] = &vertexUniform;
1311 }
1312
1313 for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++)
1314 {
1315 const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex];
1316 UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name);
1317 if (entry != linkedUniforms.end())
1318 {
1319 const sh::Uniform &vertexUniform = *entry->second;
1320 const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
Geoff Lang7dd2e102014-11-10 15:19:26 -05001321 if (!gl::Program::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001322 {
1323 return false;
1324 }
1325 }
1326 }
1327
1328 for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
1329 {
1330 const sh::Uniform &uniform = vertexUniforms[uniformIndex];
1331
1332 if (uniform.staticUse)
1333 {
1334 defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
1335 }
1336 }
1337
1338 for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
1339 {
1340 const sh::Uniform &uniform = fragmentUniforms[uniformIndex];
1341
1342 if (uniform.staticUse)
1343 {
1344 defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
1345 }
1346 }
1347
1348 if (!indexUniforms(infoLog, caps))
1349 {
1350 return false;
1351 }
1352
1353 initializeUniformStorage();
1354
1355 // special case for gl_DepthRange, the only built-in uniform (also a struct)
1356 if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange())
1357 {
1358 const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo();
1359
1360 mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo));
1361 mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo));
1362 mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo));
1363 }
1364
1365 return true;
1366}
1367
1368void ProgramD3D::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister)
1369{
Jamie Madill30d6c252014-11-13 10:03:33 -05001370 ShShaderOutput outputType = ShaderD3D::getCompilerOutputType(shader);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001371 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
1372 encoder.skipRegisters(uniformRegister);
1373
1374 defineUniform(shader, uniform, uniform.name, &encoder);
1375}
1376
1377void ProgramD3D::defineUniform(GLenum shader, const sh::ShaderVariable &uniform,
1378 const std::string &fullName, sh::HLSLBlockEncoder *encoder)
1379{
1380 if (uniform.isStruct())
1381 {
1382 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1383 {
1384 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1385
1386 encoder->enterAggregateType();
1387
1388 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1389 {
1390 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
1391 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1392
1393 defineUniform(shader, field, fieldFullName, encoder);
1394 }
1395
1396 encoder->exitAggregateType();
1397 }
1398 }
1399 else // Not a struct
1400 {
1401 // Arrays are treated as aggregate types
1402 if (uniform.isArray())
1403 {
1404 encoder->enterAggregateType();
1405 }
1406
1407 gl::LinkedUniform *linkedUniform = getUniformByName(fullName);
1408
1409 if (!linkedUniform)
1410 {
1411 linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
1412 -1, sh::BlockMemberInfo::getDefaultBlockInfo());
1413 ASSERT(linkedUniform);
1414 linkedUniform->registerElement = encoder->getCurrentElement();
1415 mUniforms.push_back(linkedUniform);
1416 }
1417
1418 ASSERT(linkedUniform->registerElement == encoder->getCurrentElement());
1419
1420 if (shader == GL_FRAGMENT_SHADER)
1421 {
1422 linkedUniform->psRegisterIndex = encoder->getCurrentRegister();
1423 }
1424 else if (shader == GL_VERTEX_SHADER)
1425 {
1426 linkedUniform->vsRegisterIndex = encoder->getCurrentRegister();
1427 }
1428 else UNREACHABLE();
1429
1430 // Advance the uniform offset, to track registers allocation for structs
1431 encoder->encodeType(uniform.type, uniform.arraySize, false);
1432
1433 // Arrays are treated as aggregate types
1434 if (uniform.isArray())
1435 {
1436 encoder->exitAggregateType();
1437 }
1438 }
1439}
1440
1441template <typename T>
1442static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
1443{
1444 ASSERT(dest != NULL);
1445 ASSERT(dirtyFlag != NULL);
1446
1447 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
1448 *dest = source;
1449}
1450
1451template <typename T>
1452void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
1453{
1454 const int components = gl::VariableComponentCount(targetUniformType);
1455 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1456
1457 gl::LinkedUniform *targetUniform = getUniformByLocation(location);
1458
1459 int elementCount = targetUniform->elementCount();
1460
1461 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
1462
1463 if (targetUniform->type == targetUniformType)
1464 {
1465 T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4;
1466
1467 for (int i = 0; i < count; i++)
1468 {
1469 T *dest = target + (i * 4);
1470 const T *source = v + (i * components);
1471
1472 for (int c = 0; c < components; c++)
1473 {
1474 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1475 }
1476 for (int c = components; c < 4; c++)
1477 {
1478 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1479 }
1480 }
1481 }
1482 else if (targetUniform->type == targetBoolType)
1483 {
1484 GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
1485
1486 for (int i = 0; i < count; i++)
1487 {
1488 GLint *dest = boolParams + (i * 4);
1489 const T *source = v + (i * components);
1490
1491 for (int c = 0; c < components; c++)
1492 {
1493 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
1494 }
1495 for (int c = components; c < 4; c++)
1496 {
1497 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1498 }
1499 }
1500 }
1501 else if (gl::IsSampler(targetUniform->type))
1502 {
1503 ASSERT(targetUniformType == GL_INT);
1504
1505 GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
1506
1507 bool wasDirty = targetUniform->dirty;
1508
1509 for (int i = 0; i < count; i++)
1510 {
1511 GLint *dest = target + (i * 4);
1512 const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
1513
1514 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1515 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1516 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1517 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1518 }
1519
1520 if (!wasDirty && targetUniform->dirty)
1521 {
1522 mDirtySamplerMapping = true;
1523 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001524 }
1525 else UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001526}
Brandon Jones18bd4102014-09-22 14:21:44 -07001527
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001528template<typename T>
1529bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1530{
1531 bool dirty = false;
1532 int copyWidth = std::min(targetHeight, srcWidth);
1533 int copyHeight = std::min(targetWidth, srcHeight);
1534
1535 for (int x = 0; x < copyWidth; x++)
1536 {
1537 for (int y = 0; y < copyHeight; y++)
1538 {
1539 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
1540 }
1541 }
1542 // clear unfilled right side
1543 for (int y = 0; y < copyWidth; y++)
1544 {
1545 for (int x = copyHeight; x < targetWidth; x++)
1546 {
1547 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1548 }
1549 }
1550 // clear unfilled bottom.
1551 for (int y = copyWidth; y < targetHeight; y++)
1552 {
1553 for (int x = 0; x < targetWidth; x++)
1554 {
1555 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1556 }
1557 }
1558
1559 return dirty;
1560}
1561
1562template<typename T>
1563bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
1564{
1565 bool dirty = false;
1566 int copyWidth = std::min(targetWidth, srcWidth);
1567 int copyHeight = std::min(targetHeight, srcHeight);
1568
1569 for (int y = 0; y < copyHeight; y++)
1570 {
1571 for (int x = 0; x < copyWidth; x++)
1572 {
1573 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
1574 }
1575 }
1576 // clear unfilled right side
1577 for (int y = 0; y < copyHeight; y++)
1578 {
1579 for (int x = copyWidth; x < targetWidth; x++)
1580 {
1581 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1582 }
1583 }
1584 // clear unfilled bottom.
1585 for (int y = copyHeight; y < targetHeight; y++)
1586 {
1587 for (int x = 0; x < targetWidth; x++)
1588 {
1589 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
1590 }
1591 }
1592
1593 return dirty;
1594}
1595
1596template <int cols, int rows>
1597void ProgramD3D::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
1598{
1599 gl::LinkedUniform *targetUniform = getUniformByLocation(location);
1600
1601 int elementCount = targetUniform->elementCount();
1602
1603 count = std::min(elementCount - (int)mUniformIndex[location].element, count);
1604 const unsigned int targetMatrixStride = (4 * rows);
1605 GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
1606
1607 for (int i = 0; i < count; i++)
1608 {
1609 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1610 if (transpose == GL_FALSE)
1611 {
1612 targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
1613 }
1614 else
1615 {
1616 targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
1617 }
1618 target += targetMatrixStride;
1619 value += cols * rows;
1620 }
1621}
1622
1623template <typename T>
1624void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
1625{
1626 gl::LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
1627
1628 if (gl::IsMatrixType(targetUniform->type))
1629 {
1630 const int rows = gl::VariableRowCount(targetUniform->type);
1631 const int cols = gl::VariableColumnCount(targetUniform->type);
1632 transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows);
1633 }
1634 else if (uniformType == gl::VariableComponentType(targetUniform->type))
1635 {
1636 unsigned int size = gl::VariableComponentCount(targetUniform->type);
1637 memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
1638 size * sizeof(T));
1639 }
1640 else
1641 {
1642 unsigned int size = gl::VariableComponentCount(targetUniform->type);
1643 switch (gl::VariableComponentType(targetUniform->type))
1644 {
1645 case GL_BOOL:
1646 {
1647 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
1648
1649 for (unsigned int i = 0; i < size; i++)
1650 {
1651 params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
1652 }
1653 }
1654 break;
1655
1656 case GL_FLOAT:
1657 {
1658 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
1659
1660 for (unsigned int i = 0; i < size; i++)
1661 {
1662 params[i] = static_cast<T>(floatParams[i]);
1663 }
1664 }
1665 break;
1666
1667 case GL_INT:
1668 {
1669 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
1670
1671 for (unsigned int i = 0; i < size; i++)
1672 {
1673 params[i] = static_cast<T>(intParams[i]);
1674 }
1675 }
1676 break;
1677
1678 case GL_UNSIGNED_INT:
1679 {
1680 GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
1681
1682 for (unsigned int i = 0; i < size; i++)
1683 {
1684 params[i] = static_cast<T>(uintParams[i]);
1685 }
1686 }
1687 break;
1688
1689 default: UNREACHABLE();
1690 }
1691 }
1692}
1693
1694template <typename VarT>
1695void ProgramD3D::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
1696 sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
1697 bool inRowMajorLayout)
1698{
1699 for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
1700 {
1701 const VarT &field = fields[uniformIndex];
1702 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
1703
1704 if (field.isStruct())
1705 {
1706 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
1707
1708 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
1709 {
1710 encoder->enterAggregateType();
1711
1712 const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
1713 defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout);
1714
1715 encoder->exitAggregateType();
1716 }
1717 }
1718 else
1719 {
1720 bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
1721
1722 sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
1723
1724 gl::LinkedUniform *newUniform = new gl::LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
1725 blockIndex, memberInfo);
1726
1727 // add to uniform list, but not index, since uniform block uniforms have no location
1728 blockUniformIndexes->push_back(mUniforms.size());
1729 mUniforms.push_back(newUniform);
1730 }
1731 }
1732}
1733
1734bool ProgramD3D::defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock,
1735 const gl::Caps &caps)
1736{
Jamie Madill30d6c252014-11-13 10:03:33 -05001737 const ShaderD3D* shaderD3D = ShaderD3D::makeShaderD3D(shader.getImplementation());
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001738
1739 // create uniform block entries if they do not exist
1740 if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
1741 {
1742 std::vector<unsigned int> blockUniformIndexes;
1743 const unsigned int blockIndex = mUniformBlocks.size();
1744
1745 // define member uniforms
1746 sh::BlockLayoutEncoder *encoder = NULL;
1747
1748 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
1749 {
1750 encoder = new sh::Std140BlockEncoder;
1751 }
1752 else
1753 {
1754 encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1755 }
1756 ASSERT(encoder);
1757
1758 defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout);
1759
1760 size_t dataSize = encoder->getBlockSize();
1761
1762 // create all the uniform blocks
1763 if (interfaceBlock.arraySize > 0)
1764 {
1765 for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
1766 {
1767 gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize);
1768 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
1769 mUniformBlocks.push_back(newUniformBlock);
1770 }
1771 }
1772 else
1773 {
1774 gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize);
1775 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
1776 mUniformBlocks.push_back(newUniformBlock);
1777 }
1778 }
1779
1780 if (interfaceBlock.staticUse)
1781 {
1782 // Assign registers to the uniform blocks
1783 const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
1784 const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
1785 ASSERT(blockIndex != GL_INVALID_INDEX);
1786 ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
1787
1788 unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
1789
1790 for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
1791 {
1792 gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
1793 ASSERT(uniformBlock->name == interfaceBlock.name);
1794
1795 if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(),
1796 interfaceBlockRegister + uniformBlockElement, caps))
1797 {
1798 return false;
1799 }
1800 }
1801 }
1802
1803 return true;
1804}
1805
1806bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex,
1807 GLenum samplerType,
1808 unsigned int samplerCount,
1809 std::vector<Sampler> &outSamplers,
1810 GLuint *outUsedRange)
1811{
1812 unsigned int samplerIndex = startSamplerIndex;
1813
1814 do
1815 {
1816 if (samplerIndex < outSamplers.size())
1817 {
1818 Sampler& sampler = outSamplers[samplerIndex];
1819 sampler.active = true;
1820 sampler.textureType = GetTextureType(samplerType);
1821 sampler.logicalTextureUnit = 0;
1822 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
1823 }
1824 else
1825 {
1826 return false;
1827 }
1828
1829 samplerIndex++;
1830 } while (samplerIndex < startSamplerIndex + samplerCount);
1831
1832 return true;
1833}
1834
1835bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps)
1836{
1837 ASSERT(gl::IsSampler(uniform.type));
1838 ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
1839
1840 if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
1841 {
1842 if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
1843 &mUsedVertexSamplerRange))
1844 {
1845 infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).",
1846 mSamplersVS.size());
1847 return false;
1848 }
1849
1850 unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors;
1851 if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
1852 {
1853 infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)",
1854 caps.maxVertexUniformVectors);
1855 return false;
1856 }
1857 }
1858
1859 if (uniform.psRegisterIndex != GL_INVALID_INDEX)
1860 {
1861 if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
1862 &mUsedPixelSamplerRange))
1863 {
1864 infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
1865 mSamplersPS.size());
1866 return false;
1867 }
1868
1869 unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors;
1870 if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
1871 {
1872 infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)",
1873 caps.maxFragmentUniformVectors);
1874 return false;
1875 }
1876 }
1877
1878 return true;
1879}
1880
1881bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
1882{
1883 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
1884 {
1885 const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
1886
1887 if (gl::IsSampler(uniform.type))
1888 {
1889 if (!indexSamplerUniform(uniform, infoLog, caps))
1890 {
1891 return false;
1892 }
1893 }
1894
1895 for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++)
1896 {
1897 mUniformIndex.push_back(gl::VariableLocation(uniform.name, arrayElementIndex, uniformIndex));
1898 }
1899 }
1900
1901 return true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001902}
1903
Brandon Jonesc9610c52014-08-25 17:02:59 -07001904void ProgramD3D::reset()
1905{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001906 ProgramImpl::reset();
1907
Brandon Joneseb994362014-09-24 10:27:28 -07001908 SafeDeleteContainer(mVertexExecutables);
1909 SafeDeleteContainer(mPixelExecutables);
1910 SafeDelete(mGeometryExecutable);
1911
1912 mTransformFeedbackBufferMode = GL_NONE;
Brandon Joneseb994362014-09-24 10:27:28 -07001913
Brandon Jones22502d52014-08-29 16:58:36 -07001914 mVertexHLSL.clear();
Brandon Joneseb994362014-09-24 10:27:28 -07001915 mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones44151a92014-09-10 11:32:25 -07001916 mShaderVersion = 100;
Brandon Jones22502d52014-08-29 16:58:36 -07001917
1918 mPixelHLSL.clear();
Brandon Joneseb994362014-09-24 10:27:28 -07001919 mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
Brandon Jones22502d52014-08-29 16:58:36 -07001920 mUsesFragDepth = false;
1921 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001922 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -07001923
Brandon Jonesc9610c52014-08-25 17:02:59 -07001924 SafeDelete(mVertexUniformStorage);
1925 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001926
1927 mSamplersPS.clear();
1928 mSamplersVS.clear();
1929
1930 mUsedVertexSamplerRange = 0;
1931 mUsedPixelSamplerRange = 0;
1932 mDirtySamplerMapping = true;
Brandon Jonesc9610c52014-08-25 17:02:59 -07001933}
1934
Geoff Lang7dd2e102014-11-10 15:19:26 -05001935unsigned int ProgramD3D::getSerial() const
1936{
1937 return mSerial;
1938}
1939
1940unsigned int ProgramD3D::issueSerial()
1941{
1942 return mCurrentSerial++;
1943}
1944
Brandon Jonesc9610c52014-08-25 17:02:59 -07001945}