1 //
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 
9 #include "libANGLE/renderer/d3d/ProgramD3D.h"
10 
11 #include "common/bitset_utils.h"
12 #include "common/string_utils.h"
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Framebuffer.h"
16 #include "libANGLE/FramebufferAttachment.h"
17 #include "libANGLE/Program.h"
18 #include "libANGLE/ProgramLinkedResources.h"
19 #include "libANGLE/Uniform.h"
20 #include "libANGLE/VertexArray.h"
21 #include "libANGLE/features.h"
22 #include "libANGLE/queryconversions.h"
23 #include "libANGLE/renderer/ContextImpl.h"
24 #include "libANGLE/renderer/d3d/DynamicHLSL.h"
25 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
26 #include "libANGLE/renderer/d3d/RendererD3D.h"
27 #include "libANGLE/renderer/d3d/ShaderD3D.h"
28 #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
29 #include "libANGLE/renderer/d3d/VertexDataManager.h"
30 
31 using namespace angle;
32 
33 namespace rx
34 {
35 
36 namespace
37 {
38 
GetDefaultInputLayoutFromShader(const gl::Context * context,gl::Shader * vertexShader,gl::InputLayout * inputLayoutOut)39 void GetDefaultInputLayoutFromShader(const gl::Context *context,
40                                      gl::Shader *vertexShader,
41                                      gl::InputLayout *inputLayoutOut)
42 {
43     inputLayoutOut->clear();
44 
45     for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes(context))
46     {
47         if (shaderAttr.type != GL_NONE)
48         {
49             GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
50 
51             for (size_t rowIndex = 0;
52                  static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
53             {
54                 GLenum componentType = gl::VariableComponentType(transposedType);
55                 GLuint components    = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
56                 bool pureInt = (componentType != GL_FLOAT);
57                 gl::VertexFormatType defaultType =
58                     gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
59 
60                 inputLayoutOut->push_back(defaultType);
61             }
62         }
63     }
64 }
65 
GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> & shaderOutputVars,std::vector<GLenum> * outputLayoutOut)66 void GetDefaultOutputLayoutFromShader(
67     const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
68     std::vector<GLenum> *outputLayoutOut)
69 {
70     outputLayoutOut->clear();
71 
72     if (!shaderOutputVars.empty())
73     {
74         outputLayoutOut->push_back(GL_COLOR_ATTACHMENT0 +
75                                    static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
76     }
77 }
78 
79 template <typename T, int cols, int rows>
TransposeExpandMatrix(T * target,const GLfloat * value)80 bool TransposeExpandMatrix(T *target, const GLfloat *value)
81 {
82     constexpr int targetWidth  = 4;
83     constexpr int targetHeight = rows;
84     constexpr int srcWidth     = rows;
85     constexpr int srcHeight    = cols;
86 
87     constexpr int copyWidth  = std::min(targetHeight, srcWidth);
88     constexpr int copyHeight = std::min(targetWidth, srcHeight);
89 
90     T staging[targetWidth * targetHeight] = {0};
91 
92     for (int x = 0; x < copyWidth; x++)
93     {
94         for (int y = 0; y < copyHeight; y++)
95         {
96             staging[x * targetWidth + y] = static_cast<T>(value[y * srcWidth + x]);
97         }
98     }
99 
100     if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
101     {
102         return false;
103     }
104 
105     memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
106     return true;
107 }
108 
109 template <typename T, int cols, int rows>
ExpandMatrix(T * target,const GLfloat * value)110 bool ExpandMatrix(T *target, const GLfloat *value)
111 {
112     constexpr int targetWidth  = 4;
113     constexpr int targetHeight = rows;
114     constexpr int srcWidth = cols;
115     constexpr int srcHeight = rows;
116 
117     constexpr int copyWidth  = std::min(targetWidth, srcWidth);
118     constexpr int copyHeight = std::min(targetHeight, srcHeight);
119 
120     T staging[targetWidth * targetHeight] = {0};
121 
122     for (int y = 0; y < copyHeight; y++)
123     {
124         for (int x = 0; x < copyWidth; x++)
125         {
126             staging[y * targetWidth + x] = static_cast<T>(value[y * srcWidth + x]);
127         }
128     }
129 
130     if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
131     {
132         return false;
133     }
134 
135     memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
136     return true;
137 }
138 
GetGeometryShaderTypeFromDrawMode(GLenum drawMode)139 gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
140 {
141     switch (drawMode)
142     {
143         // Uses the point sprite geometry shader.
144         case GL_POINTS:
145             return gl::PRIMITIVE_POINTS;
146 
147         // All line drawing uses the same geometry shader.
148         case GL_LINES:
149         case GL_LINE_STRIP:
150         case GL_LINE_LOOP:
151             return gl::PRIMITIVE_LINES;
152 
153         // The triangle fan primitive is emulated with strips in D3D11.
154         case GL_TRIANGLES:
155         case GL_TRIANGLE_FAN:
156             return gl::PRIMITIVE_TRIANGLES;
157 
158         // Special case for triangle strips.
159         case GL_TRIANGLE_STRIP:
160             return gl::PRIMITIVE_TRIANGLE_STRIP;
161 
162         default:
163             UNREACHABLE();
164             return gl::PRIMITIVE_TYPE_MAX;
165     }
166 }
167 
FindFlatInterpolationVarying(const std::vector<sh::Varying> & varyings)168 bool FindFlatInterpolationVarying(const std::vector<sh::Varying> &varyings)
169 {
170     // Note: this assumes nested structs can only be packed with one interpolation.
171     for (const auto &varying : varyings)
172     {
173         if (varying.interpolation == sh::INTERPOLATION_FLAT)
174         {
175             return true;
176         }
177     }
178 
179     return false;
180 }
181 
182 // Helper method to de-tranpose a matrix uniform for an API query.
GetMatrixUniform(GLint columns,GLint rows,GLfloat * dataOut,const GLfloat * source)183 void GetMatrixUniform(GLint columns, GLint rows, GLfloat *dataOut, const GLfloat *source)
184 {
185     for (GLint col = 0; col < columns; ++col)
186     {
187         for (GLint row = 0; row < rows; ++row)
188         {
189             GLfloat *outptr      = dataOut + ((col * rows) + row);
190             const GLfloat *inptr = source + ((row * 4) + col);
191             *outptr              = *inptr;
192         }
193     }
194 }
195 
196 template <typename NonFloatT>
GetMatrixUniform(GLint columns,GLint rows,NonFloatT * dataOut,const NonFloatT * source)197 void GetMatrixUniform(GLint columns, GLint rows, NonFloatT *dataOut, const NonFloatT *source)
198 {
199     UNREACHABLE();
200 }
201 
202 class UniformBlockInfo final : angle::NonCopyable
203 {
204   public:
UniformBlockInfo()205     UniformBlockInfo() {}
206 
207     void getShaderBlockInfo(const gl::Context *context, gl::Shader *shader);
208 
209     bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut);
210     bool getBlockMemberInfo(const std::string &name,
211                             const std::string &mappedName,
212                             sh::BlockMemberInfo *infoOut);
213 
214   private:
215     size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock);
216 
217     std::map<std::string, size_t> mBlockSizes;
218     sh::BlockLayoutMap mBlockLayout;
219 };
220 
getShaderBlockInfo(const gl::Context * context,gl::Shader * shader)221 void UniformBlockInfo::getShaderBlockInfo(const gl::Context *context, gl::Shader *shader)
222 {
223     for (const sh::InterfaceBlock &interfaceBlock : shader->getUniformBlocks(context))
224     {
225         if (!interfaceBlock.staticUse && interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED)
226             continue;
227 
228         if (mBlockSizes.count(interfaceBlock.name) > 0)
229             continue;
230 
231         size_t dataSize                  = getBlockInfo(interfaceBlock);
232         mBlockSizes[interfaceBlock.name] = dataSize;
233     }
234 }
235 
getBlockInfo(const sh::InterfaceBlock & interfaceBlock)236 size_t UniformBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
237 {
238     ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
239 
240     // define member uniforms
241     sh::Std140BlockEncoder std140Encoder;
242     sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
243     sh::BlockLayoutEncoder *encoder = nullptr;
244 
245     if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
246     {
247         encoder = &std140Encoder;
248     }
249     else
250     {
251         encoder = &hlslEncoder;
252     }
253 
254     sh::GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
255                             interfaceBlock.isRowMajorLayout, &mBlockLayout);
256 
257     return encoder->getBlockSize();
258 }
259 
getBlockSize(const std::string & name,const std::string & mappedName,size_t * sizeOut)260 bool UniformBlockInfo::getBlockSize(const std::string &name,
261                                     const std::string &mappedName,
262                                     size_t *sizeOut)
263 {
264     size_t nameLengthWithoutArrayIndex;
265     gl::ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
266     std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
267     auto sizeIter        = mBlockSizes.find(baseName);
268     if (sizeIter == mBlockSizes.end())
269     {
270         *sizeOut = 0;
271         return false;
272     }
273 
274     *sizeOut = sizeIter->second;
275     return true;
276 };
277 
getBlockMemberInfo(const std::string & name,const std::string & mappedName,sh::BlockMemberInfo * infoOut)278 bool UniformBlockInfo::getBlockMemberInfo(const std::string &name,
279                                           const std::string &mappedName,
280                                           sh::BlockMemberInfo *infoOut)
281 {
282     auto infoIter = mBlockLayout.find(name);
283     if (infoIter == mBlockLayout.end())
284     {
285         *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
286         return false;
287     }
288 
289     *infoOut = infoIter->second;
290     return true;
291 };
292 
293 }  // anonymous namespace
294 
295 // D3DUniform Implementation
296 
D3DUniform(GLenum type,const std::string & nameIn,const std::vector<unsigned int> & arraySizesIn,bool defaultBlock)297 D3DUniform::D3DUniform(GLenum type,
298                        const std::string &nameIn,
299                        const std::vector<unsigned int> &arraySizesIn,
300                        bool defaultBlock)
301     : typeInfo(gl::GetUniformTypeInfo(type)),
302       name(nameIn),
303       arraySizes(arraySizesIn),
304       vsData(nullptr),
305       psData(nullptr),
306       csData(nullptr),
307       vsRegisterIndex(GL_INVALID_INDEX),
308       psRegisterIndex(GL_INVALID_INDEX),
309       csRegisterIndex(GL_INVALID_INDEX),
310       registerCount(0),
311       registerElement(0)
312 {
313     // We use data storage for default block uniforms to cache values that are sent to D3D during
314     // rendering
315     // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
316     if (defaultBlock)
317     {
318         // Use the row count as register count, will work for non-square matrices.
319         registerCount = typeInfo.rowCount * getArraySizeProduct();
320     }
321 }
322 
~D3DUniform()323 D3DUniform::~D3DUniform()
324 {
325 }
326 
getArraySizeProduct() const327 unsigned int D3DUniform::getArraySizeProduct() const
328 {
329     return gl::ArraySizeProduct(arraySizes);
330 }
331 
getDataPtrToElement(size_t elementIndex) const332 const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
333 {
334     ASSERT((!isArray() && elementIndex == 0) ||
335            (isArray() && elementIndex < getArraySizeProduct()));
336 
337     if (isSampler())
338     {
339         return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
340     }
341 
342     return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
343 }
344 
isSampler() const345 bool D3DUniform::isSampler() const
346 {
347     return typeInfo.isSampler;
348 }
349 
isReferencedByVertexShader() const350 bool D3DUniform::isReferencedByVertexShader() const
351 {
352     return vsRegisterIndex != GL_INVALID_INDEX;
353 }
354 
isReferencedByFragmentShader() const355 bool D3DUniform::isReferencedByFragmentShader() const
356 {
357     return psRegisterIndex != GL_INVALID_INDEX;
358 }
359 
isReferencedByComputeShader() const360 bool D3DUniform::isReferencedByComputeShader() const
361 {
362     return csRegisterIndex != GL_INVALID_INDEX;
363 }
364 
firstNonNullData() const365 const uint8_t *D3DUniform::firstNonNullData() const
366 {
367     ASSERT(vsData || psData || csData || !mSamplerData.empty());
368 
369     if (!mSamplerData.empty())
370     {
371         return reinterpret_cast<const uint8_t *>(mSamplerData.data());
372     }
373 
374     return vsData ? vsData : (psData ? psData : csData);
375 }
376 
377 // D3DVarying Implementation
378 
D3DVarying()379 D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0)
380 {
381 }
382 
D3DVarying(const std::string & semanticNameIn,unsigned int semanticIndexIn,unsigned int componentCountIn,unsigned int outputSlotIn)383 D3DVarying::D3DVarying(const std::string &semanticNameIn,
384                        unsigned int semanticIndexIn,
385                        unsigned int componentCountIn,
386                        unsigned int outputSlotIn)
387     : semanticName(semanticNameIn),
388       semanticIndex(semanticIndexIn),
389       componentCount(componentCountIn),
390       outputSlot(outputSlotIn)
391 {
392 }
393 
394 // ProgramD3DMetadata Implementation
395 
ProgramD3DMetadata(RendererD3D * renderer,const ShaderD3D * vertexShader,const ShaderD3D * fragmentShader)396 ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
397                                        const ShaderD3D *vertexShader,
398                                        const ShaderD3D *fragmentShader)
399     : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
400       mShaderModelSuffix(renderer->getShaderModelSuffix()),
401       mUsesInstancedPointSpriteEmulation(
402           renderer->getWorkarounds().useInstancedPointSpriteEmulation),
403       mUsesViewScale(renderer->presentPathFastEnabled()),
404       mHasANGLEMultiviewEnabled(vertexShader->hasANGLEMultiviewEnabled()),
405       mUsesViewID(fragmentShader->usesViewID()),
406       mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
407       mVertexShader(vertexShader),
408       mFragmentShader(fragmentShader)
409 {
410 }
411 
getRendererMajorShaderModel() const412 int ProgramD3DMetadata::getRendererMajorShaderModel() const
413 {
414     return mRendererMajorShaderModel;
415 }
416 
usesBroadcast(const gl::ContextState & data) const417 bool ProgramD3DMetadata::usesBroadcast(const gl::ContextState &data) const
418 {
419     return (mFragmentShader->usesFragColor() && mFragmentShader->usesMultipleRenderTargets() &&
420             data.getClientMajorVersion() < 3);
421 }
422 
usesFragDepth() const423 bool ProgramD3DMetadata::usesFragDepth() const
424 {
425     return mFragmentShader->usesFragDepth();
426 }
427 
usesPointCoord() const428 bool ProgramD3DMetadata::usesPointCoord() const
429 {
430     return mFragmentShader->usesPointCoord();
431 }
432 
usesFragCoord() const433 bool ProgramD3DMetadata::usesFragCoord() const
434 {
435     return mFragmentShader->usesFragCoord();
436 }
437 
usesPointSize() const438 bool ProgramD3DMetadata::usesPointSize() const
439 {
440     return mVertexShader->usesPointSize();
441 }
442 
usesInsertedPointCoordValue() const443 bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
444 {
445     return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
446            mRendererMajorShaderModel >= 4;
447 }
448 
usesViewScale() const449 bool ProgramD3DMetadata::usesViewScale() const
450 {
451     return mUsesViewScale;
452 }
453 
hasANGLEMultiviewEnabled() const454 bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
455 {
456     return mHasANGLEMultiviewEnabled;
457 }
458 
usesViewID() const459 bool ProgramD3DMetadata::usesViewID() const
460 {
461     return mUsesViewID;
462 }
463 
canSelectViewInVertexShader() const464 bool ProgramD3DMetadata::canSelectViewInVertexShader() const
465 {
466     return mCanSelectViewInVertexShader;
467 }
468 
addsPointCoordToVertexShader() const469 bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
470 {
471     // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
472     // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
473     // Even with a geometry shader, the app can render triangles or lines and reference
474     // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
475     // simplicity, we always add this to the vertex shader when the fragment shader
476     // references gl_PointCoord, even if we could skip it in the geometry shader.
477     return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
478            usesInsertedPointCoordValue();
479 }
480 
usesTransformFeedbackGLPosition() const481 bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
482 {
483     // gl_Position only needs to be outputted from the vertex shader if transform feedback is
484     // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
485     // the vertex shader in this case. This saves us 1 output vector.
486     return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
487 }
488 
usesSystemValuePointSize() const489 bool ProgramD3DMetadata::usesSystemValuePointSize() const
490 {
491     return !mUsesInstancedPointSpriteEmulation && usesPointSize();
492 }
493 
usesMultipleFragmentOuts() const494 bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
495 {
496     return mFragmentShader->usesMultipleRenderTargets();
497 }
498 
getMajorShaderVersion() const499 GLint ProgramD3DMetadata::getMajorShaderVersion() const
500 {
501     return mVertexShader->getData().getShaderVersion();
502 }
503 
getFragmentShader() const504 const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
505 {
506     return mFragmentShader;
507 }
508 
509 // ProgramD3D Implementation
510 
VertexExecutable(const gl::InputLayout & inputLayout,const Signature & signature,ShaderExecutableD3D * shaderExecutable)511 ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
512                                                const Signature &signature,
513                                                ShaderExecutableD3D *shaderExecutable)
514     : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
515 {
516 }
517 
~VertexExecutable()518 ProgramD3D::VertexExecutable::~VertexExecutable()
519 {
520     SafeDelete(mShaderExecutable);
521 }
522 
523 // static
GetAttribType(GLenum type)524 ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
525     GLenum type)
526 {
527     switch (type)
528     {
529         case GL_INT:
530             return HLSLAttribType::SIGNED_INT;
531         case GL_UNSIGNED_INT:
532             return HLSLAttribType::UNSIGNED_INT;
533         case GL_SIGNED_NORMALIZED:
534         case GL_UNSIGNED_NORMALIZED:
535         case GL_FLOAT:
536             return HLSLAttribType::FLOAT;
537         default:
538             UNREACHABLE();
539             return HLSLAttribType::FLOAT;
540     }
541 }
542 
543 // static
getSignature(RendererD3D * renderer,const gl::InputLayout & inputLayout,Signature * signatureOut)544 void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
545                                                 const gl::InputLayout &inputLayout,
546                                                 Signature *signatureOut)
547 {
548     signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
549 
550     for (size_t index = 0; index < inputLayout.size(); ++index)
551     {
552         gl::VertexFormatType vertexFormatType = inputLayout[index];
553         if (vertexFormatType == gl::VERTEX_FORMAT_INVALID)
554             continue;
555 
556         VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType);
557         if ((conversionType & VERTEX_CONVERT_GPU) == 0)
558             continue;
559 
560         GLenum componentType = renderer->getVertexComponentType(vertexFormatType);
561         (*signatureOut)[index] = GetAttribType(componentType);
562     }
563 }
564 
matchesSignature(const Signature & signature) const565 bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
566 {
567     size_t limit = std::max(mSignature.size(), signature.size());
568     for (size_t index = 0; index < limit; ++index)
569     {
570         // treat undefined indexes as FLOAT
571         auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
572         auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
573         if (a != b)
574             return false;
575     }
576 
577     return true;
578 }
579 
PixelExecutable(const std::vector<GLenum> & outputSignature,ShaderExecutableD3D * shaderExecutable)580 ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
581                                              ShaderExecutableD3D *shaderExecutable)
582     : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
583 {
584 }
585 
~PixelExecutable()586 ProgramD3D::PixelExecutable::~PixelExecutable()
587 {
588     SafeDelete(mShaderExecutable);
589 }
590 
Sampler()591 ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
592 {
593 }
594 
595 unsigned int ProgramD3D::mCurrentSerial = 1;
596 
ProgramD3D(const gl::ProgramState & state,RendererD3D * renderer)597 ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
598     : ProgramImpl(state),
599       mRenderer(renderer),
600       mDynamicHLSL(nullptr),
601       mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX),
602       mComputeExecutable(nullptr),
603       mUsesPointSize(false),
604       mUsesFlatInterpolation(false),
605       mVertexUniformStorage(nullptr),
606       mFragmentUniformStorage(nullptr),
607       mComputeUniformStorage(nullptr),
608       mUsedVertexSamplerRange(0),
609       mUsedPixelSamplerRange(0),
610       mUsedComputeSamplerRange(0),
611       mDirtySamplerMapping(true),
612       mSerial(issueSerial()),
613       mVertexUniformsDirty(true),
614       mFragmentUniformsDirty(true),
615       mComputeUniformsDirty(true)
616 {
617     mDynamicHLSL = new DynamicHLSL(renderer);
618 }
619 
~ProgramD3D()620 ProgramD3D::~ProgramD3D()
621 {
622     reset();
623     SafeDelete(mDynamicHLSL);
624 }
625 
usesPointSpriteEmulation() const626 bool ProgramD3D::usesPointSpriteEmulation() const
627 {
628     return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
629 }
630 
usesGeometryShaderForPointSpriteEmulation() const631 bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
632 {
633     return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
634 }
635 
usesGeometryShader(GLenum drawMode) const636 bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
637 {
638     if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
639     {
640         return true;
641     }
642     if (drawMode != GL_POINTS)
643     {
644         return mUsesFlatInterpolation;
645     }
646     return usesGeometryShaderForPointSpriteEmulation();
647 }
648 
usesInstancedPointSpriteEmulation() const649 bool ProgramD3D::usesInstancedPointSpriteEmulation() const
650 {
651     return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
652 }
653 
getSamplerMapping(gl::SamplerType type,unsigned int samplerIndex,const gl::Caps & caps) const654 GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
655                                     unsigned int samplerIndex,
656                                     const gl::Caps &caps) const
657 {
658     GLint logicalTextureUnit = -1;
659 
660     switch (type)
661     {
662         case gl::SAMPLER_PIXEL:
663             ASSERT(samplerIndex < caps.maxTextureImageUnits);
664             if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
665             {
666                 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
667             }
668             break;
669         case gl::SAMPLER_VERTEX:
670             ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
671             if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
672             {
673                 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
674             }
675             break;
676         case gl::SAMPLER_COMPUTE:
677             ASSERT(samplerIndex < caps.maxComputeTextureImageUnits);
678             if (samplerIndex < mSamplersCS.size() && mSamplersCS[samplerIndex].active)
679             {
680                 logicalTextureUnit = mSamplersCS[samplerIndex].logicalTextureUnit;
681             }
682             break;
683         default:
684             UNREACHABLE();
685     }
686 
687     if (logicalTextureUnit >= 0 &&
688         logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
689     {
690         return logicalTextureUnit;
691     }
692 
693     return -1;
694 }
695 
696 // Returns the texture type for a given Direct3D 9 sampler type and
697 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
getSamplerTextureType(gl::SamplerType type,unsigned int samplerIndex) const698 GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
699 {
700     switch (type)
701     {
702         case gl::SAMPLER_PIXEL:
703             ASSERT(samplerIndex < mSamplersPS.size());
704             ASSERT(mSamplersPS[samplerIndex].active);
705             return mSamplersPS[samplerIndex].textureType;
706         case gl::SAMPLER_VERTEX:
707             ASSERT(samplerIndex < mSamplersVS.size());
708             ASSERT(mSamplersVS[samplerIndex].active);
709             return mSamplersVS[samplerIndex].textureType;
710         case gl::SAMPLER_COMPUTE:
711             ASSERT(samplerIndex < mSamplersCS.size());
712             ASSERT(mSamplersCS[samplerIndex].active);
713             return mSamplersCS[samplerIndex].textureType;
714         default:
715             UNREACHABLE();
716     }
717 
718     return GL_TEXTURE_2D;
719 }
720 
getUsedSamplerRange(gl::SamplerType type) const721 GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
722 {
723     switch (type)
724     {
725         case gl::SAMPLER_PIXEL:
726             return mUsedPixelSamplerRange;
727         case gl::SAMPLER_VERTEX:
728             return mUsedVertexSamplerRange;
729         case gl::SAMPLER_COMPUTE:
730             return mUsedComputeSamplerRange;
731         default:
732             UNREACHABLE();
733             return 0u;
734     }
735 }
736 
updateSamplerMapping()737 ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping()
738 {
739     if (!mDirtySamplerMapping)
740     {
741         return SamplerMapping::WasClean;
742     }
743 
744     mDirtySamplerMapping = false;
745 
746     // Retrieve sampler uniform values
747     for (const D3DUniform *d3dUniform : mD3DUniforms)
748     {
749         if (!d3dUniform->isSampler())
750             continue;
751 
752         int count = d3dUniform->getArraySizeProduct();
753 
754         if (d3dUniform->isReferencedByFragmentShader())
755         {
756             unsigned int firstIndex = d3dUniform->psRegisterIndex;
757 
758             for (int i = 0; i < count; i++)
759             {
760                 unsigned int samplerIndex = firstIndex + i;
761 
762                 if (samplerIndex < mSamplersPS.size())
763                 {
764                     ASSERT(mSamplersPS[samplerIndex].active);
765                     mSamplersPS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
766                 }
767             }
768         }
769 
770         if (d3dUniform->isReferencedByVertexShader())
771         {
772             unsigned int firstIndex = d3dUniform->vsRegisterIndex;
773 
774             for (int i = 0; i < count; i++)
775             {
776                 unsigned int samplerIndex = firstIndex + i;
777 
778                 if (samplerIndex < mSamplersVS.size())
779                 {
780                     ASSERT(mSamplersVS[samplerIndex].active);
781                     mSamplersVS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
782                 }
783             }
784         }
785 
786         if (d3dUniform->isReferencedByComputeShader())
787         {
788             unsigned int firstIndex = d3dUniform->csRegisterIndex;
789 
790             for (int i = 0; i < count; i++)
791             {
792                 unsigned int samplerIndex = firstIndex + i;
793 
794                 if (samplerIndex < mSamplersCS.size())
795                 {
796                     ASSERT(mSamplersCS[samplerIndex].active);
797                     mSamplersCS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
798                 }
799             }
800         }
801     }
802 
803     return SamplerMapping::WasDirty;
804 }
805 
load(const gl::Context * context,gl::InfoLog & infoLog,gl::BinaryInputStream * stream)806 gl::LinkResult ProgramD3D::load(const gl::Context *context,
807                                 gl::InfoLog &infoLog,
808                                 gl::BinaryInputStream *stream)
809 {
810     // TODO(jmadill): Use Renderer from contextImpl.
811 
812     reset();
813 
814     DeviceIdentifier binaryDeviceIdentifier = {0};
815     stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
816                       sizeof(DeviceIdentifier));
817 
818     DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
819     if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
820     {
821         infoLog << "Invalid program binary, device configuration has changed.";
822         return false;
823     }
824 
825     int compileFlags = stream->readInt<int>();
826     if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
827     {
828         infoLog << "Mismatched compilation flags.";
829         return false;
830     }
831 
832     for (int &index : mAttribLocationToD3DSemantic)
833     {
834         stream->readInt(&index);
835     }
836 
837     const unsigned int psSamplerCount = stream->readInt<unsigned int>();
838     for (unsigned int i = 0; i < psSamplerCount; ++i)
839     {
840         Sampler sampler;
841         stream->readBool(&sampler.active);
842         stream->readInt(&sampler.logicalTextureUnit);
843         stream->readInt(&sampler.textureType);
844         mSamplersPS.push_back(sampler);
845     }
846     const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
847     for (unsigned int i = 0; i < vsSamplerCount; ++i)
848     {
849         Sampler sampler;
850         stream->readBool(&sampler.active);
851         stream->readInt(&sampler.logicalTextureUnit);
852         stream->readInt(&sampler.textureType);
853         mSamplersVS.push_back(sampler);
854     }
855 
856     const unsigned int csSamplerCount = stream->readInt<unsigned int>();
857     for (unsigned int i = 0; i < csSamplerCount; ++i)
858     {
859         Sampler sampler;
860         stream->readBool(&sampler.active);
861         stream->readInt(&sampler.logicalTextureUnit);
862         stream->readInt(&sampler.textureType);
863         mSamplersCS.push_back(sampler);
864     }
865 
866     stream->readInt(&mUsedVertexSamplerRange);
867     stream->readInt(&mUsedPixelSamplerRange);
868     stream->readInt(&mUsedComputeSamplerRange);
869 
870     const unsigned int uniformCount = stream->readInt<unsigned int>();
871     if (stream->error())
872     {
873         infoLog << "Invalid program binary.";
874         return false;
875     }
876 
877     const auto &linkedUniforms = mState.getUniforms();
878     ASSERT(mD3DUniforms.empty());
879     for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
880     {
881         const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
882 
883         D3DUniform *d3dUniform =
884             new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySizes,
885                            linkedUniform.isInDefaultBlock());
886         stream->readInt(&d3dUniform->psRegisterIndex);
887         stream->readInt(&d3dUniform->vsRegisterIndex);
888         stream->readInt(&d3dUniform->csRegisterIndex);
889         stream->readInt(&d3dUniform->registerCount);
890         stream->readInt(&d3dUniform->registerElement);
891 
892         mD3DUniforms.push_back(d3dUniform);
893     }
894 
895     const unsigned int blockCount = stream->readInt<unsigned int>();
896     if (stream->error())
897     {
898         infoLog << "Invalid program binary.";
899         return false;
900     }
901 
902     ASSERT(mD3DUniformBlocks.empty());
903     for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
904     {
905         D3DUniformBlock uniformBlock;
906         stream->readInt(&uniformBlock.psRegisterIndex);
907         stream->readInt(&uniformBlock.vsRegisterIndex);
908         stream->readInt(&uniformBlock.csRegisterIndex);
909         mD3DUniformBlocks.push_back(uniformBlock);
910     }
911 
912     const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
913     mStreamOutVaryings.resize(streamOutVaryingCount);
914     for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
915     {
916         D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
917 
918         stream->readString(&varying->semanticName);
919         stream->readInt(&varying->semanticIndex);
920         stream->readInt(&varying->componentCount);
921         stream->readInt(&varying->outputSlot);
922     }
923 
924     stream->readString(&mVertexHLSL);
925     stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
926                       sizeof(angle::CompilerWorkaroundsD3D));
927     stream->readString(&mPixelHLSL);
928     stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
929                       sizeof(angle::CompilerWorkaroundsD3D));
930     stream->readBool(&mUsesFragDepth);
931     stream->readBool(&mHasANGLEMultiviewEnabled);
932     stream->readBool(&mUsesViewID);
933     stream->readBool(&mUsesPointSize);
934     stream->readBool(&mUsesFlatInterpolation);
935 
936     const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
937     mPixelShaderKey.resize(pixelShaderKeySize);
938     for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
939          pixelShaderKeyIndex++)
940     {
941         stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
942         stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
943         stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
944         stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
945     }
946 
947     stream->readString(&mGeometryShaderPreamble);
948 
949     const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
950 
951     bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
952 
953     const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
954     for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
955          vertexShaderIndex++)
956     {
957         size_t inputLayoutSize = stream->readInt<size_t>();
958         gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID);
959 
960         for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
961         {
962             inputLayout[inputIndex] = stream->readInt<gl::VertexFormatType>();
963         }
964 
965         unsigned int vertexShaderSize             = stream->readInt<unsigned int>();
966         const unsigned char *vertexShaderFunction = binary + stream->offset();
967 
968         ShaderExecutableD3D *shaderExecutable = nullptr;
969 
970         ANGLE_TRY(mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
971                                             gl::SHADER_VERTEX, mStreamOutVaryings, separateAttribs,
972                                             &shaderExecutable));
973 
974         if (!shaderExecutable)
975         {
976             infoLog << "Could not create vertex shader.";
977             return false;
978         }
979 
980         // generated converted input layout
981         VertexExecutable::Signature signature;
982         VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
983 
984         // add new binary
985         mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
986             new VertexExecutable(inputLayout, signature, shaderExecutable)));
987 
988         stream->skip(vertexShaderSize);
989     }
990 
991     const size_t pixelShaderCount = stream->readInt<unsigned int>();
992     for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
993     {
994         const size_t outputCount = stream->readInt<unsigned int>();
995         std::vector<GLenum> outputs(outputCount);
996         for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
997         {
998             stream->readInt(&outputs[outputIndex]);
999         }
1000 
1001         const size_t pixelShaderSize             = stream->readInt<unsigned int>();
1002         const unsigned char *pixelShaderFunction = binary + stream->offset();
1003         ShaderExecutableD3D *shaderExecutable    = nullptr;
1004 
1005         ANGLE_TRY(mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
1006                                             gl::SHADER_FRAGMENT, mStreamOutVaryings,
1007                                             separateAttribs, &shaderExecutable));
1008 
1009         if (!shaderExecutable)
1010         {
1011             infoLog << "Could not create pixel shader.";
1012             return false;
1013         }
1014 
1015         // add new binary
1016         mPixelExecutables.push_back(
1017             std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
1018 
1019         stream->skip(pixelShaderSize);
1020     }
1021 
1022     for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
1023          ++geometryExeIndex)
1024     {
1025         unsigned int geometryShaderSize = stream->readInt<unsigned int>();
1026         if (geometryShaderSize == 0)
1027         {
1028             continue;
1029         }
1030 
1031         const unsigned char *geometryShaderFunction = binary + stream->offset();
1032 
1033         ShaderExecutableD3D *geometryExecutable = nullptr;
1034         ANGLE_TRY(mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize,
1035                                             gl::SHADER_GEOMETRY, mStreamOutVaryings,
1036                                             separateAttribs, &geometryExecutable));
1037 
1038         if (!geometryExecutable)
1039         {
1040             infoLog << "Could not create geometry shader.";
1041             return false;
1042         }
1043 
1044         mGeometryExecutables[geometryExeIndex].reset(geometryExecutable);
1045 
1046         stream->skip(geometryShaderSize);
1047     }
1048 
1049     unsigned int computeShaderSize = stream->readInt<unsigned int>();
1050     if (computeShaderSize > 0)
1051     {
1052         const unsigned char *computeShaderFunction = binary + stream->offset();
1053 
1054         ShaderExecutableD3D *computeExecutable = nullptr;
1055         ANGLE_TRY(mRenderer->loadExecutable(computeShaderFunction, computeShaderSize,
1056                                             gl::SHADER_COMPUTE, std::vector<D3DVarying>(), false,
1057                                             &computeExecutable));
1058 
1059         if (!computeExecutable)
1060         {
1061             infoLog << "Could not create compute shader.";
1062             return false;
1063         }
1064 
1065         mComputeExecutable.reset(computeExecutable);
1066     }
1067 
1068     initializeUniformStorage();
1069 
1070     return true;
1071 }
1072 
save(const gl::Context * context,gl::BinaryOutputStream * stream)1073 void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream)
1074 {
1075     // Output the DeviceIdentifier before we output any shader code
1076     // When we load the binary again later, we can validate the device identifier before trying to
1077     // compile any HLSL
1078     DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
1079     stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
1080                        sizeof(DeviceIdentifier));
1081 
1082     stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
1083 
1084     for (int d3dSemantic : mAttribLocationToD3DSemantic)
1085     {
1086         stream->writeInt(d3dSemantic);
1087     }
1088 
1089     stream->writeInt(mSamplersPS.size());
1090     for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
1091     {
1092         stream->writeInt(mSamplersPS[i].active);
1093         stream->writeInt(mSamplersPS[i].logicalTextureUnit);
1094         stream->writeInt(mSamplersPS[i].textureType);
1095     }
1096 
1097     stream->writeInt(mSamplersVS.size());
1098     for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
1099     {
1100         stream->writeInt(mSamplersVS[i].active);
1101         stream->writeInt(mSamplersVS[i].logicalTextureUnit);
1102         stream->writeInt(mSamplersVS[i].textureType);
1103     }
1104 
1105     stream->writeInt(mSamplersCS.size());
1106     for (unsigned int i = 0; i < mSamplersCS.size(); ++i)
1107     {
1108         stream->writeInt(mSamplersCS[i].active);
1109         stream->writeInt(mSamplersCS[i].logicalTextureUnit);
1110         stream->writeInt(mSamplersCS[i].textureType);
1111     }
1112 
1113     stream->writeInt(mUsedVertexSamplerRange);
1114     stream->writeInt(mUsedPixelSamplerRange);
1115     stream->writeInt(mUsedComputeSamplerRange);
1116 
1117     stream->writeInt(mD3DUniforms.size());
1118     for (const D3DUniform *uniform : mD3DUniforms)
1119     {
1120         // Type, name and arraySize are redundant, so aren't stored in the binary.
1121         stream->writeIntOrNegOne(uniform->psRegisterIndex);
1122         stream->writeIntOrNegOne(uniform->vsRegisterIndex);
1123         stream->writeIntOrNegOne(uniform->csRegisterIndex);
1124         stream->writeInt(uniform->registerCount);
1125         stream->writeInt(uniform->registerElement);
1126     }
1127 
1128     stream->writeInt(mD3DUniformBlocks.size());
1129     for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
1130     {
1131         stream->writeIntOrNegOne(uniformBlock.psRegisterIndex);
1132         stream->writeIntOrNegOne(uniformBlock.vsRegisterIndex);
1133         stream->writeIntOrNegOne(uniformBlock.csRegisterIndex);
1134     }
1135 
1136     stream->writeInt(mStreamOutVaryings.size());
1137     for (const auto &varying : mStreamOutVaryings)
1138     {
1139         stream->writeString(varying.semanticName);
1140         stream->writeInt(varying.semanticIndex);
1141         stream->writeInt(varying.componentCount);
1142         stream->writeInt(varying.outputSlot);
1143     }
1144 
1145     stream->writeString(mVertexHLSL);
1146     stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
1147                        sizeof(angle::CompilerWorkaroundsD3D));
1148     stream->writeString(mPixelHLSL);
1149     stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
1150                        sizeof(angle::CompilerWorkaroundsD3D));
1151     stream->writeInt(mUsesFragDepth);
1152     stream->writeInt(mHasANGLEMultiviewEnabled);
1153     stream->writeInt(mUsesViewID);
1154     stream->writeInt(mUsesPointSize);
1155     stream->writeInt(mUsesFlatInterpolation);
1156 
1157     const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
1158     stream->writeInt(pixelShaderKey.size());
1159     for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
1160          pixelShaderKeyIndex++)
1161     {
1162         const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
1163         stream->writeInt(variable.type);
1164         stream->writeString(variable.name);
1165         stream->writeString(variable.source);
1166         stream->writeInt(variable.outputIndex);
1167     }
1168 
1169     stream->writeString(mGeometryShaderPreamble);
1170 
1171     stream->writeInt(mVertexExecutables.size());
1172     for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
1173          vertexExecutableIndex++)
1174     {
1175         VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
1176 
1177         const auto &inputLayout = vertexExecutable->inputs();
1178         stream->writeInt(inputLayout.size());
1179 
1180         for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
1181         {
1182             stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex]));
1183         }
1184 
1185         size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1186         stream->writeInt(vertexShaderSize);
1187 
1188         const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
1189         stream->writeBytes(vertexBlob, vertexShaderSize);
1190     }
1191 
1192     stream->writeInt(mPixelExecutables.size());
1193     for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
1194          pixelExecutableIndex++)
1195     {
1196         PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
1197 
1198         const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
1199         stream->writeInt(outputs.size());
1200         for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1201         {
1202             stream->writeInt(outputs[outputIndex]);
1203         }
1204 
1205         size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1206         stream->writeInt(pixelShaderSize);
1207 
1208         const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
1209         stream->writeBytes(pixelBlob, pixelShaderSize);
1210     }
1211 
1212     for (auto const &geometryExecutable : mGeometryExecutables)
1213     {
1214         if (!geometryExecutable)
1215         {
1216             stream->writeInt(0);
1217             continue;
1218         }
1219 
1220         size_t geometryShaderSize = geometryExecutable->getLength();
1221         stream->writeInt(geometryShaderSize);
1222         stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
1223     }
1224 
1225     if (mComputeExecutable)
1226     {
1227         size_t computeShaderSize = mComputeExecutable->getLength();
1228         stream->writeInt(computeShaderSize);
1229         stream->writeBytes(mComputeExecutable->getFunction(), computeShaderSize);
1230     }
1231     else
1232     {
1233         stream->writeInt(0);
1234     }
1235 }
1236 
setBinaryRetrievableHint(bool)1237 void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
1238 {
1239 }
1240 
setSeparable(bool)1241 void ProgramD3D::setSeparable(bool /* separable */)
1242 {
1243 }
1244 
getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1245 gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable,
1246                                                               gl::InfoLog *infoLog)
1247 {
1248     if (mCachedPixelExecutableIndex.valid())
1249     {
1250         *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
1251         return gl::NoError();
1252     }
1253 
1254     std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
1255         mPixelHLSL, mPixelShaderKey, mUsesFragDepth, mPixelShaderOutputLayoutCache);
1256 
1257     // Generate new pixel executable
1258     ShaderExecutableD3D *pixelExecutable = nullptr;
1259 
1260     gl::InfoLog tempInfoLog;
1261     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1262 
1263     ANGLE_TRY(mRenderer->compileToExecutable(
1264         *currentInfoLog, finalPixelHLSL, gl::SHADER_FRAGMENT, mStreamOutVaryings,
1265         (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
1266         &pixelExecutable));
1267 
1268     if (pixelExecutable)
1269     {
1270         mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
1271             new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
1272         mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
1273     }
1274     else if (!infoLog)
1275     {
1276         ERR() << "Error compiling dynamic pixel executable:" << std::endl
1277               << tempInfoLog.str() << std::endl;
1278     }
1279 
1280     *outExecutable = pixelExecutable;
1281     return gl::NoError();
1282 }
1283 
getVertexExecutableForCachedInputLayout(ShaderExecutableD3D ** outExectuable,gl::InfoLog * infoLog)1284 gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
1285                                                               gl::InfoLog *infoLog)
1286 {
1287     if (mCachedVertexExecutableIndex.valid())
1288     {
1289         *outExectuable =
1290             mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
1291         return gl::NoError();
1292     }
1293 
1294     // Generate new dynamic layout with attribute conversions
1295     std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1296         mVertexHLSL, mCachedInputLayout, mState.getAttributes());
1297 
1298     // Generate new vertex executable
1299     ShaderExecutableD3D *vertexExecutable = nullptr;
1300 
1301     gl::InfoLog tempInfoLog;
1302     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1303 
1304     ANGLE_TRY(mRenderer->compileToExecutable(
1305         *currentInfoLog, finalVertexHLSL, gl::SHADER_VERTEX, mStreamOutVaryings,
1306         (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
1307         &vertexExecutable));
1308 
1309     if (vertexExecutable)
1310     {
1311         mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
1312             new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
1313         mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
1314     }
1315     else if (!infoLog)
1316     {
1317         ERR() << "Error compiling dynamic vertex executable:" << std::endl
1318               << tempInfoLog.str() << std::endl;
1319     }
1320 
1321     *outExectuable = vertexExecutable;
1322     return gl::NoError();
1323 }
1324 
getGeometryExecutableForPrimitiveType(const gl::Context * context,GLenum drawMode,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1325 gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Context *context,
1326                                                             GLenum drawMode,
1327                                                             ShaderExecutableD3D **outExecutable,
1328                                                             gl::InfoLog *infoLog)
1329 {
1330     if (outExecutable)
1331     {
1332         *outExecutable = nullptr;
1333     }
1334 
1335     // Return a null shader if the current rendering doesn't use a geometry shader
1336     if (!usesGeometryShader(drawMode))
1337     {
1338         return gl::NoError();
1339     }
1340 
1341     gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1342 
1343     if (mGeometryExecutables[geometryShaderType])
1344     {
1345         if (outExecutable)
1346         {
1347             *outExecutable = mGeometryExecutables[geometryShaderType].get();
1348         }
1349         return gl::NoError();
1350     }
1351 
1352     std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
1353         context, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
1354         mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
1355         usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
1356 
1357     gl::InfoLog tempInfoLog;
1358     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1359 
1360     ShaderExecutableD3D *geometryExecutable = nullptr;
1361     gl::Error error                         = mRenderer->compileToExecutable(
1362         *currentInfoLog, geometryHLSL, gl::SHADER_GEOMETRY, mStreamOutVaryings,
1363         (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1364         angle::CompilerWorkaroundsD3D(), &geometryExecutable);
1365 
1366     if (!infoLog && error.isError())
1367     {
1368         ERR() << "Error compiling dynamic geometry executable:" << std::endl
1369               << tempInfoLog.str() << std::endl;
1370     }
1371 
1372     if (geometryExecutable != nullptr)
1373     {
1374         mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
1375     }
1376 
1377     if (outExecutable)
1378     {
1379         *outExecutable = mGeometryExecutables[geometryShaderType].get();
1380     }
1381     return error;
1382 }
1383 
1384 class ProgramD3D::GetExecutableTask : public Closure
1385 {
1386   public:
GetExecutableTask(ProgramD3D * program)1387     GetExecutableTask(ProgramD3D *program)
1388         : mProgram(program), mError(gl::NoError()), mInfoLog(), mResult(nullptr)
1389     {
1390     }
1391 
1392     virtual gl::Error run() = 0;
1393 
operator ()()1394     void operator()() override { mError = run(); }
1395 
getError() const1396     const gl::Error &getError() const { return mError; }
getInfoLog() const1397     const gl::InfoLog &getInfoLog() const { return mInfoLog; }
getResult()1398     ShaderExecutableD3D *getResult() { return mResult; }
1399 
1400   protected:
1401     ProgramD3D *mProgram;
1402     gl::Error mError;
1403     gl::InfoLog mInfoLog;
1404     ShaderExecutableD3D *mResult;
1405 };
1406 
1407 class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
1408 {
1409   public:
GetVertexExecutableTask(ProgramD3D * program,const gl::Context * context)1410     GetVertexExecutableTask(ProgramD3D *program, const gl::Context *context)
1411         : GetExecutableTask(program), mContext(context)
1412     {
1413     }
run()1414     gl::Error run() override
1415     {
1416         mProgram->updateCachedInputLayoutFromShader(mContext);
1417 
1418         ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(&mResult, &mInfoLog));
1419 
1420         return gl::NoError();
1421     }
1422 
1423   private:
1424     const gl::Context *mContext;
1425 };
1426 
updateCachedInputLayoutFromShader(const gl::Context * context)1427 void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context)
1428 {
1429     GetDefaultInputLayoutFromShader(context, mState.getAttachedVertexShader(), &mCachedInputLayout);
1430     VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
1431     updateCachedVertexExecutableIndex();
1432 }
1433 
1434 class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
1435 {
1436   public:
GetPixelExecutableTask(ProgramD3D * program)1437     GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
run()1438     gl::Error run() override
1439     {
1440         mProgram->updateCachedOutputLayoutFromShader();
1441 
1442         ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(&mResult, &mInfoLog));
1443 
1444         return gl::NoError();
1445     }
1446 };
1447 
updateCachedOutputLayoutFromShader()1448 void ProgramD3D::updateCachedOutputLayoutFromShader()
1449 {
1450     GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
1451     updateCachedPixelExecutableIndex();
1452 }
1453 
1454 class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
1455 {
1456   public:
GetGeometryExecutableTask(ProgramD3D * program,const gl::Context * context)1457     GetGeometryExecutableTask(ProgramD3D *program, const gl::Context *context)
1458         : GetExecutableTask(program), mContext(context)
1459     {
1460     }
1461 
run()1462     gl::Error run() override
1463     {
1464         // Auto-generate the geometry shader here, if we expect to be using point rendering in
1465         // D3D11.
1466         if (mProgram->usesGeometryShader(GL_POINTS))
1467         {
1468             ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(mContext, GL_POINTS, &mResult,
1469                                                                       &mInfoLog));
1470         }
1471 
1472         return gl::NoError();
1473     }
1474 
1475   private:
1476     const gl::Context *mContext;
1477 };
1478 
getComputeExecutable(ShaderExecutableD3D ** outExecutable)1479 gl::Error ProgramD3D::getComputeExecutable(ShaderExecutableD3D **outExecutable)
1480 {
1481     if (outExecutable)
1482     {
1483         *outExecutable = mComputeExecutable.get();
1484     }
1485 
1486     return gl::NoError();
1487 }
1488 
compileProgramExecutables(const gl::Context * context,gl::InfoLog & infoLog)1489 gl::LinkResult ProgramD3D::compileProgramExecutables(const gl::Context *context,
1490                                                      gl::InfoLog &infoLog)
1491 {
1492     // Ensure the compiler is initialized to avoid race conditions.
1493     ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
1494 
1495     WorkerThreadPool *workerPool = mRenderer->getWorkerThreadPool();
1496 
1497     GetVertexExecutableTask vertexTask(this, context);
1498     GetPixelExecutableTask pixelTask(this);
1499     GetGeometryExecutableTask geometryTask(this, context);
1500 
1501     std::array<WaitableEvent, 3> waitEvents = {{workerPool->postWorkerTask(&vertexTask),
1502                                                 workerPool->postWorkerTask(&pixelTask),
1503                                                 workerPool->postWorkerTask(&geometryTask)}};
1504 
1505     WaitableEvent::WaitMany(&waitEvents);
1506 
1507     infoLog << vertexTask.getInfoLog().str();
1508     infoLog << pixelTask.getInfoLog().str();
1509     infoLog << geometryTask.getInfoLog().str();
1510 
1511     ANGLE_TRY(vertexTask.getError());
1512     ANGLE_TRY(pixelTask.getError());
1513     ANGLE_TRY(geometryTask.getError());
1514 
1515     ShaderExecutableD3D *defaultVertexExecutable = vertexTask.getResult();
1516     ShaderExecutableD3D *defaultPixelExecutable  = pixelTask.getResult();
1517     ShaderExecutableD3D *pointGS                 = geometryTask.getResult();
1518 
1519     const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
1520 
1521     if (usesGeometryShader(GL_POINTS) && pointGS)
1522     {
1523         // Geometry shaders are currently only used internally, so there is no corresponding shader
1524         // object at the interface level. For now the geometry shader debug info is prepended to
1525         // the vertex shader.
1526         vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1527         vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo());
1528         vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1529     }
1530 
1531     if (defaultVertexExecutable)
1532     {
1533         vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1534     }
1535 
1536     if (defaultPixelExecutable)
1537     {
1538         const ShaderD3D *fragmentShaderD3D =
1539             GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
1540         fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1541     }
1542 
1543     return (defaultVertexExecutable && defaultPixelExecutable &&
1544             (!usesGeometryShader(GL_POINTS) || pointGS));
1545 }
1546 
compileComputeExecutable(const gl::Context * context,gl::InfoLog & infoLog)1547 gl::LinkResult ProgramD3D::compileComputeExecutable(const gl::Context *context,
1548                                                     gl::InfoLog &infoLog)
1549 {
1550     // Ensure the compiler is initialized to avoid race conditions.
1551     ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
1552 
1553     std::string computeShader = mDynamicHLSL->generateComputeShaderLinkHLSL(context, mState);
1554 
1555     ShaderExecutableD3D *computeExecutable = nullptr;
1556     ANGLE_TRY(mRenderer->compileToExecutable(infoLog, computeShader, gl::SHADER_COMPUTE,
1557                                              std::vector<D3DVarying>(), false,
1558                                              angle::CompilerWorkaroundsD3D(), &computeExecutable));
1559 
1560     if (computeExecutable == nullptr)
1561     {
1562         ERR() << "Error compiling dynamic compute executable:" << std::endl
1563               << infoLog.str() << std::endl;
1564     }
1565     else
1566     {
1567         const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
1568         computeShaderD3D->appendDebugInfo(computeExecutable->getDebugInfo());
1569         mComputeExecutable.reset(computeExecutable);
1570     }
1571 
1572     return mComputeExecutable.get() != nullptr;
1573 }
1574 
link(const gl::Context * context,const gl::ProgramLinkedResources & resources,gl::InfoLog & infoLog)1575 gl::LinkResult ProgramD3D::link(const gl::Context *context,
1576                                 const gl::ProgramLinkedResources &resources,
1577                                 gl::InfoLog &infoLog)
1578 {
1579     const auto &data = context->getContextState();
1580 
1581     reset();
1582 
1583     gl::Shader *computeShader = mState.getAttachedComputeShader();
1584     if (computeShader)
1585     {
1586         mSamplersCS.resize(data.getCaps().maxComputeTextureImageUnits);
1587 
1588         defineUniformsAndAssignRegisters(context);
1589 
1590         gl::LinkResult result = compileComputeExecutable(context, infoLog);
1591         if (result.isError())
1592         {
1593             infoLog << result.getError().getMessage();
1594             return result;
1595         }
1596         else if (!result.getResult())
1597         {
1598             infoLog << "Failed to create D3D compute shader.";
1599             return result;
1600         }
1601     }
1602     else
1603     {
1604         gl::Shader *vertexShader   = mState.getAttachedVertexShader();
1605         gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
1606 
1607         const ShaderD3D *vertexShaderD3D   = GetImplAs<ShaderD3D>(vertexShader);
1608         const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
1609 
1610         mSamplersVS.resize(data.getCaps().maxVertexTextureImageUnits);
1611         mSamplersPS.resize(data.getCaps().maxTextureImageUnits);
1612 
1613         vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
1614         fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
1615 
1616         if (mRenderer->getNativeLimitations().noFrontFacingSupport)
1617         {
1618             if (fragmentShaderD3D->usesFrontFacing())
1619             {
1620                 infoLog << "The current renderer doesn't support gl_FrontFacing";
1621                 return false;
1622             }
1623         }
1624 
1625         // TODO(jmadill): Implement more sophisticated component packing in D3D9.
1626         // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
1627         // intelligently, but D3D9 assumes one semantic per register.
1628         if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
1629             resources.varyingPacking.getMaxSemanticIndex() > data.getCaps().maxVaryingVectors)
1630         {
1631             infoLog << "Cannot pack these varyings on D3D9.";
1632             return false;
1633         }
1634 
1635         ProgramD3DMetadata metadata(mRenderer, vertexShaderD3D, fragmentShaderD3D);
1636         BuiltinVaryingsD3D builtins(metadata, resources.varyingPacking);
1637 
1638         mDynamicHLSL->generateShaderLinkHLSL(context, mState, metadata, resources.varyingPacking,
1639                                              builtins, &mPixelHLSL, &mVertexHLSL);
1640 
1641         mUsesPointSize = vertexShaderD3D->usesPointSize();
1642         mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
1643         mUsesFragDepth = metadata.usesFragDepth();
1644         mUsesViewID               = metadata.usesViewID();
1645         mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
1646 
1647         // Cache if we use flat shading
1648         mUsesFlatInterpolation =
1649             (FindFlatInterpolationVarying(fragmentShader->getInputVaryings(context)) ||
1650              FindFlatInterpolationVarying(vertexShader->getOutputVaryings(context)));
1651 
1652         if (mRenderer->getMajorShaderModel() >= 4)
1653         {
1654             mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
1655                 resources.varyingPacking, builtins, mHasANGLEMultiviewEnabled,
1656                 metadata.canSelectViewInVertexShader());
1657         }
1658 
1659         initAttribLocationsToD3DSemantic(context);
1660 
1661         defineUniformsAndAssignRegisters(context);
1662 
1663         gatherTransformFeedbackVaryings(resources.varyingPacking, builtins[gl::SHADER_VERTEX]);
1664 
1665         gl::LinkResult result = compileProgramExecutables(context, infoLog);
1666         if (result.isError())
1667         {
1668             infoLog << result.getError().getMessage();
1669             return result;
1670         }
1671         else if (!result.getResult())
1672         {
1673             infoLog << "Failed to create D3D shaders.";
1674             return result;
1675         }
1676     }
1677 
1678     linkResources(context, resources);
1679 
1680     return true;
1681 }
1682 
validate(const gl::Caps &,gl::InfoLog *)1683 GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
1684 {
1685     // TODO(jmadill): Do something useful here?
1686     return GL_TRUE;
1687 }
1688 
initializeUniformBlocks()1689 void ProgramD3D::initializeUniformBlocks()
1690 {
1691     if (mState.getUniformBlocks().empty())
1692     {
1693         return;
1694     }
1695 
1696     ASSERT(mD3DUniformBlocks.empty());
1697 
1698     // Assign registers and update sizes.
1699     const ShaderD3D *vertexShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
1700     const ShaderD3D *fragmentShaderD3D =
1701         SafeGetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
1702     const ShaderD3D *computeShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
1703 
1704     for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
1705     {
1706         unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
1707 
1708         D3DUniformBlock d3dUniformBlock;
1709 
1710         if (uniformBlock.vertexStaticUse)
1711         {
1712             ASSERT(vertexShaderD3D != nullptr);
1713             unsigned int baseRegister = vertexShaderD3D->getUniformBlockRegister(uniformBlock.name);
1714             d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
1715         }
1716 
1717         if (uniformBlock.fragmentStaticUse)
1718         {
1719             ASSERT(fragmentShaderD3D != nullptr);
1720             unsigned int baseRegister =
1721                 fragmentShaderD3D->getUniformBlockRegister(uniformBlock.name);
1722             d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
1723         }
1724 
1725         if (uniformBlock.computeStaticUse)
1726         {
1727             ASSERT(computeShaderD3D != nullptr);
1728             unsigned int baseRegister =
1729                 computeShaderD3D->getUniformBlockRegister(uniformBlock.name);
1730             d3dUniformBlock.csRegisterIndex = baseRegister + uniformBlockElement;
1731         }
1732 
1733         mD3DUniformBlocks.push_back(d3dUniformBlock);
1734     }
1735 }
1736 
initializeUniformStorage()1737 void ProgramD3D::initializeUniformStorage()
1738 {
1739     // Compute total default block size
1740     unsigned int vertexRegisters   = 0;
1741     unsigned int fragmentRegisters = 0;
1742     unsigned int computeRegisters  = 0;
1743     for (const D3DUniform *d3dUniform : mD3DUniforms)
1744     {
1745         if (!d3dUniform->isSampler())
1746         {
1747             if (d3dUniform->isReferencedByVertexShader())
1748             {
1749                 vertexRegisters = std::max(vertexRegisters,
1750                                            d3dUniform->vsRegisterIndex + d3dUniform->registerCount);
1751             }
1752             if (d3dUniform->isReferencedByFragmentShader())
1753             {
1754                 fragmentRegisters = std::max(
1755                     fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
1756             }
1757             if (d3dUniform->isReferencedByComputeShader())
1758             {
1759                 computeRegisters = std::max(
1760                     computeRegisters, d3dUniform->csRegisterIndex + d3dUniform->registerCount);
1761             }
1762         }
1763     }
1764 
1765     mVertexUniformStorage =
1766         std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(vertexRegisters * 16u));
1767     mFragmentUniformStorage = std::unique_ptr<UniformStorageD3D>(
1768         mRenderer->createUniformStorage(fragmentRegisters * 16u));
1769     mComputeUniformStorage =
1770         std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(computeRegisters * 16u));
1771 
1772     // Iterate the uniforms again to assign data pointers to default block uniforms.
1773     for (D3DUniform *d3dUniform : mD3DUniforms)
1774     {
1775         if (d3dUniform->isSampler())
1776         {
1777             d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
1778             continue;
1779         }
1780 
1781         if (d3dUniform->isReferencedByVertexShader())
1782         {
1783             d3dUniform->vsData = mVertexUniformStorage->getDataPointer(d3dUniform->vsRegisterIndex,
1784                                                                        d3dUniform->registerElement);
1785         }
1786 
1787         if (d3dUniform->isReferencedByFragmentShader())
1788         {
1789             d3dUniform->psData = mFragmentUniformStorage->getDataPointer(
1790                 d3dUniform->psRegisterIndex, d3dUniform->registerElement);
1791         }
1792 
1793         if (d3dUniform->isReferencedByComputeShader())
1794         {
1795             d3dUniform->csData = mComputeUniformStorage->getDataPointer(
1796                 d3dUniform->csRegisterIndex, d3dUniform->registerElement);
1797         }
1798     }
1799 }
1800 
updateUniformBufferCache(const gl::Caps & caps,unsigned int reservedVertex,unsigned int reservedFragment)1801 void ProgramD3D::updateUniformBufferCache(const gl::Caps &caps,
1802                                           unsigned int reservedVertex,
1803                                           unsigned int reservedFragment)
1804 {
1805     if (mState.getUniformBlocks().empty())
1806     {
1807         return;
1808     }
1809 
1810     mVertexUBOCache.clear();
1811     mFragmentUBOCache.clear();
1812 
1813     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
1814          uniformBlockIndex++)
1815     {
1816         const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
1817         GLuint blockBinding                 = mState.getUniformBlockBinding(uniformBlockIndex);
1818 
1819         // Unnecessary to apply an unreferenced standard or shared UBO
1820         if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
1821         {
1822             continue;
1823         }
1824 
1825         if (uniformBlock.vertexStaticUse())
1826         {
1827             unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedVertex;
1828             ASSERT(registerIndex < caps.maxVertexUniformBlocks);
1829 
1830             if (mVertexUBOCache.size() <= registerIndex)
1831             {
1832                 mVertexUBOCache.resize(registerIndex + 1, -1);
1833             }
1834 
1835             ASSERT(mVertexUBOCache[registerIndex] == -1);
1836             mVertexUBOCache[registerIndex] = blockBinding;
1837         }
1838 
1839         if (uniformBlock.fragmentStaticUse())
1840         {
1841             unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedFragment;
1842             ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
1843 
1844             if (mFragmentUBOCache.size() <= registerIndex)
1845             {
1846                 mFragmentUBOCache.resize(registerIndex + 1, -1);
1847             }
1848 
1849             ASSERT(mFragmentUBOCache[registerIndex] == -1);
1850             mFragmentUBOCache[registerIndex] = blockBinding;
1851         }
1852     }
1853 }
1854 
getVertexUniformBufferCache() const1855 const std::vector<GLint> &ProgramD3D::getVertexUniformBufferCache() const
1856 {
1857     return mVertexUBOCache;
1858 }
1859 
getFragmentUniformBufferCache() const1860 const std::vector<GLint> &ProgramD3D::getFragmentUniformBufferCache() const
1861 {
1862     return mFragmentUBOCache;
1863 }
1864 
dirtyAllUniforms()1865 void ProgramD3D::dirtyAllUniforms()
1866 {
1867     mVertexUniformsDirty   = true;
1868     mFragmentUniformsDirty = true;
1869     mComputeUniformsDirty  = true;
1870 }
1871 
markUniformsClean()1872 void ProgramD3D::markUniformsClean()
1873 {
1874     mVertexUniformsDirty   = false;
1875     mFragmentUniformsDirty = false;
1876     mComputeUniformsDirty  = false;
1877 }
1878 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)1879 void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
1880 {
1881     setUniformInternal(location, count, v, GL_FLOAT);
1882 }
1883 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)1884 void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1885 {
1886     setUniformInternal(location, count, v, GL_FLOAT_VEC2);
1887 }
1888 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)1889 void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1890 {
1891     setUniformInternal(location, count, v, GL_FLOAT_VEC3);
1892 }
1893 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)1894 void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1895 {
1896     setUniformInternal(location, count, v, GL_FLOAT_VEC4);
1897 }
1898 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1899 void ProgramD3D::setUniformMatrix2fv(GLint location,
1900                                      GLsizei count,
1901                                      GLboolean transpose,
1902                                      const GLfloat *value)
1903 {
1904     setUniformMatrixfvInternal<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
1905 }
1906 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1907 void ProgramD3D::setUniformMatrix3fv(GLint location,
1908                                      GLsizei count,
1909                                      GLboolean transpose,
1910                                      const GLfloat *value)
1911 {
1912     setUniformMatrixfvInternal<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
1913 }
1914 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1915 void ProgramD3D::setUniformMatrix4fv(GLint location,
1916                                      GLsizei count,
1917                                      GLboolean transpose,
1918                                      const GLfloat *value)
1919 {
1920     setUniformMatrixfvInternal<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
1921 }
1922 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1923 void ProgramD3D::setUniformMatrix2x3fv(GLint location,
1924                                        GLsizei count,
1925                                        GLboolean transpose,
1926                                        const GLfloat *value)
1927 {
1928     setUniformMatrixfvInternal<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
1929 }
1930 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1931 void ProgramD3D::setUniformMatrix3x2fv(GLint location,
1932                                        GLsizei count,
1933                                        GLboolean transpose,
1934                                        const GLfloat *value)
1935 {
1936     setUniformMatrixfvInternal<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
1937 }
1938 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1939 void ProgramD3D::setUniformMatrix2x4fv(GLint location,
1940                                        GLsizei count,
1941                                        GLboolean transpose,
1942                                        const GLfloat *value)
1943 {
1944     setUniformMatrixfvInternal<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
1945 }
1946 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1947 void ProgramD3D::setUniformMatrix4x2fv(GLint location,
1948                                        GLsizei count,
1949                                        GLboolean transpose,
1950                                        const GLfloat *value)
1951 {
1952     setUniformMatrixfvInternal<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
1953 }
1954 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1955 void ProgramD3D::setUniformMatrix3x4fv(GLint location,
1956                                        GLsizei count,
1957                                        GLboolean transpose,
1958                                        const GLfloat *value)
1959 {
1960     setUniformMatrixfvInternal<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
1961 }
1962 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)1963 void ProgramD3D::setUniformMatrix4x3fv(GLint location,
1964                                        GLsizei count,
1965                                        GLboolean transpose,
1966                                        const GLfloat *value)
1967 {
1968     setUniformMatrixfvInternal<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
1969 }
1970 
setUniform1iv(GLint location,GLsizei count,const GLint * v)1971 void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1972 {
1973     setUniformInternal(location, count, v, GL_INT);
1974 }
1975 
setUniform2iv(GLint location,GLsizei count,const GLint * v)1976 void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1977 {
1978     setUniformInternal(location, count, v, GL_INT_VEC2);
1979 }
1980 
setUniform3iv(GLint location,GLsizei count,const GLint * v)1981 void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1982 {
1983     setUniformInternal(location, count, v, GL_INT_VEC3);
1984 }
1985 
setUniform4iv(GLint location,GLsizei count,const GLint * v)1986 void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1987 {
1988     setUniformInternal(location, count, v, GL_INT_VEC4);
1989 }
1990 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)1991 void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1992 {
1993     setUniformInternal(location, count, v, GL_UNSIGNED_INT);
1994 }
1995 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)1996 void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1997 {
1998     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
1999 }
2000 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)2001 void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2002 {
2003     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
2004 }
2005 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)2006 void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2007 {
2008     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
2009 }
2010 
setUniformBlockBinding(GLuint,GLuint)2011 void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
2012                                         GLuint /*uniformBlockBinding*/)
2013 {
2014 }
2015 
defineUniformsAndAssignRegisters(const gl::Context * context)2016 void ProgramD3D::defineUniformsAndAssignRegisters(const gl::Context *context)
2017 {
2018     D3DUniformMap uniformMap;
2019     gl::Shader *computeShader = mState.getAttachedComputeShader();
2020     if (computeShader)
2021     {
2022         for (const sh::Uniform &computeUniform : computeShader->getUniforms(context))
2023         {
2024             if (computeUniform.staticUse)
2025             {
2026                 defineUniformBase(computeShader, computeUniform, &uniformMap);
2027             }
2028         }
2029     }
2030     else
2031     {
2032         gl::Shader *vertexShader = mState.getAttachedVertexShader();
2033         for (const sh::Uniform &vertexUniform : vertexShader->getUniforms(context))
2034         {
2035             if (vertexUniform.staticUse)
2036             {
2037                 defineUniformBase(vertexShader, vertexUniform, &uniformMap);
2038             }
2039         }
2040 
2041         gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
2042         for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms(context))
2043         {
2044             if (fragmentUniform.staticUse)
2045             {
2046                 defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
2047             }
2048         }
2049     }
2050 
2051     // Initialize the D3DUniform list to mirror the indexing of the GL layer.
2052     for (const gl::LinkedUniform &glUniform : mState.getUniforms())
2053     {
2054         if (!glUniform.isInDefaultBlock())
2055             continue;
2056 
2057         std::string name = glUniform.name;
2058         if (glUniform.isArray())
2059         {
2060             // In the program state, array uniform names include [0] as in the program resource
2061             // spec. Here we don't include it.
2062             // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL
2063             // layer.
2064             ASSERT(angle::EndsWith(name, "[0]"));
2065             name.resize(name.length() - 3);
2066         }
2067         auto mapEntry = uniformMap.find(name);
2068         ASSERT(mapEntry != uniformMap.end());
2069         mD3DUniforms.push_back(mapEntry->second);
2070     }
2071 
2072     assignAllSamplerRegisters();
2073     initializeUniformStorage();
2074 }
2075 
defineUniformBase(const gl::Shader * shader,const sh::Uniform & uniform,D3DUniformMap * uniformMap)2076 void ProgramD3D::defineUniformBase(const gl::Shader *shader,
2077                                    const sh::Uniform &uniform,
2078                                    D3DUniformMap *uniformMap)
2079 {
2080     // Samplers get their registers assigned in assignAllSamplerRegisters.
2081     if (uniform.isBuiltIn() || gl::IsSamplerType(uniform.type))
2082     {
2083         defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
2084         return;
2085     }
2086 
2087     const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
2088 
2089     unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
2090     ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
2091     sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
2092     encoder.skipRegisters(startRegister);
2093 
2094     defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
2095 }
2096 
getD3DUniformByName(const std::string & name)2097 D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
2098 {
2099     for (D3DUniform *d3dUniform : mD3DUniforms)
2100     {
2101         if (d3dUniform->name == name)
2102         {
2103             return d3dUniform;
2104         }
2105     }
2106 
2107     return nullptr;
2108 }
2109 
defineStructUniformFields(GLenum shaderType,const std::vector<sh::ShaderVariable> & fields,const std::string & namePrefix,sh::HLSLBlockEncoder * encoder,D3DUniformMap * uniformMap)2110 void ProgramD3D::defineStructUniformFields(GLenum shaderType,
2111                                            const std::vector<sh::ShaderVariable> &fields,
2112                                            const std::string &namePrefix,
2113                                            sh::HLSLBlockEncoder *encoder,
2114                                            D3DUniformMap *uniformMap)
2115 {
2116     if (encoder)
2117         encoder->enterAggregateType();
2118 
2119     for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
2120     {
2121         const sh::ShaderVariable &field  = fields[fieldIndex];
2122         const std::string &fieldFullName = (namePrefix + "." + field.name);
2123 
2124         // Samplers get their registers assigned in assignAllSamplerRegisters.
2125         // Also they couldn't use the same encoder as the rest of the struct, since they are
2126         // extracted out of the struct by the shader translator.
2127         if (gl::IsSamplerType(field.type))
2128         {
2129             defineUniform(shaderType, field, fieldFullName, nullptr, uniformMap);
2130         }
2131         else
2132         {
2133             defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
2134         }
2135     }
2136 
2137     if (encoder)
2138         encoder->exitAggregateType();
2139 }
2140 
defineArrayOfStructsUniformFields(GLenum shaderType,const sh::ShaderVariable & uniform,unsigned int arrayNestingIndex,const std::string & prefix,sh::HLSLBlockEncoder * encoder,D3DUniformMap * uniformMap)2141 void ProgramD3D::defineArrayOfStructsUniformFields(GLenum shaderType,
2142                                                    const sh::ShaderVariable &uniform,
2143                                                    unsigned int arrayNestingIndex,
2144                                                    const std::string &prefix,
2145                                                    sh::HLSLBlockEncoder *encoder,
2146                                                    D3DUniformMap *uniformMap)
2147 {
2148     // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
2149     // innermost.
2150     const unsigned int currentArraySize = uniform.getNestedArraySize(arrayNestingIndex);
2151     for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
2152     {
2153         const std::string &elementString = prefix + ArrayString(arrayElement);
2154         if (arrayNestingIndex + 1u < uniform.arraySizes.size())
2155         {
2156             defineArrayOfStructsUniformFields(shaderType, uniform, arrayNestingIndex + 1u,
2157                                               elementString, encoder, uniformMap);
2158         }
2159         else
2160         {
2161             defineStructUniformFields(shaderType, uniform.fields, elementString, encoder,
2162                                       uniformMap);
2163         }
2164     }
2165 }
2166 
defineArrayUniformElements(GLenum shaderType,const sh::ShaderVariable & uniform,const std::string & fullName,sh::HLSLBlockEncoder * encoder,D3DUniformMap * uniformMap)2167 void ProgramD3D::defineArrayUniformElements(GLenum shaderType,
2168                                             const sh::ShaderVariable &uniform,
2169                                             const std::string &fullName,
2170                                             sh::HLSLBlockEncoder *encoder,
2171                                             D3DUniformMap *uniformMap)
2172 {
2173     if (encoder)
2174         encoder->enterAggregateType();
2175 
2176     sh::ShaderVariable uniformElement = uniform;
2177     uniformElement.arraySizes.pop_back();
2178     for (unsigned int arrayIndex = 0u; arrayIndex < uniform.getOutermostArraySize(); ++arrayIndex)
2179     {
2180         std::string elementFullName = fullName + ArrayString(arrayIndex);
2181         defineUniform(shaderType, uniformElement, elementFullName, encoder, uniformMap);
2182     }
2183 
2184     if (encoder)
2185         encoder->exitAggregateType();
2186 }
2187 
defineUniform(GLenum shaderType,const sh::ShaderVariable & uniform,const std::string & fullName,sh::HLSLBlockEncoder * encoder,D3DUniformMap * uniformMap)2188 void ProgramD3D::defineUniform(GLenum shaderType,
2189                                const sh::ShaderVariable &uniform,
2190                                const std::string &fullName,
2191                                sh::HLSLBlockEncoder *encoder,
2192                                D3DUniformMap *uniformMap)
2193 {
2194     if (uniform.isStruct())
2195     {
2196         if (uniform.isArray())
2197         {
2198             defineArrayOfStructsUniformFields(shaderType, uniform, 0u, fullName, encoder,
2199                                               uniformMap);
2200         }
2201         else
2202         {
2203             defineStructUniformFields(shaderType, uniform.fields, fullName, encoder, uniformMap);
2204         }
2205         return;
2206     }
2207     if (uniform.isArrayOfArrays())
2208     {
2209         defineArrayUniformElements(shaderType, uniform, fullName, encoder, uniformMap);
2210         return;
2211     }
2212 
2213     // Not a struct. Arrays are treated as aggregate types.
2214     if (uniform.isArray() && encoder)
2215     {
2216         encoder->enterAggregateType();
2217     }
2218 
2219     // Advance the uniform offset, to track registers allocation for structs
2220     sh::BlockMemberInfo blockInfo =
2221         encoder ? encoder->encodeType(uniform.type, uniform.arraySizes, false)
2222                 : sh::BlockMemberInfo::getDefaultBlockInfo();
2223 
2224     auto uniformMapEntry   = uniformMap->find(fullName);
2225     D3DUniform *d3dUniform = nullptr;
2226 
2227     if (uniformMapEntry != uniformMap->end())
2228     {
2229         d3dUniform = uniformMapEntry->second;
2230     }
2231     else
2232     {
2233         d3dUniform              = new D3DUniform(uniform.type, fullName, uniform.arraySizes, true);
2234         (*uniformMap)[fullName] = d3dUniform;
2235     }
2236 
2237     if (encoder)
2238     {
2239         d3dUniform->registerElement =
2240             static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
2241         unsigned int reg =
2242             static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
2243         if (shaderType == GL_FRAGMENT_SHADER)
2244         {
2245             d3dUniform->psRegisterIndex = reg;
2246         }
2247         else if (shaderType == GL_VERTEX_SHADER)
2248         {
2249             d3dUniform->vsRegisterIndex = reg;
2250         }
2251         else
2252         {
2253             ASSERT(shaderType == GL_COMPUTE_SHADER);
2254             d3dUniform->csRegisterIndex = reg;
2255         }
2256 
2257         // Arrays are treated as aggregate types
2258         if (uniform.isArray())
2259         {
2260             encoder->exitAggregateType();
2261         }
2262     }
2263 }
2264 
2265 // Assume count is already clamped.
2266 template <typename T>
setUniformImpl(const gl::VariableLocation & locationInfo,GLsizei count,const T * v,uint8_t * targetData,GLenum uniformType)2267 void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
2268                                 GLsizei count,
2269                                 const T *v,
2270                                 uint8_t *targetData,
2271                                 GLenum uniformType)
2272 {
2273     D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2274     const int components      = targetUniform->typeInfo.componentCount;
2275     const unsigned int arrayElementOffset = locationInfo.arrayIndex;
2276 
2277     if (targetUniform->typeInfo.type == uniformType)
2278     {
2279         T *dest         = reinterpret_cast<T *>(targetData) + arrayElementOffset * 4;
2280         const T *source = v;
2281 
2282         for (GLint i = 0; i < count; i++, dest += 4, source += components)
2283         {
2284             memcpy(dest, source, components * sizeof(T));
2285         }
2286     }
2287     else
2288     {
2289         ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
2290         GLint *boolParams = reinterpret_cast<GLint *>(targetData) + arrayElementOffset * 4;
2291 
2292         for (GLint i = 0; i < count; i++)
2293         {
2294             GLint *dest     = boolParams + (i * 4);
2295             const T *source = v + (i * components);
2296 
2297             for (int c = 0; c < components; c++)
2298             {
2299                 dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
2300             }
2301         }
2302     }
2303 }
2304 
2305 template <typename T>
setUniformInternal(GLint location,GLsizei count,const T * v,GLenum uniformType)2306 void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType)
2307 {
2308     const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2309     D3DUniform *targetUniform                = mD3DUniforms[locationInfo.index];
2310 
2311     if (targetUniform->typeInfo.isSampler)
2312     {
2313         ASSERT(uniformType == GL_INT);
2314         size_t size = count * sizeof(T);
2315         GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
2316         if (memcmp(dest, v, size) != 0)
2317         {
2318             memcpy(dest, v, size);
2319             mDirtySamplerMapping = true;
2320         }
2321         return;
2322     }
2323 
2324     if (targetUniform->vsData)
2325     {
2326         setUniformImpl(locationInfo, count, v, targetUniform->vsData, uniformType);
2327         mVertexUniformsDirty = true;
2328     }
2329 
2330     if (targetUniform->psData)
2331     {
2332         setUniformImpl(locationInfo, count, v, targetUniform->psData, uniformType);
2333         mFragmentUniformsDirty = true;
2334     }
2335 
2336     if (targetUniform->csData)
2337     {
2338         setUniformImpl(locationInfo, count, v, targetUniform->csData, uniformType);
2339         mComputeUniformsDirty = true;
2340     }
2341 }
2342 
2343 template <int cols, int rows>
setUniformMatrixfvImpl(GLint location,GLsizei countIn,GLboolean transpose,const GLfloat * value,uint8_t * targetData,GLenum targetUniformType)2344 bool ProgramD3D::setUniformMatrixfvImpl(GLint location,
2345                                         GLsizei countIn,
2346                                         GLboolean transpose,
2347                                         const GLfloat *value,
2348                                         uint8_t *targetData,
2349                                         GLenum targetUniformType)
2350 {
2351     D3DUniform *targetUniform = getD3DUniformFromLocation(location);
2352 
2353     unsigned int elementCount       = targetUniform->getArraySizeProduct();
2354     unsigned int arrayElementOffset = mState.getUniformLocations()[location].arrayIndex;
2355     unsigned int count =
2356         std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
2357 
2358     const unsigned int targetMatrixStride = (4 * rows);
2359     GLfloat *target                       = reinterpret_cast<GLfloat *>(
2360         targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
2361 
2362     bool dirty = false;
2363 
2364     for (unsigned int i = 0; i < count; i++)
2365     {
2366         // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
2367         if (transpose == GL_FALSE)
2368         {
2369             dirty = TransposeExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
2370         }
2371         else
2372         {
2373             dirty = ExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
2374         }
2375         target += targetMatrixStride;
2376         value += cols * rows;
2377     }
2378 
2379     return dirty;
2380 }
2381 
2382 template <int cols, int rows>
setUniformMatrixfvInternal(GLint location,GLsizei countIn,GLboolean transpose,const GLfloat * value,GLenum targetUniformType)2383 void ProgramD3D::setUniformMatrixfvInternal(GLint location,
2384                                             GLsizei countIn,
2385                                             GLboolean transpose,
2386                                             const GLfloat *value,
2387                                             GLenum targetUniformType)
2388 {
2389     D3DUniform *targetUniform = getD3DUniformFromLocation(location);
2390 
2391     if (targetUniform->vsData)
2392     {
2393         if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
2394                                                targetUniform->vsData, targetUniformType))
2395         {
2396             mVertexUniformsDirty = true;
2397         }
2398     }
2399 
2400     if (targetUniform->psData)
2401     {
2402         if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
2403                                                targetUniform->psData, targetUniformType))
2404         {
2405             mFragmentUniformsDirty = true;
2406         }
2407     }
2408 
2409     if (targetUniform->csData)
2410     {
2411         if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
2412                                                targetUniform->csData, targetUniformType))
2413         {
2414             mComputeUniformsDirty = true;
2415         }
2416     }
2417 }
2418 
assignAllSamplerRegisters()2419 void ProgramD3D::assignAllSamplerRegisters()
2420 {
2421     for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2422     {
2423         if (mD3DUniforms[uniformIndex]->isSampler())
2424         {
2425             assignSamplerRegisters(uniformIndex);
2426         }
2427     }
2428 }
2429 
assignSamplerRegisters(size_t uniformIndex)2430 void ProgramD3D::assignSamplerRegisters(size_t uniformIndex)
2431 {
2432     D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2433     ASSERT(d3dUniform->isSampler());
2434     // If the uniform is an array of arrays, then we have separate entries for each inner array in
2435     // mD3DUniforms. However, the sampler register info is stored in the shader only for the
2436     // outermost array.
2437     std::vector<unsigned int> subscripts;
2438     const std::string baseName  = gl::ParseResourceName(d3dUniform->name, &subscripts);
2439     unsigned int registerOffset = mState.getUniforms()[uniformIndex].flattenedOffsetInParentArrays *
2440                                   d3dUniform->getArraySizeProduct();
2441 
2442     const gl::Shader *computeShader = mState.getAttachedComputeShader();
2443     if (computeShader)
2444     {
2445         const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
2446         ASSERT(computeShaderD3D->hasUniform(baseName));
2447         d3dUniform->csRegisterIndex =
2448             computeShaderD3D->getUniformRegister(baseName) + registerOffset;
2449         ASSERT(d3dUniform->csRegisterIndex != GL_INVALID_INDEX);
2450         AssignSamplers(d3dUniform->csRegisterIndex, d3dUniform->typeInfo,
2451                        d3dUniform->getArraySizeProduct(), mSamplersCS, &mUsedComputeSamplerRange);
2452     }
2453     else
2454     {
2455         const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
2456         const ShaderD3D *fragmentShaderD3D =
2457             GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
2458         ASSERT(vertexShaderD3D->hasUniform(baseName) || fragmentShaderD3D->hasUniform(baseName));
2459         if (vertexShaderD3D->hasUniform(baseName))
2460         {
2461             d3dUniform->vsRegisterIndex =
2462                 vertexShaderD3D->getUniformRegister(baseName) + registerOffset;
2463             ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX);
2464             AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->typeInfo,
2465                            d3dUniform->getArraySizeProduct(), mSamplersVS,
2466                            &mUsedVertexSamplerRange);
2467         }
2468         if (fragmentShaderD3D->hasUniform(baseName))
2469         {
2470             d3dUniform->psRegisterIndex =
2471                 fragmentShaderD3D->getUniformRegister(baseName) + registerOffset;
2472             ASSERT(d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
2473             AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->typeInfo,
2474                            d3dUniform->getArraySizeProduct(), mSamplersPS, &mUsedPixelSamplerRange);
2475         }
2476     }
2477 }
2478 
2479 // static
AssignSamplers(unsigned int startSamplerIndex,const gl::UniformTypeInfo & typeInfo,unsigned int samplerCount,std::vector<Sampler> & outSamplers,GLuint * outUsedRange)2480 void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
2481                                 const gl::UniformTypeInfo &typeInfo,
2482                                 unsigned int samplerCount,
2483                                 std::vector<Sampler> &outSamplers,
2484                                 GLuint *outUsedRange)
2485 {
2486     unsigned int samplerIndex = startSamplerIndex;
2487 
2488     do
2489     {
2490         ASSERT(samplerIndex < outSamplers.size());
2491         Sampler *sampler            = &outSamplers[samplerIndex];
2492         sampler->active             = true;
2493         sampler->textureType        = typeInfo.samplerTextureType;
2494         sampler->logicalTextureUnit = 0;
2495         *outUsedRange               = std::max(samplerIndex + 1, *outUsedRange);
2496         samplerIndex++;
2497     } while (samplerIndex < startSamplerIndex + samplerCount);
2498 }
2499 
reset()2500 void ProgramD3D::reset()
2501 {
2502     mVertexExecutables.clear();
2503     mPixelExecutables.clear();
2504 
2505     for (auto &geometryExecutable : mGeometryExecutables)
2506     {
2507         geometryExecutable.reset(nullptr);
2508     }
2509 
2510     mComputeExecutable.reset(nullptr);
2511 
2512     mVertexHLSL.clear();
2513     mVertexWorkarounds = angle::CompilerWorkaroundsD3D();
2514 
2515     mPixelHLSL.clear();
2516     mPixelWorkarounds = angle::CompilerWorkaroundsD3D();
2517     mUsesFragDepth = false;
2518     mHasANGLEMultiviewEnabled = false;
2519     mUsesViewID               = false;
2520     mPixelShaderKey.clear();
2521     mUsesPointSize = false;
2522     mUsesFlatInterpolation = false;
2523 
2524     SafeDeleteContainer(mD3DUniforms);
2525     mD3DUniformBlocks.clear();
2526 
2527     mVertexUniformStorage.reset(nullptr);
2528     mFragmentUniformStorage.reset(nullptr);
2529     mComputeUniformStorage.reset(nullptr);
2530 
2531     mSamplersPS.clear();
2532     mSamplersVS.clear();
2533     mSamplersCS.clear();
2534 
2535     mUsedVertexSamplerRange = 0;
2536     mUsedPixelSamplerRange  = 0;
2537     mUsedComputeSamplerRange = 0;
2538     mDirtySamplerMapping    = true;
2539 
2540     mAttribLocationToD3DSemantic.fill(-1);
2541 
2542     mStreamOutVaryings.clear();
2543 
2544     mGeometryShaderPreamble.clear();
2545 
2546     dirtyAllUniforms();
2547 
2548     mCachedPixelExecutableIndex.reset();
2549     mCachedVertexExecutableIndex.reset();
2550 }
2551 
getSerial() const2552 unsigned int ProgramD3D::getSerial() const
2553 {
2554     return mSerial;
2555 }
2556 
issueSerial()2557 unsigned int ProgramD3D::issueSerial()
2558 {
2559     return mCurrentSerial++;
2560 }
2561 
initAttribLocationsToD3DSemantic(const gl::Context * context)2562 void ProgramD3D::initAttribLocationsToD3DSemantic(const gl::Context *context)
2563 {
2564     gl::Shader *vertexShader = mState.getAttachedVertexShader();
2565     ASSERT(vertexShader != nullptr);
2566 
2567     // Init semantic index
2568     int semanticIndex = 0;
2569     for (const sh::Attribute &attribute : vertexShader->getActiveAttributes(context))
2570     {
2571         int regCount    = gl::VariableRegisterCount(attribute.type);
2572         GLuint location = mState.getAttributeLocation(attribute.name);
2573         ASSERT(location != std::numeric_limits<GLuint>::max());
2574 
2575         for (int reg = 0; reg < regCount; ++reg)
2576         {
2577             mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
2578         }
2579     }
2580 }
2581 
updateCachedInputLayout(Serial associatedSerial,const gl::State & state)2582 void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state)
2583 {
2584     if (mCurrentVertexArrayStateSerial == associatedSerial)
2585     {
2586         return;
2587     }
2588 
2589     mCurrentVertexArrayStateSerial = associatedSerial;
2590     mCachedInputLayout.clear();
2591 
2592     const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
2593 
2594     for (size_t locationIndex : mState.getActiveAttribLocationsMask())
2595     {
2596         int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
2597 
2598         if (d3dSemantic != -1)
2599         {
2600             if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
2601             {
2602                 mCachedInputLayout.resize(d3dSemantic + 1, gl::VERTEX_FORMAT_INVALID);
2603             }
2604             mCachedInputLayout[d3dSemantic] =
2605                 GetVertexFormatType(vertexAttributes[locationIndex],
2606                                     state.getVertexAttribCurrentValue(locationIndex).Type);
2607         }
2608     }
2609 
2610     VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
2611 
2612     updateCachedVertexExecutableIndex();
2613 }
2614 
updateCachedOutputLayout(const gl::Context * context,const gl::Framebuffer * framebuffer)2615 void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
2616                                           const gl::Framebuffer *framebuffer)
2617 {
2618     mPixelShaderOutputLayoutCache.clear();
2619 
2620     FramebufferD3D *fboD3D   = GetImplAs<FramebufferD3D>(framebuffer);
2621     const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
2622 
2623     for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
2624     {
2625         const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
2626 
2627         if (colorbuffer)
2628         {
2629             auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
2630                                                                 : colorbuffer->getBinding();
2631             mPixelShaderOutputLayoutCache.push_back(binding);
2632         }
2633         else
2634         {
2635             mPixelShaderOutputLayoutCache.push_back(GL_NONE);
2636         }
2637     }
2638 
2639     updateCachedPixelExecutableIndex();
2640 }
2641 
gatherTransformFeedbackVaryings(const gl::VaryingPacking & varyingPacking,const BuiltinInfo & builtins)2642 void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
2643                                                  const BuiltinInfo &builtins)
2644 {
2645     const std::string &varyingSemantic =
2646         GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
2647 
2648     // Gather the linked varyings that are used for transform feedback, they should all exist.
2649     mStreamOutVaryings.clear();
2650 
2651     const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
2652     for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
2653          ++outputSlot)
2654     {
2655         const auto &tfVaryingName = tfVaryingNames[outputSlot];
2656         if (tfVaryingName == "gl_Position")
2657         {
2658             if (builtins.glPosition.enabled)
2659             {
2660                 mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic,
2661                                                         builtins.glPosition.index, 4, outputSlot));
2662             }
2663         }
2664         else if (tfVaryingName == "gl_FragCoord")
2665         {
2666             if (builtins.glFragCoord.enabled)
2667             {
2668                 mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic,
2669                                                         builtins.glFragCoord.index, 4, outputSlot));
2670             }
2671         }
2672         else if (tfVaryingName == "gl_PointSize")
2673         {
2674             if (builtins.glPointSize.enabled)
2675             {
2676                 mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot));
2677             }
2678         }
2679         else
2680         {
2681             std::vector<unsigned int> subscripts;
2682             std::string baseName = gl::ParseResourceName(tfVaryingName, &subscripts);
2683             size_t subscript     = GL_INVALID_INDEX;
2684             if (!subscripts.empty())
2685             {
2686                 subscript = subscripts.back();
2687             }
2688             for (const auto &registerInfo : varyingPacking.getRegisterList())
2689             {
2690                 const auto &varying   = *registerInfo.packedVarying->varying;
2691                 GLenum transposedType = gl::TransposeMatrixType(varying.type);
2692                 int componentCount = gl::VariableColumnCount(transposedType);
2693                 ASSERT(!varying.isBuiltIn());
2694 
2695                 // Transform feedback for varying structs is underspecified.
2696                 // See Khronos bug 9856.
2697                 // TODO(jmadill): Figure out how to be spec-compliant here.
2698                 if (registerInfo.packedVarying->isStructField() || varying.isStruct())
2699                     continue;
2700 
2701                 // There can be more than one register assigned to a particular varying, and each
2702                 // register needs its own stream out entry.
2703                 if (baseName == registerInfo.packedVarying->varying->name &&
2704                     (subscript == GL_INVALID_INDEX || subscript == registerInfo.varyingArrayIndex))
2705                 {
2706                     mStreamOutVaryings.push_back(D3DVarying(
2707                         varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
2708                 }
2709             }
2710         }
2711     }
2712 }
2713 
getD3DUniformFromLocation(GLint location)2714 D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
2715 {
2716     return mD3DUniforms[mState.getUniformLocations()[location].index];
2717 }
2718 
getD3DUniformFromLocation(GLint location) const2719 const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const
2720 {
2721     return mD3DUniforms[mState.getUniformLocations()[location].index];
2722 }
2723 
setPathFragmentInputGen(const std::string & inputName,GLenum genMode,GLint components,const GLfloat * coeffs)2724 void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
2725                                          GLenum genMode,
2726                                          GLint components,
2727                                          const GLfloat *coeffs)
2728 {
2729     UNREACHABLE();
2730 }
2731 
hasVertexExecutableForCachedInputLayout()2732 bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
2733 {
2734     return mCachedVertexExecutableIndex.valid();
2735 }
2736 
hasGeometryExecutableForPrimitiveType(GLenum drawMode)2737 bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode)
2738 {
2739     if (!usesGeometryShader(drawMode))
2740     {
2741         // No shader necessary mean we have the required (null) executable.
2742         return true;
2743     }
2744 
2745     gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
2746     return mGeometryExecutables[geometryShaderType].get() != nullptr;
2747 }
2748 
hasPixelExecutableForCachedOutputLayout()2749 bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
2750 {
2751     return mCachedPixelExecutableIndex.valid();
2752 }
2753 
2754 template <typename DestT>
getUniformInternal(GLint location,DestT * dataOut) const2755 void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const
2756 {
2757     const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2758     const gl::LinkedUniform &uniform         = mState.getUniforms()[locationInfo.index];
2759 
2760     const D3DUniform *targetUniform = getD3DUniformFromLocation(location);
2761     const uint8_t *srcPointer       = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
2762 
2763     if (gl::IsMatrixType(uniform.type))
2764     {
2765         GetMatrixUniform(gl::VariableColumnCount(uniform.type), gl::VariableRowCount(uniform.type),
2766                          dataOut, reinterpret_cast<const DestT *>(srcPointer));
2767     }
2768     else
2769     {
2770         memcpy(dataOut, srcPointer, uniform.getElementSize());
2771     }
2772 }
2773 
getUniformfv(const gl::Context * context,GLint location,GLfloat * params) const2774 void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
2775 {
2776     getUniformInternal(location, params);
2777 }
2778 
getUniformiv(const gl::Context * context,GLint location,GLint * params) const2779 void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
2780 {
2781     getUniformInternal(location, params);
2782 }
2783 
getUniformuiv(const gl::Context * context,GLint location,GLuint * params) const2784 void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
2785 {
2786     getUniformInternal(location, params);
2787 }
2788 
updateCachedVertexExecutableIndex()2789 void ProgramD3D::updateCachedVertexExecutableIndex()
2790 {
2791     mCachedVertexExecutableIndex.reset();
2792     for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
2793     {
2794         if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
2795         {
2796             mCachedVertexExecutableIndex = executableIndex;
2797             break;
2798         }
2799     }
2800 }
2801 
updateCachedPixelExecutableIndex()2802 void ProgramD3D::updateCachedPixelExecutableIndex()
2803 {
2804     mCachedPixelExecutableIndex.reset();
2805     for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
2806     {
2807         if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
2808         {
2809             mCachedPixelExecutableIndex = executableIndex;
2810             break;
2811         }
2812     }
2813 }
2814 
linkResources(const gl::Context * context,const gl::ProgramLinkedResources & resources)2815 void ProgramD3D::linkResources(const gl::Context *context,
2816                                const gl::ProgramLinkedResources &resources)
2817 {
2818     UniformBlockInfo uniformBlockInfo;
2819 
2820     if (mState.getAttachedVertexShader())
2821     {
2822         uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedVertexShader());
2823     }
2824 
2825     if (mState.getAttachedFragmentShader())
2826     {
2827         uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedFragmentShader());
2828     }
2829 
2830     if (mState.getAttachedComputeShader())
2831     {
2832         uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedComputeShader());
2833     }
2834 
2835     // Gather interface block info.
2836     auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name,
2837                                                    const std::string &mappedName, size_t *sizeOut) {
2838         return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut);
2839     };
2840 
2841     auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name,
2842                                                          const std::string &mappedName,
2843                                                          sh::BlockMemberInfo *infoOut) {
2844         return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
2845     };
2846 
2847     resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
2848     initializeUniformBlocks();
2849 
2850     // TODO(jiajia.qin@intel.com): Determine correct shader storage block info.
2851     auto getShaderStorageBlockSize = [](const std::string &name, const std::string &mappedName,
2852                                         size_t *sizeOut) {
2853         *sizeOut = 0;
2854         return true;
2855     };
2856 
2857     auto getShaderStorageBlockMemberInfo =
2858         [](const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut) {
2859             *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
2860             return true;
2861         };
2862 
2863     resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
2864                                                   getShaderStorageBlockMemberInfo);
2865 }
2866 
2867 }  // namespace rx
2868