blob: 87649d1e5b55aa46eb3b7a37808a8dedbeeb3123 [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"
Jamie Madill437d2662014-12-05 14:23:35 -050010
Dian Xianga4928832015-09-15 10:11:17 -070011#include "common/BitSetIterator.h"
Jamie Madill437d2662014-12-05 14:23:35 -050012#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Framebuffer.h"
14#include "libANGLE/FramebufferAttachment.h"
15#include "libANGLE/Program.h"
Jamie Madilld3dfda22015-07-06 08:28:49 -040016#include "libANGLE/VertexArray.h"
Jamie Madill6df9b372015-02-18 21:28:19 +000017#include "libANGLE/features.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/renderer/d3d/DynamicHLSL.h"
Jamie Madill85a18042015-03-05 15:41:41 -050019#include "libANGLE/renderer/d3d/FramebufferD3D.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/renderer/d3d/RendererD3D.h"
21#include "libANGLE/renderer/d3d/ShaderD3D.h"
Geoff Lang359ef262015-01-05 14:42:29 -050022#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
Jamie Madill437d2662014-12-05 14:23:35 -050023#include "libANGLE/renderer/d3d/VertexDataManager.h"
Geoff Lang22072132014-11-20 15:15:01 -050024
Brandon Jonesc9610c52014-08-25 17:02:59 -070025namespace rx
26{
27
Brandon Joneseb994362014-09-24 10:27:28 -070028namespace
29{
30
Jamie Madillf8dd7b12015-08-05 13:50:08 -040031gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
Brandon Joneseb994362014-09-24 10:27:28 -070032{
Jamie Madillbd136f92015-08-10 14:51:37 -040033 gl::InputLayout defaultLayout;
34 for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
Brandon Joneseb994362014-09-24 10:27:28 -070035 {
Brandon Joneseb994362014-09-24 10:27:28 -070036 if (shaderAttr.type != GL_NONE)
37 {
38 GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
39
Jamie Madilld3dfda22015-07-06 08:28:49 -040040 for (size_t rowIndex = 0;
Jamie Madill334d6152015-10-22 14:00:28 -040041 static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
Brandon Joneseb994362014-09-24 10:27:28 -070042 {
Jamie Madilld3dfda22015-07-06 08:28:49 -040043 GLenum componentType = gl::VariableComponentType(transposedType);
Jamie Madill334d6152015-10-22 14:00:28 -040044 GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
Jamie Madilld3dfda22015-07-06 08:28:49 -040045 bool pureInt = (componentType != GL_FLOAT);
Jamie Madill334d6152015-10-22 14:00:28 -040046 gl::VertexFormatType defaultType =
47 gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
Brandon Joneseb994362014-09-24 10:27:28 -070048
Jamie Madillbd136f92015-08-10 14:51:37 -040049 defaultLayout.push_back(defaultType);
Brandon Joneseb994362014-09-24 10:27:28 -070050 }
51 }
52 }
Jamie Madillf8dd7b12015-08-05 13:50:08 -040053
54 return defaultLayout;
Brandon Joneseb994362014-09-24 10:27:28 -070055}
56
Jamie Madill334d6152015-10-22 14:00:28 -040057std::vector<GLenum> GetDefaultOutputLayoutFromShader(
58 const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
Brandon Joneseb994362014-09-24 10:27:28 -070059{
Jamie Madillb4463142014-12-19 14:56:54 -050060 std::vector<GLenum> defaultPixelOutput;
Brandon Joneseb994362014-09-24 10:27:28 -070061
Jamie Madillb4463142014-12-19 14:56:54 -050062 if (!shaderOutputVars.empty())
63 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070064 defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
65 static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
Jamie Madillb4463142014-12-19 14:56:54 -050066 }
Brandon Joneseb994362014-09-24 10:27:28 -070067
68 return defaultPixelOutput;
69}
70
Brandon Jones1a8a7e32014-10-01 12:49:30 -070071bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
72{
73 return var.isRowMajorLayout;
74}
75
76bool IsRowMajorLayout(const sh::ShaderVariable &var)
77{
78 return false;
79}
80
Jamie Madill437d2662014-12-05 14:23:35 -050081struct AttributeSorter
82{
Jamie Madill63805b42015-08-25 13:17:39 -040083 AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
Jamie Madill80d934b2015-02-19 10:16:12 -050084 : originalIndices(&semanticIndices)
Jamie Madill437d2662014-12-05 14:23:35 -050085 {
86 }
87
88 bool operator()(int a, int b)
89 {
Jamie Madill80d934b2015-02-19 10:16:12 -050090 int indexA = (*originalIndices)[a];
91 int indexB = (*originalIndices)[b];
92
Jamie Madill334d6152015-10-22 14:00:28 -040093 if (indexA == -1)
94 return false;
95 if (indexB == -1)
96 return true;
Jamie Madill80d934b2015-02-19 10:16:12 -050097 return (indexA < indexB);
Jamie Madill437d2662014-12-05 14:23:35 -050098 }
99
Jamie Madill63805b42015-08-25 13:17:39 -0400100 const ProgramD3D::SemanticIndexArray *originalIndices;
Jamie Madill437d2662014-12-05 14:23:35 -0500101};
102
Jamie Madillca03b352015-09-02 12:38:13 -0400103std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
104 const gl::Shader &fragmentShader,
105 const std::vector<std::string> &tfVaryings)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400106{
Jamie Madillca03b352015-09-02 12:38:13 -0400107 std::vector<PackedVarying> packedVaryings;
108
109 for (const sh::Varying &output : vertexShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400110 {
Jamie Madillca03b352015-09-02 12:38:13 -0400111 bool packed = false;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400112
113 // Built-in varyings obey special rules
Jamie Madillca03b352015-09-02 12:38:13 -0400114 if (output.isBuiltIn())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400115 {
116 continue;
117 }
118
Jamie Madillca03b352015-09-02 12:38:13 -0400119 for (const sh::Varying &input : fragmentShader.getVaryings())
Jamie Madillada9ecc2015-08-17 12:53:37 -0400120 {
Jamie Madillca03b352015-09-02 12:38:13 -0400121 if (output.name == input.name)
Jamie Madillada9ecc2015-08-17 12:53:37 -0400122 {
Jamie Madillca03b352015-09-02 12:38:13 -0400123 packedVaryings.push_back(PackedVarying(input));
124 packed = true;
Jamie Madillada9ecc2015-08-17 12:53:37 -0400125 break;
126 }
127 }
128
Jamie Madillca03b352015-09-02 12:38:13 -0400129 // Keep Transform FB varyings in the merged list always.
130 if (!packed)
131 {
132 for (const std::string &tfVarying : tfVaryings)
133 {
134 if (tfVarying == output.name)
135 {
136 packedVaryings.push_back(PackedVarying(output));
137 packedVaryings.back().vertexOnly = true;
138 break;
139 }
140 }
141 }
Jamie Madillada9ecc2015-08-17 12:53:37 -0400142 }
143
Jamie Madillca03b352015-09-02 12:38:13 -0400144 return packedVaryings;
Brandon Joneseb994362014-09-24 10:27:28 -0700145}
146
Jamie Madill62d31cb2015-09-11 13:25:51 -0400147template <typename VarT>
148void GetUniformBlockInfo(const std::vector<VarT> &fields,
149 const std::string &prefix,
150 sh::BlockLayoutEncoder *encoder,
151 bool inRowMajorLayout,
152 std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
153{
154 for (const VarT &field : fields)
155 {
156 const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
157
158 if (field.isStruct())
159 {
160 bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
161
162 for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
163 {
164 encoder->enterAggregateType();
165
166 const std::string uniformElementName =
167 fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
168 GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
169 blockInfoOut);
170
171 encoder->exitAggregateType();
172 }
173 }
174 else
175 {
176 bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
177 (*blockInfoOut)[fieldName] =
178 encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
179 }
180 }
181}
182
Jamie Madill334d6152015-10-22 14:00:28 -0400183template <typename T>
184bool TransposeMatrix(T *target,
185 const GLfloat *value,
186 int targetWidth,
187 int targetHeight,
188 int srcWidth,
189 int srcHeight)
190{
191 bool dirty = false;
192 int copyWidth = std::min(targetHeight, srcWidth);
193 int copyHeight = std::min(targetWidth, srcHeight);
194
195 for (int x = 0; x < copyWidth; x++)
196 {
197 for (int y = 0; y < copyHeight; y++)
198 {
199 SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]),
200 &dirty);
201 }
202 }
203 // clear unfilled right side
204 for (int y = 0; y < copyWidth; y++)
205 {
206 for (int x = copyHeight; x < targetWidth; x++)
207 {
208 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
209 }
210 }
211 // clear unfilled bottom.
212 for (int y = copyWidth; y < targetHeight; y++)
213 {
214 for (int x = 0; x < targetWidth; x++)
215 {
216 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
217 }
218 }
219
220 return dirty;
221}
222
223template <typename T>
224bool ExpandMatrix(T *target,
225 const GLfloat *value,
226 int targetWidth,
227 int targetHeight,
228 int srcWidth,
229 int srcHeight)
230{
231 bool dirty = false;
232 int copyWidth = std::min(targetWidth, srcWidth);
233 int copyHeight = std::min(targetHeight, srcHeight);
234
235 for (int y = 0; y < copyHeight; y++)
236 {
237 for (int x = 0; x < copyWidth; x++)
238 {
239 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]),
240 &dirty);
241 }
242 }
243 // clear unfilled right side
244 for (int y = 0; y < copyHeight; y++)
245 {
246 for (int x = copyWidth; x < targetWidth; x++)
247 {
248 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
249 }
250 }
251 // clear unfilled bottom.
252 for (int y = copyHeight; y < targetHeight; y++)
253 {
254 for (int x = 0; x < targetWidth; x++)
255 {
256 SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
257 }
258 }
259
260 return dirty;
261}
262
Jamie Madillada9ecc2015-08-17 12:53:37 -0400263} // anonymous namespace
264
Jamie Madill62d31cb2015-09-11 13:25:51 -0400265D3DUniform::D3DUniform(GLenum typeIn,
266 const std::string &nameIn,
267 unsigned int arraySizeIn,
268 bool defaultBlock)
269 : type(typeIn),
270 name(nameIn),
271 arraySize(arraySizeIn),
272 data(nullptr),
273 dirty(true),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400274 vsRegisterIndex(GL_INVALID_INDEX),
Geoff Lang98c56da2015-09-15 15:45:34 -0400275 psRegisterIndex(GL_INVALID_INDEX),
Jamie Madill62d31cb2015-09-11 13:25:51 -0400276 registerCount(0),
277 registerElement(0)
278{
279 // We use data storage for default block uniforms to cache values that are sent to D3D during
280 // rendering
281 // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
282 if (defaultBlock)
283 {
284 size_t bytes = gl::VariableInternalSize(type) * elementCount();
285 data = new uint8_t[bytes];
286 memset(data, 0, bytes);
287
288 // TODO(jmadill): is this correct with non-square matrices?
289 registerCount = gl::VariableRowCount(type) * elementCount();
290 }
291}
292
293D3DUniform::~D3DUniform()
294{
295 SafeDeleteArray(data);
296}
297
298bool D3DUniform::isSampler() const
299{
300 return gl::IsSamplerType(type);
301}
302
303bool D3DUniform::isReferencedByVertexShader() const
304{
305 return vsRegisterIndex != GL_INVALID_INDEX;
306}
307
308bool D3DUniform::isReferencedByFragmentShader() const
309{
310 return psRegisterIndex != GL_INVALID_INDEX;
311}
312
Jamie Madilld3dfda22015-07-06 08:28:49 -0400313ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
314 const Signature &signature,
Geoff Lang359ef262015-01-05 14:42:29 -0500315 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400316 : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700317{
Brandon Joneseb994362014-09-24 10:27:28 -0700318}
319
320ProgramD3D::VertexExecutable::~VertexExecutable()
321{
322 SafeDelete(mShaderExecutable);
323}
324
Jamie Madilld3dfda22015-07-06 08:28:49 -0400325// static
326void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
327 const gl::InputLayout &inputLayout,
328 Signature *signatureOut)
Brandon Joneseb994362014-09-24 10:27:28 -0700329{
Jamie Madillbd136f92015-08-10 14:51:37 -0400330 signatureOut->resize(inputLayout.size());
Jamie Madilld3dfda22015-07-06 08:28:49 -0400331
332 for (size_t index = 0; index < inputLayout.size(); ++index)
Brandon Joneseb994362014-09-24 10:27:28 -0700333 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400334 gl::VertexFormatType vertexFormatType = inputLayout[index];
Jamie Madillbd136f92015-08-10 14:51:37 -0400335 bool converted = false;
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400336 if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
Brandon Joneseb994362014-09-24 10:27:28 -0700337 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400338 VertexConversionType conversionType =
339 renderer->getVertexConversionType(vertexFormatType);
Jamie Madillbd136f92015-08-10 14:51:37 -0400340 converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
Brandon Joneseb994362014-09-24 10:27:28 -0700341 }
Jamie Madillbd136f92015-08-10 14:51:37 -0400342
343 (*signatureOut)[index] = converted;
Brandon Joneseb994362014-09-24 10:27:28 -0700344 }
Brandon Joneseb994362014-09-24 10:27:28 -0700345}
346
Jamie Madilld3dfda22015-07-06 08:28:49 -0400347bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
348{
Jamie Madillbd136f92015-08-10 14:51:37 -0400349 size_t limit = std::max(mSignature.size(), signature.size());
350 for (size_t index = 0; index < limit; ++index)
351 {
352 // treat undefined indexes as 'not converted'
353 bool a = index < signature.size() ? signature[index] : false;
354 bool b = index < mSignature.size() ? mSignature[index] : false;
355 if (a != b)
356 return false;
357 }
358
359 return true;
Jamie Madilld3dfda22015-07-06 08:28:49 -0400360}
361
362ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
363 ShaderExecutableD3D *shaderExecutable)
Jamie Madill334d6152015-10-22 14:00:28 -0400364 : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -0700365{
366}
367
368ProgramD3D::PixelExecutable::~PixelExecutable()
369{
370 SafeDelete(mShaderExecutable);
371}
372
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700373ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
374{
375}
376
Geoff Lang7dd2e102014-11-10 15:19:26 -0500377unsigned int ProgramD3D::mCurrentSerial = 1;
378
Jamie Madill5c6b7bf2015-08-17 12:53:35 -0400379ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
380 : ProgramImpl(data),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700381 mRenderer(renderer),
382 mDynamicHLSL(NULL),
Brandon Joneseb994362014-09-24 10:27:28 -0700383 mGeometryExecutable(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700384 mUsesPointSize(false),
Brandon Jonesc9610c52014-08-25 17:02:59 -0700385 mVertexUniformStorage(NULL),
Brandon Jones44151a92014-09-10 11:32:25 -0700386 mFragmentUniformStorage(NULL),
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700387 mUsedVertexSamplerRange(0),
388 mUsedPixelSamplerRange(0),
389 mDirtySamplerMapping(true),
Geoff Lang7dd2e102014-11-10 15:19:26 -0500390 mSerial(issueSerial())
Brandon Jonesc9610c52014-08-25 17:02:59 -0700391{
Brandon Joneseb994362014-09-24 10:27:28 -0700392 mDynamicHLSL = new DynamicHLSL(renderer);
Brandon Jonesc9610c52014-08-25 17:02:59 -0700393}
394
395ProgramD3D::~ProgramD3D()
396{
397 reset();
398 SafeDelete(mDynamicHLSL);
399}
400
Brandon Jones44151a92014-09-10 11:32:25 -0700401bool ProgramD3D::usesPointSpriteEmulation() const
402{
403 return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
404}
405
406bool ProgramD3D::usesGeometryShader() const
407{
Cooper Partine6664f02015-01-09 16:22:24 -0800408 return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
409}
410
411bool ProgramD3D::usesInstancedPointSpriteEmulation() const
412{
413 return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
Brandon Jones44151a92014-09-10 11:32:25 -0700414}
415
Jamie Madill334d6152015-10-22 14:00:28 -0400416GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
417 unsigned int samplerIndex,
418 const gl::Caps &caps) const
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700419{
420 GLint logicalTextureUnit = -1;
421
422 switch (type)
423 {
Jamie Madill334d6152015-10-22 14:00:28 -0400424 case gl::SAMPLER_PIXEL:
425 ASSERT(samplerIndex < caps.maxTextureImageUnits);
426 if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
427 {
428 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
429 }
430 break;
431 case gl::SAMPLER_VERTEX:
432 ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
433 if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
434 {
435 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
436 }
437 break;
438 default:
439 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700440 }
441
Jamie Madill334d6152015-10-22 14:00:28 -0400442 if (logicalTextureUnit >= 0 &&
443 logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700444 {
445 return logicalTextureUnit;
446 }
447
448 return -1;
449}
450
451// Returns the texture type for a given Direct3D 9 sampler type and
452// index (0-15 for the pixel shader and 0-3 for the vertex shader).
453GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
454{
455 switch (type)
456 {
Jamie Madill334d6152015-10-22 14:00:28 -0400457 case gl::SAMPLER_PIXEL:
458 ASSERT(samplerIndex < mSamplersPS.size());
459 ASSERT(mSamplersPS[samplerIndex].active);
460 return mSamplersPS[samplerIndex].textureType;
461 case gl::SAMPLER_VERTEX:
462 ASSERT(samplerIndex < mSamplersVS.size());
463 ASSERT(mSamplersVS[samplerIndex].active);
464 return mSamplersVS[samplerIndex].textureType;
465 default:
466 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700467 }
468
469 return GL_TEXTURE_2D;
470}
471
472GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
473{
474 switch (type)
475 {
Jamie Madill334d6152015-10-22 14:00:28 -0400476 case gl::SAMPLER_PIXEL:
477 return mUsedPixelSamplerRange;
478 case gl::SAMPLER_VERTEX:
479 return mUsedVertexSamplerRange;
480 default:
481 UNREACHABLE();
482 return 0;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700483 }
484}
485
486void ProgramD3D::updateSamplerMapping()
487{
488 if (!mDirtySamplerMapping)
489 {
490 return;
491 }
492
493 mDirtySamplerMapping = false;
494
495 // Retrieve sampler uniform values
Jamie Madill62d31cb2015-09-11 13:25:51 -0400496 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700497 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400498 if (!d3dUniform->dirty)
499 continue;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700500
Jamie Madill62d31cb2015-09-11 13:25:51 -0400501 if (!d3dUniform->isSampler())
502 continue;
503
504 int count = d3dUniform->elementCount();
505 const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
506
507 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700508 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400509 unsigned int firstIndex = d3dUniform->psRegisterIndex;
510
511 for (int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700512 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400513 unsigned int samplerIndex = firstIndex + i;
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700514
Jamie Madill62d31cb2015-09-11 13:25:51 -0400515 if (samplerIndex < mSamplersPS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700516 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400517 ASSERT(mSamplersPS[samplerIndex].active);
518 mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700519 }
Jamie Madill62d31cb2015-09-11 13:25:51 -0400520 }
521 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700522
Jamie Madill62d31cb2015-09-11 13:25:51 -0400523 if (d3dUniform->isReferencedByVertexShader())
524 {
525 unsigned int firstIndex = d3dUniform->vsRegisterIndex;
526
527 for (int i = 0; i < count; i++)
528 {
529 unsigned int samplerIndex = firstIndex + i;
530
531 if (samplerIndex < mSamplersVS.size())
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700532 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400533 ASSERT(mSamplersVS[samplerIndex].active);
534 mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700535 }
536 }
537 }
538 }
539}
540
Geoff Lang7dd2e102014-11-10 15:19:26 -0500541LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700542{
Jamie Madill62d31cb2015-09-11 13:25:51 -0400543 reset();
544
Jamie Madill334d6152015-10-22 14:00:28 -0400545 DeviceIdentifier binaryDeviceIdentifier = {0};
546 stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
547 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700548
549 DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
550 if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
551 {
552 infoLog << "Invalid program binary, device configuration has changed.";
553 return LinkResult(false, gl::Error(GL_NO_ERROR));
554 }
555
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500556 int compileFlags = stream->readInt<int>();
557 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
558 {
Jamie Madillf6113162015-05-07 11:49:21 -0400559 infoLog << "Mismatched compilation flags.";
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500560 return LinkResult(false, gl::Error(GL_NO_ERROR));
561 }
562
Jamie Madill63805b42015-08-25 13:17:39 -0400563 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
564 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
565 {
566 stream->readInt(&mSemanticIndexes[i]);
567 }
568
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700569 const unsigned int psSamplerCount = stream->readInt<unsigned int>();
570 for (unsigned int i = 0; i < psSamplerCount; ++i)
571 {
572 Sampler sampler;
573 stream->readBool(&sampler.active);
574 stream->readInt(&sampler.logicalTextureUnit);
575 stream->readInt(&sampler.textureType);
576 mSamplersPS.push_back(sampler);
577 }
578 const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
579 for (unsigned int i = 0; i < vsSamplerCount; ++i)
580 {
581 Sampler sampler;
582 stream->readBool(&sampler.active);
583 stream->readInt(&sampler.logicalTextureUnit);
584 stream->readInt(&sampler.textureType);
585 mSamplersVS.push_back(sampler);
586 }
587
588 stream->readInt(&mUsedVertexSamplerRange);
589 stream->readInt(&mUsedPixelSamplerRange);
590
591 const unsigned int uniformCount = stream->readInt<unsigned int>();
592 if (stream->error())
593 {
Jamie Madillf6113162015-05-07 11:49:21 -0400594 infoLog << "Invalid program binary.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500595 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700596 }
597
Jamie Madill62d31cb2015-09-11 13:25:51 -0400598 const auto &linkedUniforms = mData.getUniforms();
599 ASSERT(mD3DUniforms.empty());
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700600 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
601 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400602 const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700603
Jamie Madill62d31cb2015-09-11 13:25:51 -0400604 D3DUniform *d3dUniform =
605 new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
606 linkedUniform.isInDefaultBlock());
607 stream->readInt(&d3dUniform->psRegisterIndex);
608 stream->readInt(&d3dUniform->vsRegisterIndex);
609 stream->readInt(&d3dUniform->registerCount);
610 stream->readInt(&d3dUniform->registerElement);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700611
Jamie Madill62d31cb2015-09-11 13:25:51 -0400612 mD3DUniforms.push_back(d3dUniform);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700613 }
614
Jamie Madill4a3c2342015-10-08 12:58:45 -0400615 const unsigned int blockCount = stream->readInt<unsigned int>();
616 if (stream->error())
617 {
618 infoLog << "Invalid program binary.";
619 return LinkResult(false, gl::Error(GL_NO_ERROR));
620 }
621
622 ASSERT(mD3DUniformBlocks.empty());
623 for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
624 {
625 D3DUniformBlock uniformBlock;
626 stream->readInt(&uniformBlock.psRegisterIndex);
627 stream->readInt(&uniformBlock.vsRegisterIndex);
628 mD3DUniformBlocks.push_back(uniformBlock);
629 }
630
Brandon Joneseb994362014-09-24 10:27:28 -0700631 const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
632 mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
Jamie Madill334d6152015-10-22 14:00:28 -0400633 for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount;
634 varyingIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700635 {
636 gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
637
638 stream->readString(&varying.name);
639 stream->readInt(&varying.type);
640 stream->readInt(&varying.size);
641 stream->readString(&varying.semanticName);
642 stream->readInt(&varying.semanticIndex);
643 stream->readInt(&varying.semanticIndexCount);
644 }
645
Brandon Jones22502d52014-08-29 16:58:36 -0700646 stream->readString(&mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400647 stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
648 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700649 stream->readString(&mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400650 stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
651 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700652 stream->readBool(&mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700653 stream->readBool(&mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700654
655 const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
656 mPixelShaderKey.resize(pixelShaderKeySize);
Jamie Madill334d6152015-10-22 14:00:28 -0400657 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
658 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700659 {
660 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
661 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
662 stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
663 stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
664 }
665
Jamie Madill334d6152015-10-22 14:00:28 -0400666 const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
Brandon Joneseb994362014-09-24 10:27:28 -0700667
668 const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
Jamie Madill334d6152015-10-22 14:00:28 -0400669 for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
670 vertexShaderIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700671 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400672 size_t inputLayoutSize = stream->readInt<size_t>();
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400673 gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
Brandon Joneseb994362014-09-24 10:27:28 -0700674
Jamie Madilld3dfda22015-07-06 08:28:49 -0400675 for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700676 {
Jamie Madillf8dd7b12015-08-05 13:50:08 -0400677 inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
Brandon Joneseb994362014-09-24 10:27:28 -0700678 }
679
Jamie Madill334d6152015-10-22 14:00:28 -0400680 unsigned int vertexShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700681 const unsigned char *vertexShaderFunction = binary + stream->offset();
Geoff Langb543aff2014-09-30 14:52:54 -0400682
Jamie Madillada9ecc2015-08-17 12:53:37 -0400683 ShaderExecutableD3D *shaderExecutable = nullptr;
684
685 gl::Error error = mRenderer->loadExecutable(
686 vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
687 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400688 if (error.isError())
689 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500690 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400691 }
692
Brandon Joneseb994362014-09-24 10:27:28 -0700693 if (!shaderExecutable)
694 {
Jamie Madillf6113162015-05-07 11:49:21 -0400695 infoLog << "Could not create vertex shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500696 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700697 }
698
699 // generated converted input layout
Jamie Madilld3dfda22015-07-06 08:28:49 -0400700 VertexExecutable::Signature signature;
701 VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
Brandon Joneseb994362014-09-24 10:27:28 -0700702
703 // add new binary
Jamie Madill334d6152015-10-22 14:00:28 -0400704 mVertexExecutables.push_back(
705 new VertexExecutable(inputLayout, signature, shaderExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -0700706
707 stream->skip(vertexShaderSize);
708 }
709
710 const size_t pixelShaderCount = stream->readInt<unsigned int>();
711 for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
712 {
713 const size_t outputCount = stream->readInt<unsigned int>();
714 std::vector<GLenum> outputs(outputCount);
715 for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
716 {
717 stream->readInt(&outputs[outputIndex]);
718 }
719
Jamie Madill334d6152015-10-22 14:00:28 -0400720 const size_t pixelShaderSize = stream->readInt<unsigned int>();
Brandon Joneseb994362014-09-24 10:27:28 -0700721 const unsigned char *pixelShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400722 ShaderExecutableD3D *shaderExecutable = nullptr;
723
724 gl::Error error = mRenderer->loadExecutable(
725 pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
726 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400727 if (error.isError())
728 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500729 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400730 }
Brandon Joneseb994362014-09-24 10:27:28 -0700731
732 if (!shaderExecutable)
733 {
Jamie Madillf6113162015-05-07 11:49:21 -0400734 infoLog << "Could not create pixel shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500735 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700736 }
737
738 // add new binary
739 mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
740
741 stream->skip(pixelShaderSize);
742 }
743
744 unsigned int geometryShaderSize = stream->readInt<unsigned int>();
745
746 if (geometryShaderSize > 0)
747 {
748 const unsigned char *geometryShaderFunction = binary + stream->offset();
Jamie Madillada9ecc2015-08-17 12:53:37 -0400749 gl::Error error = mRenderer->loadExecutable(
750 geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
751 mTransformFeedbackLinkedVaryings,
752 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400753 if (error.isError())
754 {
Geoff Lang7dd2e102014-11-10 15:19:26 -0500755 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -0400756 }
Brandon Joneseb994362014-09-24 10:27:28 -0700757
758 if (!mGeometryExecutable)
759 {
Jamie Madillf6113162015-05-07 11:49:21 -0400760 infoLog << "Could not create geometry shader.";
Geoff Lang7dd2e102014-11-10 15:19:26 -0500761 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Joneseb994362014-09-24 10:27:28 -0700762 }
763 stream->skip(geometryShaderSize);
764 }
765
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700766 initializeUniformStorage();
Jamie Madill437d2662014-12-05 14:23:35 -0500767 initAttributesByLayout();
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700768
Geoff Lang7dd2e102014-11-10 15:19:26 -0500769 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -0700770}
771
Geoff Langb543aff2014-09-30 14:52:54 -0400772gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
Brandon Jones22502d52014-08-29 16:58:36 -0700773{
Austin Kinross137b1512015-06-17 16:14:53 -0700774 // Output the DeviceIdentifier before we output any shader code
Jamie Madill334d6152015-10-22 14:00:28 -0400775 // When we load the binary again later, we can validate the device identifier before trying to
776 // compile any HLSL
Austin Kinross137b1512015-06-17 16:14:53 -0700777 DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
Jamie Madill334d6152015-10-22 14:00:28 -0400778 stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
779 sizeof(DeviceIdentifier));
Austin Kinross137b1512015-06-17 16:14:53 -0700780
Jamie Madill2db1fbb2014-12-03 10:58:55 -0500781 stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
782
Jamie Madill63805b42015-08-25 13:17:39 -0400783 // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
784 for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
785 {
786 stream->writeInt(mSemanticIndexes[i]);
787 }
788
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700789 stream->writeInt(mSamplersPS.size());
790 for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
791 {
792 stream->writeInt(mSamplersPS[i].active);
793 stream->writeInt(mSamplersPS[i].logicalTextureUnit);
794 stream->writeInt(mSamplersPS[i].textureType);
795 }
796
797 stream->writeInt(mSamplersVS.size());
798 for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
799 {
800 stream->writeInt(mSamplersVS[i].active);
801 stream->writeInt(mSamplersVS[i].logicalTextureUnit);
802 stream->writeInt(mSamplersVS[i].textureType);
803 }
804
805 stream->writeInt(mUsedVertexSamplerRange);
806 stream->writeInt(mUsedPixelSamplerRange);
807
Jamie Madill62d31cb2015-09-11 13:25:51 -0400808 stream->writeInt(mD3DUniforms.size());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400809 for (const D3DUniform *uniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700810 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400811 // Type, name and arraySize are redundant, so aren't stored in the binary.
Jamie Madill4a3c2342015-10-08 12:58:45 -0400812 stream->writeInt(uniform->psRegisterIndex);
813 stream->writeInt(uniform->vsRegisterIndex);
814 stream->writeInt(uniform->registerCount);
815 stream->writeInt(uniform->registerElement);
816 }
817
818 stream->writeInt(mD3DUniformBlocks.size());
819 for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
820 {
821 stream->writeInt(uniformBlock.psRegisterIndex);
822 stream->writeInt(uniformBlock.vsRegisterIndex);
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700823 }
824
Brandon Joneseb994362014-09-24 10:27:28 -0700825 stream->writeInt(mTransformFeedbackLinkedVaryings.size());
826 for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
827 {
828 const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
829
830 stream->writeString(varying.name);
831 stream->writeInt(varying.type);
832 stream->writeInt(varying.size);
833 stream->writeString(varying.semanticName);
834 stream->writeInt(varying.semanticIndex);
835 stream->writeInt(varying.semanticIndexCount);
836 }
837
Brandon Jones22502d52014-08-29 16:58:36 -0700838 stream->writeString(mVertexHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400839 stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
840 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700841 stream->writeString(mPixelHLSL);
Jamie Madill334d6152015-10-22 14:00:28 -0400842 stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
843 sizeof(D3DCompilerWorkarounds));
Brandon Jones22502d52014-08-29 16:58:36 -0700844 stream->writeInt(mUsesFragDepth);
Brandon Jones44151a92014-09-10 11:32:25 -0700845 stream->writeInt(mUsesPointSize);
Brandon Jones22502d52014-08-29 16:58:36 -0700846
Brandon Joneseb994362014-09-24 10:27:28 -0700847 const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
Brandon Jones22502d52014-08-29 16:58:36 -0700848 stream->writeInt(pixelShaderKey.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400849 for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
850 pixelShaderKeyIndex++)
Brandon Jones22502d52014-08-29 16:58:36 -0700851 {
Brandon Joneseb994362014-09-24 10:27:28 -0700852 const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
Brandon Jones22502d52014-08-29 16:58:36 -0700853 stream->writeInt(variable.type);
854 stream->writeString(variable.name);
855 stream->writeString(variable.source);
856 stream->writeInt(variable.outputIndex);
857 }
858
Brandon Joneseb994362014-09-24 10:27:28 -0700859 stream->writeInt(mVertexExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400860 for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
861 vertexExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700862 {
863 VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
864
Jamie Madilld3dfda22015-07-06 08:28:49 -0400865 const auto &inputLayout = vertexExecutable->inputs();
866 stream->writeInt(inputLayout.size());
867
868 for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700869 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400870 stream->writeInt(inputLayout[inputIndex]);
Brandon Joneseb994362014-09-24 10:27:28 -0700871 }
872
873 size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
874 stream->writeInt(vertexShaderSize);
875
876 const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
877 stream->writeBytes(vertexBlob, vertexShaderSize);
878 }
879
880 stream->writeInt(mPixelExecutables.size());
Jamie Madill334d6152015-10-22 14:00:28 -0400881 for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
882 pixelExecutableIndex++)
Brandon Joneseb994362014-09-24 10:27:28 -0700883 {
884 PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
885
886 const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
887 stream->writeInt(outputs.size());
888 for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
889 {
890 stream->writeInt(outputs[outputIndex]);
891 }
892
893 size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
894 stream->writeInt(pixelShaderSize);
895
896 const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
897 stream->writeBytes(pixelBlob, pixelShaderSize);
898 }
899
Jamie Madill334d6152015-10-22 14:00:28 -0400900 size_t geometryShaderSize =
901 (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
Brandon Joneseb994362014-09-24 10:27:28 -0700902 stream->writeInt(geometryShaderSize);
903
904 if (mGeometryExecutable != NULL && geometryShaderSize > 0)
905 {
906 const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
907 stream->writeBytes(geometryBlob, geometryShaderSize);
908 }
909
Geoff Langb543aff2014-09-30 14:52:54 -0400910 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700911}
912
Jamie Madill334d6152015-10-22 14:00:28 -0400913gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
914 ShaderExecutableD3D **outExecutable)
Brandon Jones22502d52014-08-29 16:58:36 -0700915{
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400916 mPixelShaderOutputFormatCache.clear();
Brandon Joneseb994362014-09-24 10:27:28 -0700917
Jamie Madill85a18042015-03-05 15:41:41 -0500918 const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
Jamie Madill334d6152015-10-22 14:00:28 -0400919 const gl::AttachmentList &colorbuffers =
920 fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
Brandon Joneseb994362014-09-24 10:27:28 -0700921
922 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
923 {
924 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
925
926 if (colorbuffer)
927 {
Jamie Madill334d6152015-10-22 14:00:28 -0400928 mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
929 ? GL_COLOR_ATTACHMENT0
930 : colorbuffer->getBinding());
Brandon Joneseb994362014-09-24 10:27:28 -0700931 }
932 else
933 {
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400934 mPixelShaderOutputFormatCache.push_back(GL_NONE);
Brandon Joneseb994362014-09-24 10:27:28 -0700935 }
936 }
937
Geoff Lang7a26a1a2015-03-25 12:29:06 -0400938 return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
Brandon Joneseb994362014-09-24 10:27:28 -0700939}
940
Jamie Madill97399232014-12-23 12:31:15 -0500941gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
Geoff Lang359ef262015-01-05 14:42:29 -0500942 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -0500943 gl::InfoLog *infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700944{
945 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
946 {
947 if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
948 {
Geoff Langb543aff2014-09-30 14:52:54 -0400949 *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
950 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700951 }
952 }
953
Jamie Madill334d6152015-10-22 14:00:28 -0400954 std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
955 mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
Brandon Jones22502d52014-08-29 16:58:36 -0700956
957 // Generate new pixel executable
Geoff Lang359ef262015-01-05 14:42:29 -0500958 ShaderExecutableD3D *pixelExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -0500959
960 gl::InfoLog tempInfoLog;
961 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
962
Jamie Madillada9ecc2015-08-17 12:53:37 -0400963 gl::Error error = mRenderer->compileToExecutable(
964 *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
965 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
966 &pixelExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -0400967 if (error.isError())
968 {
969 return error;
970 }
Brandon Joneseb994362014-09-24 10:27:28 -0700971
Jamie Madill97399232014-12-23 12:31:15 -0500972 if (pixelExecutable)
973 {
974 mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
975 }
976 else if (!infoLog)
Brandon Joneseb994362014-09-24 10:27:28 -0700977 {
978 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700979 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Brandon Joneseb994362014-09-24 10:27:28 -0700980 ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
981 }
Brandon Jones22502d52014-08-29 16:58:36 -0700982
Geoff Langb543aff2014-09-30 14:52:54 -0400983 *outExectuable = pixelExecutable;
984 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -0700985}
986
Jamie Madilld3dfda22015-07-06 08:28:49 -0400987gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
Geoff Lang359ef262015-01-05 14:42:29 -0500988 ShaderExecutableD3D **outExectuable,
Jamie Madill97399232014-12-23 12:31:15 -0500989 gl::InfoLog *infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -0700990{
Jamie Madilld3dfda22015-07-06 08:28:49 -0400991 VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
Brandon Joneseb994362014-09-24 10:27:28 -0700992
993 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
994 {
Jamie Madilld3dfda22015-07-06 08:28:49 -0400995 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
Brandon Joneseb994362014-09-24 10:27:28 -0700996 {
Geoff Langb543aff2014-09-30 14:52:54 -0400997 *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
998 return gl::Error(GL_NO_ERROR);
Brandon Joneseb994362014-09-24 10:27:28 -0700999 }
1000 }
1001
Brandon Jones22502d52014-08-29 16:58:36 -07001002 // Generate new dynamic layout with attribute conversions
Jamie Madillc349ec02015-08-21 16:53:12 -04001003 std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1004 mVertexHLSL, inputLayout, mData.getAttributes());
Brandon Jones22502d52014-08-29 16:58:36 -07001005
1006 // Generate new vertex executable
Geoff Lang359ef262015-01-05 14:42:29 -05001007 ShaderExecutableD3D *vertexExecutable = NULL;
Jamie Madill97399232014-12-23 12:31:15 -05001008
1009 gl::InfoLog tempInfoLog;
1010 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1011
Jamie Madillada9ecc2015-08-17 12:53:37 -04001012 gl::Error error = mRenderer->compileToExecutable(
1013 *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings,
1014 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
1015 &vertexExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001016 if (error.isError())
1017 {
1018 return error;
1019 }
1020
Jamie Madill97399232014-12-23 12:31:15 -05001021 if (vertexExecutable)
Brandon Joneseb994362014-09-24 10:27:28 -07001022 {
Jamie Madill334d6152015-10-22 14:00:28 -04001023 mVertexExecutables.push_back(
1024 new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
Brandon Joneseb994362014-09-24 10:27:28 -07001025 }
Jamie Madill97399232014-12-23 12:31:15 -05001026 else if (!infoLog)
1027 {
1028 std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001029 tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
Jamie Madill97399232014-12-23 12:31:15 -05001030 ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
1031 }
Brandon Jones22502d52014-08-29 16:58:36 -07001032
Geoff Langb543aff2014-09-30 14:52:54 -04001033 *outExectuable = vertexExecutable;
1034 return gl::Error(GL_NO_ERROR);
Brandon Jones22502d52014-08-29 16:58:36 -07001035}
1036
Jamie Madill334d6152015-10-22 14:00:28 -04001037LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data,
1038 gl::InfoLog &infoLog,
Jamie Madillca03b352015-09-02 12:38:13 -04001039 int registers,
1040 const std::vector<PackedVarying> &packedVaryings)
Brandon Jones44151a92014-09-10 11:32:25 -07001041{
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001042 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Brandon Jones44151a92014-09-10 11:32:25 -07001043
Jamie Madill5c6b7bf2015-08-17 12:53:35 -04001044 const gl::InputLayout &defaultInputLayout =
1045 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +00001046 ShaderExecutableD3D *defaultVertexExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001047 gl::Error error =
1048 getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
Jamie Madille4ea2022015-03-26 20:35:05 +00001049 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -08001050 {
Jamie Madille4ea2022015-03-26 20:35:05 +00001051 return LinkResult(false, error);
1052 }
Austin Kinross434953e2015-02-20 10:49:51 -08001053
Jamie Madill334d6152015-10-22 14:00:28 -04001054 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -05001055 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001056 error =
1057 getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -04001058 if (error.isError())
1059 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001060 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001061 }
Brandon Jones44151a92014-09-10 11:32:25 -07001062
Brandon Joneseb994362014-09-24 10:27:28 -07001063 if (usesGeometryShader())
1064 {
Jamie Madill334d6152015-10-22 14:00:28 -04001065 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
1066 data, registers, fragmentShaderD3D, packedVaryings);
Brandon Jones44151a92014-09-10 11:32:25 -07001067
Jamie Madillada9ecc2015-08-17 12:53:37 -04001068 error = mRenderer->compileToExecutable(
1069 infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
1070 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1071 D3DCompilerWorkarounds(), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001072 if (error.isError())
1073 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001074 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001075 }
Brandon Joneseb994362014-09-24 10:27:28 -07001076 }
1077
Brandon Jones091540d2014-10-29 11:32:04 -07001078#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Jamie Madillca03b352015-09-02 12:38:13 -04001079 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1080
Tibor den Ouden97049c62014-10-06 21:39:16 +02001081 if (usesGeometryShader() && mGeometryExecutable)
1082 {
Jamie Madill334d6152015-10-22 14:00:28 -04001083 // Geometry shaders are currently only used internally, so there is no corresponding shader
1084 // object at the interface level. For now the geometry shader debug info is prepended to
1085 // the vertex shader.
Tibor den Ouden97049c62014-10-06 21:39:16 +02001086 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1087 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
1088 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1089 }
1090
1091 if (defaultVertexExecutable)
1092 {
1093 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1094 }
1095
1096 if (defaultPixelExecutable)
1097 {
1098 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1099 }
1100#endif
1101
Jamie Madill334d6152015-10-22 14:00:28 -04001102 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable &&
1103 (!usesGeometryShader() || mGeometryExecutable));
Geoff Lang7dd2e102014-11-10 15:19:26 -05001104 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -07001105}
1106
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001107LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001108{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001109 reset();
1110
1111 // TODO(jmadill): structures containing samplers
1112 for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
1113 {
1114 if (linkedUniform.isSampler() && linkedUniform.isField())
1115 {
1116 infoLog << "Structures containing samplers not currently supported in D3D.";
1117 return LinkResult(false, gl::Error(GL_NO_ERROR));
1118 }
1119 }
1120
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001121 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1122 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Brandon Joneseb994362014-09-24 10:27:28 -07001123
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001124 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1125 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1126
Jamie Madill63069df2015-09-01 17:26:41 +00001127 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001128 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Brandon Jones22502d52014-08-29 16:58:36 -07001129
Arun Patole44efa0b2015-03-04 17:11:05 +05301130 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001131 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1132
Austin Kinross02df7962015-07-01 10:03:42 -07001133 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1134 {
1135 if (fragmentShaderD3D->usesFrontFacing())
1136 {
1137 infoLog << "The current renderer doesn't support gl_FrontFacing";
1138 return LinkResult(false, gl::Error(GL_NO_ERROR));
1139 }
1140 }
1141
Jamie Madillca03b352015-09-02 12:38:13 -04001142 std::vector<PackedVarying> packedVaryings =
1143 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1144
Brandon Jones22502d52014-08-29 16:58:36 -07001145 // Map the varyings to the register file
Jamie Madill334d6152015-10-22 14:00:28 -04001146 int registers = mDynamicHLSL->packVaryings(*data.caps, infoLog, &packedVaryings,
Jamie Madill31c8c562015-08-19 14:08:03 -04001147 mData.getTransformFeedbackVaryingNames());
Brandon Jones22502d52014-08-29 16:58:36 -07001148
Jamie Madill31c8c562015-08-19 14:08:03 -04001149 if (registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -07001150 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001151 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001152 }
1153
Jamie Madillccdf74b2015-08-18 10:46:12 -04001154 std::vector<gl::LinkedVarying> linkedVaryings;
Jamie Madill334d6152015-10-22 14:00:28 -04001155 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, &mPixelHLSL,
1156 &mVertexHLSL, packedVaryings, &linkedVaryings,
Jamie Madillca03b352015-09-02 12:38:13 -04001157 &mPixelShaderKey, &mUsesFragDepth))
Brandon Jones22502d52014-08-29 16:58:36 -07001158 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001159 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001160 }
1161
Brandon Jones44151a92014-09-10 11:32:25 -07001162 mUsesPointSize = vertexShaderD3D->usesPointSize();
1163
Jamie Madill63805b42015-08-25 13:17:39 -04001164 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001165
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001166 defineUniformsAndAssignRegisters();
Jamie Madille473dee2015-08-18 14:49:01 -04001167
Jamie Madillccdf74b2015-08-18 10:46:12 -04001168 gatherTransformFeedbackVaryings(linkedVaryings);
1169
Jamie Madill334d6152015-10-22 14:00:28 -04001170 LinkResult result = compileProgramExecutables(data, infoLog, registers, packedVaryings);
Jamie Madill31c8c562015-08-19 14:08:03 -04001171 if (result.error.isError() || !result.linkSuccess)
1172 {
1173 infoLog << "Failed to create D3D shaders.";
1174 return result;
1175 }
1176
Jamie Madill4a3c2342015-10-08 12:58:45 -04001177 initUniformBlockInfo();
1178
Geoff Lang7dd2e102014-11-10 15:19:26 -05001179 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001180}
1181
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001182GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001183{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001184 // TODO(jmadill): Do something useful here?
1185 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001186}
1187
Jamie Madill4a3c2342015-10-08 12:58:45 -04001188void ProgramD3D::initUniformBlockInfo()
Jamie Madill62d31cb2015-09-11 13:25:51 -04001189{
1190 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1191
Jamie Madill62d31cb2015-09-11 13:25:51 -04001192 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1193 {
1194 if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
1195 continue;
1196
Jamie Madill4a3c2342015-10-08 12:58:45 -04001197 if (mBlockDataSizes.count(vertexBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001198 continue;
1199
Jamie Madill4a3c2342015-10-08 12:58:45 -04001200 size_t dataSize = getUniformBlockInfo(vertexBlock);
1201 mBlockDataSizes[vertexBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001202 }
1203
1204 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1205
1206 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1207 {
1208 if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
1209 continue;
1210
Jamie Madill4a3c2342015-10-08 12:58:45 -04001211 if (mBlockDataSizes.count(fragmentBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001212 continue;
1213
Jamie Madill4a3c2342015-10-08 12:58:45 -04001214 size_t dataSize = getUniformBlockInfo(fragmentBlock);
1215 mBlockDataSizes[fragmentBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001216 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001217}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001218
Jamie Madill4a3c2342015-10-08 12:58:45 -04001219void ProgramD3D::assignUniformBlockRegisters()
1220{
1221 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001222
1223 // Assign registers and update sizes.
Jamie Madill4a3c2342015-10-08 12:58:45 -04001224 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1225 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Jamie Madill62d31cb2015-09-11 13:25:51 -04001226
Jamie Madill4a3c2342015-10-08 12:58:45 -04001227 for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001228 {
1229 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1230
Jamie Madill4a3c2342015-10-08 12:58:45 -04001231 D3DUniformBlock d3dUniformBlock;
1232
Jamie Madill62d31cb2015-09-11 13:25:51 -04001233 if (uniformBlock.vertexStaticUse)
1234 {
1235 unsigned int baseRegister =
1236 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001237 d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001238 }
1239
1240 if (uniformBlock.fragmentStaticUse)
1241 {
1242 unsigned int baseRegister =
1243 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001244 d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001245 }
1246
Jamie Madill4a3c2342015-10-08 12:58:45 -04001247 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001248 }
1249}
1250
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001251void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001252{
1253 // Compute total default block size
Jamie Madill334d6152015-10-22 14:00:28 -04001254 unsigned int vertexRegisters = 0;
Brandon Jonesc9610c52014-08-25 17:02:59 -07001255 unsigned int fragmentRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001256 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001257 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001258 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001259 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001260 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001261 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001262 vertexRegisters = std::max(vertexRegisters,
1263 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001264 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001265 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001266 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001267 fragmentRegisters = std::max(
1268 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001269 }
1270 }
1271 }
1272
Jamie Madill334d6152015-10-22 14:00:28 -04001273 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001274 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1275}
1276
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001277gl::Error ProgramD3D::applyUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001278{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001279 updateSamplerMapping();
1280
Jamie Madill62d31cb2015-09-11 13:25:51 -04001281 gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001282 if (error.isError())
1283 {
1284 return error;
1285 }
1286
Jamie Madill62d31cb2015-09-11 13:25:51 -04001287 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001288 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001289 d3dUniform->dirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001290 }
1291
1292 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001293}
1294
Jamie Madilld1fe1642015-08-21 16:26:04 -04001295gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001296{
Jamie Madill4a3c2342015-10-08 12:58:45 -04001297 if (mData.getUniformBlocks().empty())
1298 {
1299 return gl::Error(GL_NO_ERROR);
1300 }
1301
1302 // Lazy init.
1303 if (mD3DUniformBlocks.empty())
1304 {
1305 assignUniformBlockRegisters();
1306 }
1307
Jamie Madill03260fa2015-06-22 13:57:22 -04001308 mVertexUBOCache.clear();
1309 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001310
1311 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1312 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1313
Jamie Madill4a3c2342015-10-08 12:58:45 -04001314 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001315 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001316 {
Jamie Madill4a3c2342015-10-08 12:58:45 -04001317 const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
1318 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001319
Brandon Jones18bd4102014-09-22 14:21:44 -07001320 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill4a3c2342015-10-08 12:58:45 -04001321 if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001322 {
1323 continue;
1324 }
1325
Jamie Madill4a3c2342015-10-08 12:58:45 -04001326 if (uniformBlock.vertexStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001327 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001328 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001329 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001330
Jamie Madill969194d2015-07-20 14:36:56 -04001331 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001332 {
1333 mVertexUBOCache.resize(registerIndex + 1, -1);
1334 }
1335
1336 ASSERT(mVertexUBOCache[registerIndex] == -1);
1337 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001338 }
1339
Jamie Madill4a3c2342015-10-08 12:58:45 -04001340 if (uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001341 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001342 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001343 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001344
1345 if (mFragmentUBOCache.size() <= registerIndex)
1346 {
1347 mFragmentUBOCache.resize(registerIndex + 1, -1);
1348 }
1349
1350 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1351 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001352 }
1353 }
1354
Jamie Madill03260fa2015-06-22 13:57:22 -04001355 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001356}
1357
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001358void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001359{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001360 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001361 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001362 d3dUniform->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001363 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001364}
1365
Jamie Madill334d6152015-10-22 14:00:28 -04001366void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001367{
1368 setUniform(location, count, v, GL_FLOAT);
1369}
1370
1371void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1372{
1373 setUniform(location, count, v, GL_FLOAT_VEC2);
1374}
1375
1376void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1377{
1378 setUniform(location, count, v, GL_FLOAT_VEC3);
1379}
1380
1381void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1382{
1383 setUniform(location, count, v, GL_FLOAT_VEC4);
1384}
1385
Jamie Madill334d6152015-10-22 14:00:28 -04001386void ProgramD3D::setUniformMatrix2fv(GLint location,
1387 GLsizei count,
1388 GLboolean transpose,
1389 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001390{
1391 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1392}
1393
Jamie Madill334d6152015-10-22 14:00:28 -04001394void ProgramD3D::setUniformMatrix3fv(GLint location,
1395 GLsizei count,
1396 GLboolean transpose,
1397 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001398{
1399 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1400}
1401
Jamie Madill334d6152015-10-22 14:00:28 -04001402void ProgramD3D::setUniformMatrix4fv(GLint location,
1403 GLsizei count,
1404 GLboolean transpose,
1405 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001406{
1407 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1408}
1409
Jamie Madill334d6152015-10-22 14:00:28 -04001410void ProgramD3D::setUniformMatrix2x3fv(GLint location,
1411 GLsizei count,
1412 GLboolean transpose,
1413 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001414{
1415 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1416}
1417
Jamie Madill334d6152015-10-22 14:00:28 -04001418void ProgramD3D::setUniformMatrix3x2fv(GLint location,
1419 GLsizei count,
1420 GLboolean transpose,
1421 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001422{
1423 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1424}
1425
Jamie Madill334d6152015-10-22 14:00:28 -04001426void ProgramD3D::setUniformMatrix2x4fv(GLint location,
1427 GLsizei count,
1428 GLboolean transpose,
1429 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001430{
1431 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1432}
1433
Jamie Madill334d6152015-10-22 14:00:28 -04001434void ProgramD3D::setUniformMatrix4x2fv(GLint location,
1435 GLsizei count,
1436 GLboolean transpose,
1437 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001438{
1439 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1440}
1441
Jamie Madill334d6152015-10-22 14:00:28 -04001442void ProgramD3D::setUniformMatrix3x4fv(GLint location,
1443 GLsizei count,
1444 GLboolean transpose,
1445 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001446{
1447 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1448}
1449
Jamie Madill334d6152015-10-22 14:00:28 -04001450void ProgramD3D::setUniformMatrix4x3fv(GLint location,
1451 GLsizei count,
1452 GLboolean transpose,
1453 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001454{
1455 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1456}
1457
1458void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1459{
1460 setUniform(location, count, v, GL_INT);
1461}
1462
1463void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1464{
1465 setUniform(location, count, v, GL_INT_VEC2);
1466}
1467
1468void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1469{
1470 setUniform(location, count, v, GL_INT_VEC3);
1471}
1472
1473void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1474{
1475 setUniform(location, count, v, GL_INT_VEC4);
1476}
1477
1478void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1479{
1480 setUniform(location, count, v, GL_UNSIGNED_INT);
1481}
1482
1483void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1484{
1485 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1486}
1487
1488void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1489{
1490 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1491}
1492
1493void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1494{
1495 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1496}
1497
Jamie Madill4a3c2342015-10-08 12:58:45 -04001498void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
1499 GLuint /*uniformBlockBinding*/)
Geoff Lang5d124a62015-09-15 13:03:27 -04001500{
1501}
1502
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001503void ProgramD3D::defineUniformsAndAssignRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001504{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001505 D3DUniformMap uniformMap;
Jamie Madill334d6152015-10-22 14:00:28 -04001506 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001507 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001508
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001509 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001510 if (vertexUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001511 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001512 defineUniformBase(vertexShader, vertexUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001513 }
1514 }
1515
Jamie Madill334d6152015-10-22 14:00:28 -04001516 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001517 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001518 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001519 if (fragmentUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001520 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001521 defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001522 }
1523 }
1524
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001525 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
1526 for (const gl::LinkedUniform &glUniform : mData.getUniforms())
1527 {
1528 if (!glUniform.isInDefaultBlock())
1529 continue;
1530
1531 auto mapEntry = uniformMap.find(glUniform.name);
1532 ASSERT(mapEntry != uniformMap.end());
1533 mD3DUniforms.push_back(mapEntry->second);
1534 }
1535
Jamie Madill62d31cb2015-09-11 13:25:51 -04001536 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001537 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001538}
1539
Jamie Madill91445bc2015-09-23 16:47:53 -04001540void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001541 const sh::Uniform &uniform,
1542 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04001543{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001544 if (uniform.isBuiltIn())
Jamie Madillfb536032015-09-11 13:19:49 -04001545 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001546 defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
Jamie Madill55def582015-05-04 11:24:57 -04001547 return;
1548 }
1549
Jamie Madill91445bc2015-09-23 16:47:53 -04001550 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
1551
1552 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
1553 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001554 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001555 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001556
Jamie Madill91445bc2015-09-23 16:47:53 -04001557 defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001558}
1559
Jamie Madill62d31cb2015-09-11 13:25:51 -04001560D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1561{
1562 for (D3DUniform *d3dUniform : mD3DUniforms)
1563 {
1564 if (d3dUniform->name == name)
1565 {
1566 return d3dUniform;
1567 }
1568 }
1569
1570 return nullptr;
1571}
1572
Jamie Madill91445bc2015-09-23 16:47:53 -04001573void ProgramD3D::defineUniform(GLenum shaderType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001574 const sh::ShaderVariable &uniform,
1575 const std::string &fullName,
1576 sh::HLSLBlockEncoder *encoder,
1577 D3DUniformMap *uniformMap)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001578{
1579 if (uniform.isStruct())
1580 {
1581 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1582 {
1583 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1584
Jamie Madill55def582015-05-04 11:24:57 -04001585 if (encoder)
1586 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001587
1588 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1589 {
Jamie Madill334d6152015-10-22 14:00:28 -04001590 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001591 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1592
Jamie Madill91445bc2015-09-23 16:47:53 -04001593 defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001594 }
1595
Jamie Madill55def582015-05-04 11:24:57 -04001596 if (encoder)
1597 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001598 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001599 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001600 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001601
1602 // Not a struct. Arrays are treated as aggregate types.
1603 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001604 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001605 encoder->enterAggregateType();
1606 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001607
Jamie Madill62d31cb2015-09-11 13:25:51 -04001608 // Advance the uniform offset, to track registers allocation for structs
1609 sh::BlockMemberInfo blockInfo =
1610 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
1611 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001612
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001613 auto uniformMapEntry = uniformMap->find(fullName);
1614 D3DUniform *d3dUniform = nullptr;
Jamie Madill2857f482015-02-09 15:35:29 -05001615
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001616 if (uniformMapEntry != uniformMap->end())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001617 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001618 d3dUniform = uniformMapEntry->second;
1619 }
1620 else
1621 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001622 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001623 (*uniformMap)[fullName] = d3dUniform;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001624 }
1625
1626 if (encoder)
1627 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001628 d3dUniform->registerElement =
1629 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001630 unsigned int reg =
1631 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill91445bc2015-09-23 16:47:53 -04001632 if (shaderType == GL_FRAGMENT_SHADER)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001633 {
1634 d3dUniform->psRegisterIndex = reg;
1635 }
Jamie Madill91445bc2015-09-23 16:47:53 -04001636 else
Jamie Madill62d31cb2015-09-11 13:25:51 -04001637 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001638 ASSERT(shaderType == GL_VERTEX_SHADER);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001639 d3dUniform->vsRegisterIndex = reg;
1640 }
Jamie Madillfb536032015-09-11 13:19:49 -04001641
1642 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04001643 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04001644 {
1645 encoder->exitAggregateType();
1646 }
1647 }
1648}
1649
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001650template <typename T>
Jamie Madill334d6152015-10-22 14:00:28 -04001651static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001652{
1653 ASSERT(dest != NULL);
1654 ASSERT(dirtyFlag != NULL);
1655
1656 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
Jamie Madill334d6152015-10-22 14:00:28 -04001657 *dest = source;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001658}
1659
1660template <typename T>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001661void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001662{
Jamie Madill334d6152015-10-22 14:00:28 -04001663 const int components = gl::VariableComponentCount(targetUniformType);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001664 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1665
Jamie Madill62d31cb2015-09-11 13:25:51 -04001666 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001667
Jamie Madill62d31cb2015-09-11 13:25:51 -04001668 unsigned int elementCount = targetUniform->elementCount();
1669 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1670 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001671
1672 if (targetUniform->type == targetUniformType)
1673 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001674 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001675
Jamie Madill62d31cb2015-09-11 13:25:51 -04001676 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001677 {
Jamie Madill334d6152015-10-22 14:00:28 -04001678 T *dest = target + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001679 const T *source = v + (i * components);
1680
1681 for (int c = 0; c < components; c++)
1682 {
1683 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1684 }
1685 for (int c = components; c < 4; c++)
1686 {
1687 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1688 }
1689 }
1690 }
1691 else if (targetUniform->type == targetBoolType)
1692 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001693 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001694
Jamie Madill62d31cb2015-09-11 13:25:51 -04001695 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001696 {
Jamie Madill334d6152015-10-22 14:00:28 -04001697 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001698 const T *source = v + (i * components);
1699
1700 for (int c = 0; c < components; c++)
1701 {
Jamie Madill334d6152015-10-22 14:00:28 -04001702 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
1703 &targetUniform->dirty);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001704 }
1705 for (int c = components; c < 4; c++)
1706 {
1707 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1708 }
1709 }
1710 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001711 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001712 {
1713 ASSERT(targetUniformType == GL_INT);
1714
Jamie Madill62d31cb2015-09-11 13:25:51 -04001715 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001716
1717 bool wasDirty = targetUniform->dirty;
1718
Jamie Madill62d31cb2015-09-11 13:25:51 -04001719 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001720 {
Jamie Madill334d6152015-10-22 14:00:28 -04001721 GLint *dest = target + (i * 4);
1722 const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001723
1724 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1725 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1726 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1727 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1728 }
1729
1730 if (!wasDirty && targetUniform->dirty)
1731 {
1732 mDirtySamplerMapping = true;
1733 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001734 }
Jamie Madill334d6152015-10-22 14:00:28 -04001735 else
1736 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001737}
1738
1739template <int cols, int rows>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001740void ProgramD3D::setUniformMatrixfv(GLint location,
1741 GLsizei countIn,
1742 GLboolean transpose,
1743 const GLfloat *value,
1744 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001745{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001746 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001747
Jamie Madill62d31cb2015-09-11 13:25:51 -04001748 unsigned int elementCount = targetUniform->elementCount();
1749 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1750 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001751
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001752 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001753 GLfloat *target =
1754 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001755
Jamie Madill62d31cb2015-09-11 13:25:51 -04001756 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001757 {
1758 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1759 if (transpose == GL_FALSE)
1760 {
Jamie Madill334d6152015-10-22 14:00:28 -04001761 targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) ||
1762 targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001763 }
1764 else
1765 {
Jamie Madill334d6152015-10-22 14:00:28 -04001766 targetUniform->dirty =
1767 ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001768 }
1769 target += targetMatrixStride;
1770 value += cols * rows;
1771 }
1772}
1773
Jamie Madill4a3c2342015-10-08 12:58:45 -04001774size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001775{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001776 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001777
Jamie Madill62d31cb2015-09-11 13:25:51 -04001778 // define member uniforms
1779 sh::Std140BlockEncoder std140Encoder;
1780 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1781 sh::BlockLayoutEncoder *encoder = nullptr;
1782
1783 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001784 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001785 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001786 }
1787 else
1788 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001789 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00001790 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001791
1792 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
Jamie Madill4a3c2342015-10-08 12:58:45 -04001793 &mBlockInfo);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001794
1795 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00001796}
1797
Jamie Madill62d31cb2015-09-11 13:25:51 -04001798void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001799{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001800 for (const D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001801 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001802 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04001803 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001804 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001805 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001806 }
1807}
1808
Jamie Madill62d31cb2015-09-11 13:25:51 -04001809void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001810{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001811 ASSERT(d3dUniform->isSampler());
1812 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
1813 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madillfb536032015-09-11 13:19:49 -04001814
Jamie Madill62d31cb2015-09-11 13:25:51 -04001815 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001816 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001817 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1818 mSamplersVS, &mUsedVertexSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001819 }
1820
Jamie Madill62d31cb2015-09-11 13:25:51 -04001821 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001822 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001823 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1824 mSamplersPS, &mUsedPixelSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001825 }
1826}
1827
Jamie Madill62d31cb2015-09-11 13:25:51 -04001828// static
1829void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001830 GLenum samplerType,
1831 unsigned int samplerCount,
1832 std::vector<Sampler> &outSamplers,
1833 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001834{
1835 unsigned int samplerIndex = startSamplerIndex;
1836
1837 do
1838 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001839 ASSERT(samplerIndex < outSamplers.size());
1840 Sampler *sampler = &outSamplers[samplerIndex];
1841 sampler->active = true;
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001842 sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001843 sampler->logicalTextureUnit = 0;
1844 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001845 samplerIndex++;
1846 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07001847}
1848
Brandon Jonesc9610c52014-08-25 17:02:59 -07001849void ProgramD3D::reset()
1850{
Brandon Joneseb994362014-09-24 10:27:28 -07001851 SafeDeleteContainer(mVertexExecutables);
1852 SafeDeleteContainer(mPixelExecutables);
1853 SafeDelete(mGeometryExecutable);
1854
Brandon Jones22502d52014-08-29 16:58:36 -07001855 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001856 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001857
1858 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001859 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001860 mUsesFragDepth = false;
1861 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001862 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -07001863
Jamie Madill62d31cb2015-09-11 13:25:51 -04001864 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001865 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001866
Brandon Jonesc9610c52014-08-25 17:02:59 -07001867 SafeDelete(mVertexUniformStorage);
1868 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001869
1870 mSamplersPS.clear();
1871 mSamplersVS.clear();
1872
1873 mUsedVertexSamplerRange = 0;
Jamie Madill334d6152015-10-22 14:00:28 -04001874 mUsedPixelSamplerRange = 0;
1875 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05001876
Jamie Madill63805b42015-08-25 13:17:39 -04001877 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05001878 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001879
1880 mTransformFeedbackLinkedVaryings.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07001881}
1882
Geoff Lang7dd2e102014-11-10 15:19:26 -05001883unsigned int ProgramD3D::getSerial() const
1884{
1885 return mSerial;
1886}
1887
1888unsigned int ProgramD3D::issueSerial()
1889{
1890 return mCurrentSerial++;
1891}
1892
Jamie Madill63805b42015-08-25 13:17:39 -04001893void ProgramD3D::initSemanticIndex()
1894{
1895 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1896 ASSERT(vertexShader != nullptr);
1897
1898 // Init semantic index
1899 for (const sh::Attribute &attribute : mData.getAttributes())
1900 {
1901 int attributeIndex = attribute.location;
1902 int index = vertexShader->getSemanticIndex(attribute.name);
1903 int regs = gl::VariableRegisterCount(attribute.type);
1904
1905 for (int reg = 0; reg < regs; ++reg)
1906 {
1907 mSemanticIndexes[attributeIndex + reg] = index + reg;
1908 }
1909 }
1910
1911 initAttributesByLayout();
1912}
1913
Jamie Madill437d2662014-12-05 14:23:35 -05001914void ProgramD3D::initAttributesByLayout()
1915{
1916 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
1917 {
1918 mAttributesByLayout[i] = i;
1919 }
1920
Jamie Madill63805b42015-08-25 13:17:39 -04001921 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
1922 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05001923}
1924
Jamie Madill334d6152015-10-22 14:00:28 -04001925void ProgramD3D::sortAttributesByLayout(
1926 const std::vector<TranslatedAttribute> &unsortedAttributes,
1927 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
1928 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05001929{
Jamie Madill476682e2015-06-30 10:04:29 -04001930 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05001931 {
Jamie Madill334d6152015-10-22 14:00:28 -04001932 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04001933 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill334d6152015-10-22 14:00:28 -04001934 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05001935 }
1936}
1937
Jamie Madill63805b42015-08-25 13:17:39 -04001938void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04001939{
Jamie Madillbd136f92015-08-10 14:51:37 -04001940 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04001941 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04001942
Dian Xianga4928832015-09-15 10:11:17 -07001943 for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask()))
Jamie Madilld3dfda22015-07-06 08:28:49 -04001944 {
Jamie Madill63805b42015-08-25 13:17:39 -04001945 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04001946
1947 if (semanticIndex != -1)
1948 {
Jamie Madillbd136f92015-08-10 14:51:37 -04001949 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
1950 {
1951 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
1952 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04001953 mCachedInputLayout[semanticIndex] =
1954 GetVertexFormatType(vertexAttributes[attributeIndex],
1955 state.getVertexAttribCurrentValue(attributeIndex).Type);
1956 }
1957 }
1958}
1959
Jamie Madillccdf74b2015-08-18 10:46:12 -04001960void ProgramD3D::gatherTransformFeedbackVaryings(
1961 const std::vector<gl::LinkedVarying> &linkedVaryings)
1962{
1963 // Gather the linked varyings that are used for transform feedback, they should all exist.
1964 mTransformFeedbackLinkedVaryings.clear();
1965 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
1966 {
1967 for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
1968 {
1969 if (tfVaryingName == linkedVarying.name)
1970 {
1971 mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
1972 break;
1973 }
1974 }
1975 }
1976}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001977
1978D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
1979{
1980 return mD3DUniforms[mData.getUniformLocations()[location].index];
1981}
Jamie Madill4a3c2342015-10-08 12:58:45 -04001982
1983bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
1984{
1985 std::string baseName = blockName;
1986 gl::ParseAndStripArrayIndex(&baseName);
1987
1988 auto sizeIter = mBlockDataSizes.find(baseName);
1989 if (sizeIter == mBlockDataSizes.end())
1990 {
1991 *sizeOut = 0;
1992 return false;
1993 }
1994
1995 *sizeOut = sizeIter->second;
1996 return true;
1997}
1998
1999bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
2000 sh::BlockMemberInfo *memberInfoOut) const
2001{
2002 auto infoIter = mBlockInfo.find(memberUniformName);
2003 if (infoIter == mBlockInfo.end())
2004 {
2005 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
2006 return false;
2007 }
2008
2009 *memberInfoOut = infoIter->second;
2010 return true;
2011}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002012}