blob: 9995d4922371b0584e09c81b4a49e0e4bbcab0e4 [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 gl::InputLayout &defaultInputLayout =
1043 GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
Jamie Madille4ea2022015-03-26 20:35:05 +00001044 ShaderExecutableD3D *defaultVertexExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001045 gl::Error error =
1046 getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
Jamie Madille4ea2022015-03-26 20:35:05 +00001047 if (error.isError())
Austin Kinross434953e2015-02-20 10:49:51 -08001048 {
Jamie Madille4ea2022015-03-26 20:35:05 +00001049 return LinkResult(false, error);
1050 }
Austin Kinross434953e2015-02-20 10:49:51 -08001051
Jamie Madill334d6152015-10-22 14:00:28 -04001052 std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
Geoff Lang359ef262015-01-05 14:42:29 -05001053 ShaderExecutableD3D *defaultPixelExecutable = NULL;
Jamie Madill334d6152015-10-22 14:00:28 -04001054 error =
1055 getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
Geoff Langb543aff2014-09-30 14:52:54 -04001056 if (error.isError())
1057 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001058 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001059 }
Brandon Jones44151a92014-09-10 11:32:25 -07001060
Brandon Joneseb994362014-09-24 10:27:28 -07001061 if (usesGeometryShader())
1062 {
Jamie Madill334d6152015-10-22 14:00:28 -04001063 std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
Jamie Madill76f8fa62015-10-29 10:32:56 -04001064 gl::PRIMITIVE_POINTS, data, mData, registers, packedVaryings);
Brandon Jones44151a92014-09-10 11:32:25 -07001065
Jamie Madillada9ecc2015-08-17 12:53:37 -04001066 error = mRenderer->compileToExecutable(
1067 infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
1068 (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1069 D3DCompilerWorkarounds(), &mGeometryExecutable);
Geoff Langb543aff2014-09-30 14:52:54 -04001070 if (error.isError())
1071 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001072 return LinkResult(false, error);
Geoff Langb543aff2014-09-30 14:52:54 -04001073 }
Brandon Joneseb994362014-09-24 10:27:28 -07001074 }
1075
Brandon Jones091540d2014-10-29 11:32:04 -07001076#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
Jamie Madillca03b352015-09-02 12:38:13 -04001077 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001078 if (usesGeometryShader() && mGeometryExecutable)
1079 {
Jamie Madill334d6152015-10-22 14:00:28 -04001080 // Geometry shaders are currently only used internally, so there is no corresponding shader
1081 // object at the interface level. For now the geometry shader debug info is prepended to
1082 // the vertex shader.
Tibor den Ouden97049c62014-10-06 21:39:16 +02001083 vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1084 vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
1085 vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1086 }
1087
1088 if (defaultVertexExecutable)
1089 {
1090 vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1091 }
1092
1093 if (defaultPixelExecutable)
1094 {
Jamie Madill76f8fa62015-10-29 10:32:56 -04001095 const ShaderD3D *fragmentShaderD3D =
1096 GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Tibor den Ouden97049c62014-10-06 21:39:16 +02001097 fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1098 }
1099#endif
1100
Jamie Madill334d6152015-10-22 14:00:28 -04001101 bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable &&
1102 (!usesGeometryShader() || mGeometryExecutable));
Geoff Lang7dd2e102014-11-10 15:19:26 -05001103 return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
Brandon Jones18bd4102014-09-22 14:21:44 -07001104}
1105
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001106LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
Brandon Jones22502d52014-08-29 16:58:36 -07001107{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001108 reset();
1109
1110 // TODO(jmadill): structures containing samplers
1111 for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
1112 {
1113 if (linkedUniform.isSampler() && linkedUniform.isField())
1114 {
1115 infoLog << "Structures containing samplers not currently supported in D3D.";
1116 return LinkResult(false, gl::Error(GL_NO_ERROR));
1117 }
1118 }
1119
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001120 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1121 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Brandon Joneseb994362014-09-24 10:27:28 -07001122
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001123 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
1124 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1125
Jamie Madill63069df2015-09-01 17:26:41 +00001126 mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001127 mSamplersPS.resize(data.caps->maxTextureImageUnits);
Brandon Jones22502d52014-08-29 16:58:36 -07001128
Arun Patole44efa0b2015-03-04 17:11:05 +05301129 vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
Jamie Madillf5f4ad22015-09-02 18:32:38 +00001130 fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1131
Austin Kinross02df7962015-07-01 10:03:42 -07001132 if (mRenderer->getRendererLimitations().noFrontFacingSupport)
1133 {
1134 if (fragmentShaderD3D->usesFrontFacing())
1135 {
1136 infoLog << "The current renderer doesn't support gl_FrontFacing";
1137 return LinkResult(false, gl::Error(GL_NO_ERROR));
1138 }
1139 }
1140
Jamie Madillca03b352015-09-02 12:38:13 -04001141 std::vector<PackedVarying> packedVaryings =
1142 MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
1143
Brandon Jones22502d52014-08-29 16:58:36 -07001144 // Map the varyings to the register file
Jamie Madill334d6152015-10-22 14:00:28 -04001145 int registers = mDynamicHLSL->packVaryings(*data.caps, infoLog, &packedVaryings,
Jamie Madill31c8c562015-08-19 14:08:03 -04001146 mData.getTransformFeedbackVaryingNames());
Brandon Jones22502d52014-08-29 16:58:36 -07001147
Jamie Madill31c8c562015-08-19 14:08:03 -04001148 if (registers < 0)
Brandon Jones22502d52014-08-29 16:58:36 -07001149 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001150 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001151 }
1152
Jamie Madillccdf74b2015-08-18 10:46:12 -04001153 std::vector<gl::LinkedVarying> linkedVaryings;
Jamie Madill334d6152015-10-22 14:00:28 -04001154 if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, &mPixelHLSL,
1155 &mVertexHLSL, packedVaryings, &linkedVaryings,
Jamie Madillca03b352015-09-02 12:38:13 -04001156 &mPixelShaderKey, &mUsesFragDepth))
Brandon Jones22502d52014-08-29 16:58:36 -07001157 {
Geoff Lang7dd2e102014-11-10 15:19:26 -05001158 return LinkResult(false, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001159 }
1160
Brandon Jones44151a92014-09-10 11:32:25 -07001161 mUsesPointSize = vertexShaderD3D->usesPointSize();
1162
Jamie Madill63805b42015-08-25 13:17:39 -04001163 initSemanticIndex();
Jamie Madill437d2662014-12-05 14:23:35 -05001164
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001165 defineUniformsAndAssignRegisters();
Jamie Madille473dee2015-08-18 14:49:01 -04001166
Jamie Madillccdf74b2015-08-18 10:46:12 -04001167 gatherTransformFeedbackVaryings(linkedVaryings);
1168
Jamie Madill334d6152015-10-22 14:00:28 -04001169 LinkResult result = compileProgramExecutables(data, infoLog, registers, packedVaryings);
Jamie Madill31c8c562015-08-19 14:08:03 -04001170 if (result.error.isError() || !result.linkSuccess)
1171 {
1172 infoLog << "Failed to create D3D shaders.";
1173 return result;
1174 }
1175
Jamie Madill4a3c2342015-10-08 12:58:45 -04001176 initUniformBlockInfo();
1177
Geoff Lang7dd2e102014-11-10 15:19:26 -05001178 return LinkResult(true, gl::Error(GL_NO_ERROR));
Brandon Jones22502d52014-08-29 16:58:36 -07001179}
1180
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001181GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001182{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001183 // TODO(jmadill): Do something useful here?
1184 return GL_TRUE;
Jamie Madill36cfd6a2015-08-18 10:46:20 -04001185}
1186
Jamie Madill4a3c2342015-10-08 12:58:45 -04001187void ProgramD3D::initUniformBlockInfo()
Jamie Madill62d31cb2015-09-11 13:25:51 -04001188{
1189 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1190
Jamie Madill62d31cb2015-09-11 13:25:51 -04001191 for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
1192 {
1193 if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
1194 continue;
1195
Jamie Madill4a3c2342015-10-08 12:58:45 -04001196 if (mBlockDataSizes.count(vertexBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001197 continue;
1198
Jamie Madill4a3c2342015-10-08 12:58:45 -04001199 size_t dataSize = getUniformBlockInfo(vertexBlock);
1200 mBlockDataSizes[vertexBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001201 }
1202
1203 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
1204
1205 for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
1206 {
1207 if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
1208 continue;
1209
Jamie Madill4a3c2342015-10-08 12:58:45 -04001210 if (mBlockDataSizes.count(fragmentBlock.name) > 0)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001211 continue;
1212
Jamie Madill4a3c2342015-10-08 12:58:45 -04001213 size_t dataSize = getUniformBlockInfo(fragmentBlock);
1214 mBlockDataSizes[fragmentBlock.name] = dataSize;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001215 }
Jamie Madill4a3c2342015-10-08 12:58:45 -04001216}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001217
Jamie Madill4a3c2342015-10-08 12:58:45 -04001218void ProgramD3D::assignUniformBlockRegisters()
1219{
1220 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001221
1222 // Assign registers and update sizes.
Jamie Madill4a3c2342015-10-08 12:58:45 -04001223 const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
1224 const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
Jamie Madill62d31cb2015-09-11 13:25:51 -04001225
Jamie Madill4a3c2342015-10-08 12:58:45 -04001226 for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001227 {
1228 unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1229
Jamie Madill4a3c2342015-10-08 12:58:45 -04001230 D3DUniformBlock d3dUniformBlock;
1231
Jamie Madill62d31cb2015-09-11 13:25:51 -04001232 if (uniformBlock.vertexStaticUse)
1233 {
1234 unsigned int baseRegister =
1235 vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001236 d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001237 }
1238
1239 if (uniformBlock.fragmentStaticUse)
1240 {
1241 unsigned int baseRegister =
1242 fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001243 d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001244 }
1245
Jamie Madill4a3c2342015-10-08 12:58:45 -04001246 mD3DUniformBlocks.push_back(d3dUniformBlock);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001247 }
1248}
1249
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001250void ProgramD3D::initializeUniformStorage()
Brandon Jonesc9610c52014-08-25 17:02:59 -07001251{
1252 // Compute total default block size
Jamie Madill334d6152015-10-22 14:00:28 -04001253 unsigned int vertexRegisters = 0;
Brandon Jonesc9610c52014-08-25 17:02:59 -07001254 unsigned int fragmentRegisters = 0;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001255 for (const D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jonesc9610c52014-08-25 17:02:59 -07001256 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001257 if (!d3dUniform->isSampler())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001258 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001259 if (d3dUniform->isReferencedByVertexShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001260 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001261 vertexRegisters = std::max(vertexRegisters,
1262 d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001263 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001264 if (d3dUniform->isReferencedByFragmentShader())
Brandon Jonesc9610c52014-08-25 17:02:59 -07001265 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001266 fragmentRegisters = std::max(
1267 fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001268 }
1269 }
1270 }
1271
Jamie Madill334d6152015-10-22 14:00:28 -04001272 mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
Brandon Jonesc9610c52014-08-25 17:02:59 -07001273 mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
1274}
1275
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001276gl::Error ProgramD3D::applyUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001277{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001278 updateSamplerMapping();
1279
Jamie Madill62d31cb2015-09-11 13:25:51 -04001280 gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001281 if (error.isError())
1282 {
1283 return error;
1284 }
1285
Jamie Madill62d31cb2015-09-11 13:25:51 -04001286 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001287 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001288 d3dUniform->dirty = false;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001289 }
1290
1291 return gl::Error(GL_NO_ERROR);
Brandon Jones18bd4102014-09-22 14:21:44 -07001292}
1293
Jamie Madilld1fe1642015-08-21 16:26:04 -04001294gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
Brandon Jones18bd4102014-09-22 14:21:44 -07001295{
Jamie Madill4a3c2342015-10-08 12:58:45 -04001296 if (mData.getUniformBlocks().empty())
1297 {
1298 return gl::Error(GL_NO_ERROR);
1299 }
1300
1301 // Lazy init.
1302 if (mD3DUniformBlocks.empty())
1303 {
1304 assignUniformBlockRegisters();
1305 }
1306
Jamie Madill03260fa2015-06-22 13:57:22 -04001307 mVertexUBOCache.clear();
1308 mFragmentUBOCache.clear();
Brandon Jones18bd4102014-09-22 14:21:44 -07001309
1310 const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
1311 const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
1312
Jamie Madill4a3c2342015-10-08 12:58:45 -04001313 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001314 uniformBlockIndex++)
Brandon Jones18bd4102014-09-22 14:21:44 -07001315 {
Jamie Madill4a3c2342015-10-08 12:58:45 -04001316 const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
1317 GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
Brandon Jones18bd4102014-09-22 14:21:44 -07001318
Brandon Jones18bd4102014-09-22 14:21:44 -07001319 // Unnecessary to apply an unreferenced standard or shared UBO
Jamie Madill4a3c2342015-10-08 12:58:45 -04001320 if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001321 {
1322 continue;
1323 }
1324
Jamie Madill4a3c2342015-10-08 12:58:45 -04001325 if (uniformBlock.vertexStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001326 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001327 unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001328 ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001329
Jamie Madill969194d2015-07-20 14:36:56 -04001330 if (mVertexUBOCache.size() <= registerIndex)
Jamie Madill03260fa2015-06-22 13:57:22 -04001331 {
1332 mVertexUBOCache.resize(registerIndex + 1, -1);
1333 }
1334
1335 ASSERT(mVertexUBOCache[registerIndex] == -1);
1336 mVertexUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001337 }
1338
Jamie Madill4a3c2342015-10-08 12:58:45 -04001339 if (uniformBlock.fragmentStaticUse())
Brandon Jones18bd4102014-09-22 14:21:44 -07001340 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001341 unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001342 ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
Jamie Madill03260fa2015-06-22 13:57:22 -04001343
1344 if (mFragmentUBOCache.size() <= registerIndex)
1345 {
1346 mFragmentUBOCache.resize(registerIndex + 1, -1);
1347 }
1348
1349 ASSERT(mFragmentUBOCache[registerIndex] == -1);
1350 mFragmentUBOCache[registerIndex] = blockBinding;
Brandon Jones18bd4102014-09-22 14:21:44 -07001351 }
1352 }
1353
Jamie Madill03260fa2015-06-22 13:57:22 -04001354 return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
Brandon Jones18bd4102014-09-22 14:21:44 -07001355}
1356
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001357void ProgramD3D::dirtyAllUniforms()
Brandon Jones18bd4102014-09-22 14:21:44 -07001358{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001359 for (D3DUniform *d3dUniform : mD3DUniforms)
Brandon Jones18bd4102014-09-22 14:21:44 -07001360 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001361 d3dUniform->dirty = true;
Brandon Jones18bd4102014-09-22 14:21:44 -07001362 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001363}
1364
Jamie Madill334d6152015-10-22 14:00:28 -04001365void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001366{
1367 setUniform(location, count, v, GL_FLOAT);
1368}
1369
1370void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1371{
1372 setUniform(location, count, v, GL_FLOAT_VEC2);
1373}
1374
1375void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1376{
1377 setUniform(location, count, v, GL_FLOAT_VEC3);
1378}
1379
1380void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1381{
1382 setUniform(location, count, v, GL_FLOAT_VEC4);
1383}
1384
Jamie Madill334d6152015-10-22 14:00:28 -04001385void ProgramD3D::setUniformMatrix2fv(GLint location,
1386 GLsizei count,
1387 GLboolean transpose,
1388 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001389{
1390 setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1391}
1392
Jamie Madill334d6152015-10-22 14:00:28 -04001393void ProgramD3D::setUniformMatrix3fv(GLint location,
1394 GLsizei count,
1395 GLboolean transpose,
1396 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001397{
1398 setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1399}
1400
Jamie Madill334d6152015-10-22 14:00:28 -04001401void ProgramD3D::setUniformMatrix4fv(GLint location,
1402 GLsizei count,
1403 GLboolean transpose,
1404 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001405{
1406 setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1407}
1408
Jamie Madill334d6152015-10-22 14:00:28 -04001409void ProgramD3D::setUniformMatrix2x3fv(GLint location,
1410 GLsizei count,
1411 GLboolean transpose,
1412 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001413{
1414 setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1415}
1416
Jamie Madill334d6152015-10-22 14:00:28 -04001417void ProgramD3D::setUniformMatrix3x2fv(GLint location,
1418 GLsizei count,
1419 GLboolean transpose,
1420 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001421{
1422 setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1423}
1424
Jamie Madill334d6152015-10-22 14:00:28 -04001425void ProgramD3D::setUniformMatrix2x4fv(GLint location,
1426 GLsizei count,
1427 GLboolean transpose,
1428 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001429{
1430 setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1431}
1432
Jamie Madill334d6152015-10-22 14:00:28 -04001433void ProgramD3D::setUniformMatrix4x2fv(GLint location,
1434 GLsizei count,
1435 GLboolean transpose,
1436 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001437{
1438 setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1439}
1440
Jamie Madill334d6152015-10-22 14:00:28 -04001441void ProgramD3D::setUniformMatrix3x4fv(GLint location,
1442 GLsizei count,
1443 GLboolean transpose,
1444 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001445{
1446 setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1447}
1448
Jamie Madill334d6152015-10-22 14:00:28 -04001449void ProgramD3D::setUniformMatrix4x3fv(GLint location,
1450 GLsizei count,
1451 GLboolean transpose,
1452 const GLfloat *value)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001453{
1454 setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1455}
1456
1457void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1458{
1459 setUniform(location, count, v, GL_INT);
1460}
1461
1462void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1463{
1464 setUniform(location, count, v, GL_INT_VEC2);
1465}
1466
1467void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1468{
1469 setUniform(location, count, v, GL_INT_VEC3);
1470}
1471
1472void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1473{
1474 setUniform(location, count, v, GL_INT_VEC4);
1475}
1476
1477void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1478{
1479 setUniform(location, count, v, GL_UNSIGNED_INT);
1480}
1481
1482void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1483{
1484 setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
1485}
1486
1487void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1488{
1489 setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
1490}
1491
1492void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1493{
1494 setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
1495}
1496
Jamie Madill4a3c2342015-10-08 12:58:45 -04001497void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
1498 GLuint /*uniformBlockBinding*/)
Geoff Lang5d124a62015-09-15 13:03:27 -04001499{
1500}
1501
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001502void ProgramD3D::defineUniformsAndAssignRegisters()
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001503{
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001504 D3DUniformMap uniformMap;
Jamie Madill334d6152015-10-22 14:00:28 -04001505 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001506 for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001507
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001508 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001509 if (vertexUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001510 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001511 defineUniformBase(vertexShader, vertexUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001512 }
1513 }
1514
Jamie Madill334d6152015-10-22 14:00:28 -04001515 const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001516 for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
Jamie Madillfb536032015-09-11 13:19:49 -04001517 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001518 if (fragmentUniform.staticUse)
Jamie Madillfb536032015-09-11 13:19:49 -04001519 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001520 defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
Jamie Madillfb536032015-09-11 13:19:49 -04001521 }
1522 }
1523
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001524 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
1525 for (const gl::LinkedUniform &glUniform : mData.getUniforms())
1526 {
1527 if (!glUniform.isInDefaultBlock())
1528 continue;
1529
1530 auto mapEntry = uniformMap.find(glUniform.name);
1531 ASSERT(mapEntry != uniformMap.end());
1532 mD3DUniforms.push_back(mapEntry->second);
1533 }
1534
Jamie Madill62d31cb2015-09-11 13:25:51 -04001535 assignAllSamplerRegisters();
Jamie Madillfb536032015-09-11 13:19:49 -04001536 initializeUniformStorage();
Jamie Madillfb536032015-09-11 13:19:49 -04001537}
1538
Jamie Madill91445bc2015-09-23 16:47:53 -04001539void ProgramD3D::defineUniformBase(const gl::Shader *shader,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001540 const sh::Uniform &uniform,
1541 D3DUniformMap *uniformMap)
Jamie Madillfb536032015-09-11 13:19:49 -04001542{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001543 if (uniform.isBuiltIn())
Jamie Madillfb536032015-09-11 13:19:49 -04001544 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001545 defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
Jamie Madill55def582015-05-04 11:24:57 -04001546 return;
1547 }
1548
Jamie Madill91445bc2015-09-23 16:47:53 -04001549 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
1550
1551 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
1552 ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001553 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001554 encoder.skipRegisters(startRegister);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001555
Jamie Madill91445bc2015-09-23 16:47:53 -04001556 defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001557}
1558
Jamie Madill62d31cb2015-09-11 13:25:51 -04001559D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
1560{
1561 for (D3DUniform *d3dUniform : mD3DUniforms)
1562 {
1563 if (d3dUniform->name == name)
1564 {
1565 return d3dUniform;
1566 }
1567 }
1568
1569 return nullptr;
1570}
1571
Jamie Madill91445bc2015-09-23 16:47:53 -04001572void ProgramD3D::defineUniform(GLenum shaderType,
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001573 const sh::ShaderVariable &uniform,
1574 const std::string &fullName,
1575 sh::HLSLBlockEncoder *encoder,
1576 D3DUniformMap *uniformMap)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001577{
1578 if (uniform.isStruct())
1579 {
1580 for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
1581 {
1582 const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
1583
Jamie Madill55def582015-05-04 11:24:57 -04001584 if (encoder)
1585 encoder->enterAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001586
1587 for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
1588 {
Jamie Madill334d6152015-10-22 14:00:28 -04001589 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001590 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
1591
Jamie Madill91445bc2015-09-23 16:47:53 -04001592 defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001593 }
1594
Jamie Madill55def582015-05-04 11:24:57 -04001595 if (encoder)
1596 encoder->exitAggregateType();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001597 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001598 return;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001599 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001600
1601 // Not a struct. Arrays are treated as aggregate types.
1602 if (uniform.isArray() && encoder)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001603 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001604 encoder->enterAggregateType();
1605 }
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001606
Jamie Madill62d31cb2015-09-11 13:25:51 -04001607 // Advance the uniform offset, to track registers allocation for structs
1608 sh::BlockMemberInfo blockInfo =
1609 encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
1610 : sh::BlockMemberInfo::getDefaultBlockInfo();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001611
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001612 auto uniformMapEntry = uniformMap->find(fullName);
1613 D3DUniform *d3dUniform = nullptr;
Jamie Madill2857f482015-02-09 15:35:29 -05001614
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001615 if (uniformMapEntry != uniformMap->end())
Jamie Madill62d31cb2015-09-11 13:25:51 -04001616 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001617 d3dUniform = uniformMapEntry->second;
1618 }
1619 else
1620 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001621 d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001622 (*uniformMap)[fullName] = d3dUniform;
Jamie Madill62d31cb2015-09-11 13:25:51 -04001623 }
1624
1625 if (encoder)
1626 {
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001627 d3dUniform->registerElement =
1628 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
Jamie Madill62d31cb2015-09-11 13:25:51 -04001629 unsigned int reg =
1630 static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
Jamie Madill91445bc2015-09-23 16:47:53 -04001631 if (shaderType == GL_FRAGMENT_SHADER)
Jamie Madill62d31cb2015-09-11 13:25:51 -04001632 {
1633 d3dUniform->psRegisterIndex = reg;
1634 }
Jamie Madill91445bc2015-09-23 16:47:53 -04001635 else
Jamie Madill62d31cb2015-09-11 13:25:51 -04001636 {
Jamie Madill91445bc2015-09-23 16:47:53 -04001637 ASSERT(shaderType == GL_VERTEX_SHADER);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001638 d3dUniform->vsRegisterIndex = reg;
1639 }
Jamie Madillfb536032015-09-11 13:19:49 -04001640
1641 // Arrays are treated as aggregate types
Jamie Madill62d31cb2015-09-11 13:25:51 -04001642 if (uniform.isArray())
Jamie Madillfb536032015-09-11 13:19:49 -04001643 {
1644 encoder->exitAggregateType();
1645 }
1646 }
1647}
1648
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001649template <typename T>
Jamie Madill334d6152015-10-22 14:00:28 -04001650static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001651{
1652 ASSERT(dest != NULL);
1653 ASSERT(dirtyFlag != NULL);
1654
1655 *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
Jamie Madill334d6152015-10-22 14:00:28 -04001656 *dest = source;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001657}
1658
1659template <typename T>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001660void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001661{
Jamie Madill334d6152015-10-22 14:00:28 -04001662 const int components = gl::VariableComponentCount(targetUniformType);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001663 const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
1664
Jamie Madill62d31cb2015-09-11 13:25:51 -04001665 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001666
Jamie Madill62d31cb2015-09-11 13:25:51 -04001667 unsigned int elementCount = targetUniform->elementCount();
1668 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1669 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001670
1671 if (targetUniform->type == targetUniformType)
1672 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001673 T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001674
Jamie Madill62d31cb2015-09-11 13:25:51 -04001675 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001676 {
Jamie Madill334d6152015-10-22 14:00:28 -04001677 T *dest = target + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001678 const T *source = v + (i * components);
1679
1680 for (int c = 0; c < components; c++)
1681 {
1682 SetIfDirty(dest + c, source[c], &targetUniform->dirty);
1683 }
1684 for (int c = components; c < 4; c++)
1685 {
1686 SetIfDirty(dest + c, T(0), &targetUniform->dirty);
1687 }
1688 }
1689 }
1690 else if (targetUniform->type == targetBoolType)
1691 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001692 GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001693
Jamie Madill62d31cb2015-09-11 13:25:51 -04001694 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001695 {
Jamie Madill334d6152015-10-22 14:00:28 -04001696 GLint *dest = boolParams + (i * 4);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001697 const T *source = v + (i * components);
1698
1699 for (int c = 0; c < components; c++)
1700 {
Jamie Madill334d6152015-10-22 14:00:28 -04001701 SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
1702 &targetUniform->dirty);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001703 }
1704 for (int c = components; c < 4; c++)
1705 {
1706 SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
1707 }
1708 }
1709 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001710 else if (targetUniform->isSampler())
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001711 {
1712 ASSERT(targetUniformType == GL_INT);
1713
Jamie Madill62d31cb2015-09-11 13:25:51 -04001714 GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001715
1716 bool wasDirty = targetUniform->dirty;
1717
Jamie Madill62d31cb2015-09-11 13:25:51 -04001718 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001719 {
Jamie Madill334d6152015-10-22 14:00:28 -04001720 GLint *dest = target + (i * 4);
1721 const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001722
1723 SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
1724 SetIfDirty(dest + 1, 0, &targetUniform->dirty);
1725 SetIfDirty(dest + 2, 0, &targetUniform->dirty);
1726 SetIfDirty(dest + 3, 0, &targetUniform->dirty);
1727 }
1728
1729 if (!wasDirty && targetUniform->dirty)
1730 {
1731 mDirtySamplerMapping = true;
1732 }
Brandon Jones18bd4102014-09-22 14:21:44 -07001733 }
Jamie Madill334d6152015-10-22 14:00:28 -04001734 else
1735 UNREACHABLE();
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001736}
1737
1738template <int cols, int rows>
Jamie Madill62d31cb2015-09-11 13:25:51 -04001739void ProgramD3D::setUniformMatrixfv(GLint location,
1740 GLsizei countIn,
1741 GLboolean transpose,
1742 const GLfloat *value,
1743 GLenum targetUniformType)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001744{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001745 D3DUniform *targetUniform = getD3DUniformFromLocation(location);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001746
Jamie Madill62d31cb2015-09-11 13:25:51 -04001747 unsigned int elementCount = targetUniform->elementCount();
1748 unsigned int arrayElement = mData.getUniformLocations()[location].element;
1749 unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001750
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001751 const unsigned int targetMatrixStride = (4 * rows);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001752 GLfloat *target =
1753 (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001754
Jamie Madill62d31cb2015-09-11 13:25:51 -04001755 for (unsigned int i = 0; i < count; i++)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001756 {
1757 // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
1758 if (transpose == GL_FALSE)
1759 {
Jamie Madill334d6152015-10-22 14:00:28 -04001760 targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) ||
1761 targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001762 }
1763 else
1764 {
Jamie Madill334d6152015-10-22 14:00:28 -04001765 targetUniform->dirty =
1766 ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001767 }
1768 target += targetMatrixStride;
1769 value += cols * rows;
1770 }
1771}
1772
Jamie Madill4a3c2342015-10-08 12:58:45 -04001773size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001774{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001775 ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001776
Jamie Madill62d31cb2015-09-11 13:25:51 -04001777 // define member uniforms
1778 sh::Std140BlockEncoder std140Encoder;
1779 sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
1780 sh::BlockLayoutEncoder *encoder = nullptr;
1781
1782 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001783 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001784 encoder = &std140Encoder;
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001785 }
1786 else
1787 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001788 encoder = &hlslEncoder;
Jamie Madill61b8dd92015-09-09 19:04:04 +00001789 }
Jamie Madill62d31cb2015-09-11 13:25:51 -04001790
1791 GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
Jamie Madill4a3c2342015-10-08 12:58:45 -04001792 &mBlockInfo);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001793
1794 return encoder->getBlockSize();
Jamie Madill61b8dd92015-09-09 19:04:04 +00001795}
1796
Jamie Madill62d31cb2015-09-11 13:25:51 -04001797void ProgramD3D::assignAllSamplerRegisters()
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001798{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001799 for (const D3DUniform *d3dUniform : mD3DUniforms)
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001800 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001801 if (d3dUniform->isSampler())
Jamie Madillfb536032015-09-11 13:19:49 -04001802 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001803 assignSamplerRegisters(d3dUniform);
Jamie Madillfb536032015-09-11 13:19:49 -04001804 }
Jamie Madilla2eb02c2015-09-11 12:31:41 +00001805 }
1806}
1807
Jamie Madill62d31cb2015-09-11 13:25:51 -04001808void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
Jamie Madillfb536032015-09-11 13:19:49 -04001809{
Jamie Madill62d31cb2015-09-11 13:25:51 -04001810 ASSERT(d3dUniform->isSampler());
1811 ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
1812 d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
Jamie Madillfb536032015-09-11 13:19:49 -04001813
Jamie Madill62d31cb2015-09-11 13:25:51 -04001814 if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001815 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001816 AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1817 mSamplersVS, &mUsedVertexSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001818 }
1819
Jamie Madill62d31cb2015-09-11 13:25:51 -04001820 if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
Jamie Madillfb536032015-09-11 13:19:49 -04001821 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001822 AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
1823 mSamplersPS, &mUsedPixelSamplerRange);
Jamie Madillfb536032015-09-11 13:19:49 -04001824 }
1825}
1826
Jamie Madill62d31cb2015-09-11 13:25:51 -04001827// static
1828void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
Jamie Madilld3dfda22015-07-06 08:28:49 -04001829 GLenum samplerType,
1830 unsigned int samplerCount,
1831 std::vector<Sampler> &outSamplers,
1832 GLuint *outUsedRange)
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001833{
1834 unsigned int samplerIndex = startSamplerIndex;
1835
1836 do
1837 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001838 ASSERT(samplerIndex < outSamplers.size());
1839 Sampler *sampler = &outSamplers[samplerIndex];
1840 sampler->active = true;
Jamie Madill3d3d2f22015-09-23 16:47:51 -04001841 sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
Jamie Madill62d31cb2015-09-11 13:25:51 -04001842 sampler->logicalTextureUnit = 0;
1843 *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001844 samplerIndex++;
1845 } while (samplerIndex < startSamplerIndex + samplerCount);
Brandon Jones18bd4102014-09-22 14:21:44 -07001846}
1847
Brandon Jonesc9610c52014-08-25 17:02:59 -07001848void ProgramD3D::reset()
1849{
Brandon Joneseb994362014-09-24 10:27:28 -07001850 SafeDeleteContainer(mVertexExecutables);
1851 SafeDeleteContainer(mPixelExecutables);
1852 SafeDelete(mGeometryExecutable);
1853
Brandon Jones22502d52014-08-29 16:58:36 -07001854 mVertexHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001855 mVertexWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001856
1857 mPixelHLSL.clear();
Geoff Lang6941a552015-07-27 11:06:45 -04001858 mPixelWorkarounds = D3DCompilerWorkarounds();
Brandon Jones22502d52014-08-29 16:58:36 -07001859 mUsesFragDepth = false;
1860 mPixelShaderKey.clear();
Brandon Jones44151a92014-09-10 11:32:25 -07001861 mUsesPointSize = false;
Brandon Jones22502d52014-08-29 16:58:36 -07001862
Jamie Madill62d31cb2015-09-11 13:25:51 -04001863 SafeDeleteContainer(mD3DUniforms);
Jamie Madill4a3c2342015-10-08 12:58:45 -04001864 mD3DUniformBlocks.clear();
Jamie Madill62d31cb2015-09-11 13:25:51 -04001865
Brandon Jonesc9610c52014-08-25 17:02:59 -07001866 SafeDelete(mVertexUniformStorage);
1867 SafeDelete(mFragmentUniformStorage);
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001868
1869 mSamplersPS.clear();
1870 mSamplersVS.clear();
1871
1872 mUsedVertexSamplerRange = 0;
Jamie Madill334d6152015-10-22 14:00:28 -04001873 mUsedPixelSamplerRange = 0;
1874 mDirtySamplerMapping = true;
Jamie Madill437d2662014-12-05 14:23:35 -05001875
Jamie Madill63805b42015-08-25 13:17:39 -04001876 std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
Jamie Madill437d2662014-12-05 14:23:35 -05001877 std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
Jamie Madillccdf74b2015-08-18 10:46:12 -04001878
1879 mTransformFeedbackLinkedVaryings.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07001880}
1881
Geoff Lang7dd2e102014-11-10 15:19:26 -05001882unsigned int ProgramD3D::getSerial() const
1883{
1884 return mSerial;
1885}
1886
1887unsigned int ProgramD3D::issueSerial()
1888{
1889 return mCurrentSerial++;
1890}
1891
Jamie Madill63805b42015-08-25 13:17:39 -04001892void ProgramD3D::initSemanticIndex()
1893{
1894 const gl::Shader *vertexShader = mData.getAttachedVertexShader();
1895 ASSERT(vertexShader != nullptr);
1896
1897 // Init semantic index
1898 for (const sh::Attribute &attribute : mData.getAttributes())
1899 {
1900 int attributeIndex = attribute.location;
1901 int index = vertexShader->getSemanticIndex(attribute.name);
1902 int regs = gl::VariableRegisterCount(attribute.type);
1903
1904 for (int reg = 0; reg < regs; ++reg)
1905 {
1906 mSemanticIndexes[attributeIndex + reg] = index + reg;
1907 }
1908 }
1909
1910 initAttributesByLayout();
1911}
1912
Jamie Madill437d2662014-12-05 14:23:35 -05001913void ProgramD3D::initAttributesByLayout()
1914{
1915 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
1916 {
1917 mAttributesByLayout[i] = i;
1918 }
1919
Jamie Madill63805b42015-08-25 13:17:39 -04001920 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
1921 AttributeSorter(mSemanticIndexes));
Jamie Madill437d2662014-12-05 14:23:35 -05001922}
1923
Jamie Madill334d6152015-10-22 14:00:28 -04001924void ProgramD3D::sortAttributesByLayout(
1925 const std::vector<TranslatedAttribute> &unsortedAttributes,
1926 int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
1927 const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
Jamie Madill437d2662014-12-05 14:23:35 -05001928{
Jamie Madill476682e2015-06-30 10:04:29 -04001929 for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
Jamie Madill437d2662014-12-05 14:23:35 -05001930 {
Jamie Madill334d6152015-10-22 14:00:28 -04001931 int oldIndex = mAttributesByLayout[attribIndex];
Jamie Madill63805b42015-08-25 13:17:39 -04001932 sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
Jamie Madill334d6152015-10-22 14:00:28 -04001933 sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
Jamie Madill437d2662014-12-05 14:23:35 -05001934 }
1935}
1936
Jamie Madill63805b42015-08-25 13:17:39 -04001937void ProgramD3D::updateCachedInputLayout(const gl::State &state)
Jamie Madilld3dfda22015-07-06 08:28:49 -04001938{
Jamie Madillbd136f92015-08-10 14:51:37 -04001939 mCachedInputLayout.clear();
Jamie Madilld3dfda22015-07-06 08:28:49 -04001940 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
Jamie Madillf8dd7b12015-08-05 13:50:08 -04001941
Dian Xianga4928832015-09-15 10:11:17 -07001942 for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask()))
Jamie Madilld3dfda22015-07-06 08:28:49 -04001943 {
Jamie Madill63805b42015-08-25 13:17:39 -04001944 int semanticIndex = mSemanticIndexes[attributeIndex];
Jamie Madilld3dfda22015-07-06 08:28:49 -04001945
1946 if (semanticIndex != -1)
1947 {
Jamie Madillbd136f92015-08-10 14:51:37 -04001948 if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
1949 {
1950 mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
1951 }
Jamie Madilld3dfda22015-07-06 08:28:49 -04001952 mCachedInputLayout[semanticIndex] =
1953 GetVertexFormatType(vertexAttributes[attributeIndex],
1954 state.getVertexAttribCurrentValue(attributeIndex).Type);
1955 }
1956 }
1957}
1958
Jamie Madillccdf74b2015-08-18 10:46:12 -04001959void ProgramD3D::gatherTransformFeedbackVaryings(
1960 const std::vector<gl::LinkedVarying> &linkedVaryings)
1961{
1962 // Gather the linked varyings that are used for transform feedback, they should all exist.
1963 mTransformFeedbackLinkedVaryings.clear();
1964 for (const std::string &tfVaryingName : mData.getTransformFeedbackVaryingNames())
1965 {
1966 for (const gl::LinkedVarying &linkedVarying : linkedVaryings)
1967 {
1968 if (tfVaryingName == linkedVarying.name)
1969 {
1970 mTransformFeedbackLinkedVaryings.push_back(linkedVarying);
1971 break;
1972 }
1973 }
1974 }
1975}
Jamie Madill62d31cb2015-09-11 13:25:51 -04001976
1977D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
1978{
1979 return mD3DUniforms[mData.getUniformLocations()[location].index];
1980}
Jamie Madill4a3c2342015-10-08 12:58:45 -04001981
1982bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
1983{
1984 std::string baseName = blockName;
1985 gl::ParseAndStripArrayIndex(&baseName);
1986
1987 auto sizeIter = mBlockDataSizes.find(baseName);
1988 if (sizeIter == mBlockDataSizes.end())
1989 {
1990 *sizeOut = 0;
1991 return false;
1992 }
1993
1994 *sizeOut = sizeIter->second;
1995 return true;
1996}
1997
1998bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
1999 sh::BlockMemberInfo *memberInfoOut) const
2000{
2001 auto infoIter = mBlockInfo.find(memberUniformName);
2002 if (infoIter == mBlockInfo.end())
2003 {
2004 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
2005 return false;
2006 }
2007
2008 *memberInfoOut = infoIter->second;
2009 return true;
2010}
Brandon Jonesc9610c52014-08-25 17:02:59 -07002011}