• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 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/MemoryBuffer.h"
12 #include "common/bitset_utils.h"
13 #include "common/string_utils.h"
14 #include "common/utilities.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Framebuffer.h"
17 #include "libANGLE/FramebufferAttachment.h"
18 #include "libANGLE/Program.h"
19 #include "libANGLE/ProgramLinkedResources.h"
20 #include "libANGLE/Uniform.h"
21 #include "libANGLE/VertexArray.h"
22 #include "libANGLE/features.h"
23 #include "libANGLE/queryconversions.h"
24 #include "libANGLE/renderer/ContextImpl.h"
25 #include "libANGLE/renderer/d3d/ContextD3D.h"
26 #include "libANGLE/renderer/d3d/DynamicHLSL.h"
27 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
28 #include "libANGLE/renderer/d3d/ShaderD3D.h"
29 #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
30 #include "libANGLE/renderer/d3d/VertexDataManager.h"
31 #include "libANGLE/renderer/renderer_utils.h"
32 
33 using namespace angle;
34 
35 namespace rx
36 {
37 
38 namespace
39 {
40 
GetDefaultInputLayoutFromShader(gl::Shader * vertexShader,gl::InputLayout * inputLayoutOut)41 void GetDefaultInputLayoutFromShader(gl::Shader *vertexShader, gl::InputLayout *inputLayoutOut)
42 {
43     inputLayoutOut->clear();
44 
45     if (!vertexShader)
46     {
47         return;
48     }
49 
50     for (const sh::ShaderVariable &shaderAttr : vertexShader->getActiveAttributes())
51     {
52         if (shaderAttr.type != GL_NONE)
53         {
54             GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
55 
56             for (size_t rowIndex = 0;
57                  static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
58             {
59                 GLenum componentType = gl::VariableComponentType(transposedType);
60                 GLuint components    = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
61                 bool pureInt         = (componentType != GL_FLOAT);
62 
63                 gl::VertexAttribType attribType =
64                     gl::FromGLenum<gl::VertexAttribType>(componentType);
65 
66                 angle::FormatID defaultID =
67                     gl::GetVertexFormatID(attribType, GL_FALSE, components, pureInt);
68 
69                 inputLayoutOut->push_back(defaultID);
70             }
71         }
72     }
73 }
74 
GetMaxOutputIndex(const std::vector<PixelShaderOutputVariable> & shaderOutputVars,size_t location)75 size_t GetMaxOutputIndex(const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
76                          size_t location)
77 {
78     size_t maxIndex = 0;
79     for (auto &outputVar : shaderOutputVars)
80     {
81         if (outputVar.outputLocation == location)
82         {
83             maxIndex = std::max(maxIndex, outputVar.outputIndex);
84         }
85     }
86     return maxIndex;
87 }
88 
GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> & shaderOutputVars,std::vector<GLenum> * outputLayoutOut)89 void GetDefaultOutputLayoutFromShader(
90     const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
91     std::vector<GLenum> *outputLayoutOut)
92 {
93     outputLayoutOut->clear();
94 
95     if (!shaderOutputVars.empty())
96     {
97         size_t location = shaderOutputVars[0].outputLocation;
98         size_t maxIndex = GetMaxOutputIndex(shaderOutputVars, location);
99         outputLayoutOut->assign(maxIndex + 1,
100                                 GL_COLOR_ATTACHMENT0 + static_cast<unsigned int>(location));
101     }
102 }
103 
GetDefaultImage2DBindLayoutFromComputeShader(const std::vector<sh::ShaderVariable> & image2DUniforms,gl::ImageUnitTextureTypeMap * image2DBindLayout)104 void GetDefaultImage2DBindLayoutFromComputeShader(
105     const std::vector<sh::ShaderVariable> &image2DUniforms,
106     gl::ImageUnitTextureTypeMap *image2DBindLayout)
107 {
108     image2DBindLayout->clear();
109 
110     for (const sh::ShaderVariable &image2D : image2DUniforms)
111     {
112         if (gl::IsImage2DType(image2D.type))
113         {
114             if (image2D.binding == -1)
115             {
116                 image2DBindLayout->insert(std::make_pair(0, gl::TextureType::_2D));
117             }
118             else
119             {
120                 for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++)
121                 {
122                     image2DBindLayout->insert(
123                         std::make_pair(image2D.binding + index, gl::TextureType::_2D));
124                 }
125             }
126         }
127     }
128 }
129 
GetGeometryShaderTypeFromDrawMode(gl::PrimitiveMode drawMode)130 gl::PrimitiveMode GetGeometryShaderTypeFromDrawMode(gl::PrimitiveMode drawMode)
131 {
132     switch (drawMode)
133     {
134         // Uses the point sprite geometry shader.
135         case gl::PrimitiveMode::Points:
136             return gl::PrimitiveMode::Points;
137 
138         // All line drawing uses the same geometry shader.
139         case gl::PrimitiveMode::Lines:
140         case gl::PrimitiveMode::LineStrip:
141         case gl::PrimitiveMode::LineLoop:
142             return gl::PrimitiveMode::Lines;
143 
144         // The triangle fan primitive is emulated with strips in D3D11.
145         case gl::PrimitiveMode::Triangles:
146         case gl::PrimitiveMode::TriangleFan:
147             return gl::PrimitiveMode::Triangles;
148 
149         // Special case for triangle strips.
150         case gl::PrimitiveMode::TriangleStrip:
151             return gl::PrimitiveMode::TriangleStrip;
152 
153         default:
154             UNREACHABLE();
155             return gl::PrimitiveMode::InvalidEnum;
156     }
157 }
158 
HasFlatInterpolationVarying(const std::vector<sh::ShaderVariable> & varyings)159 bool HasFlatInterpolationVarying(const std::vector<sh::ShaderVariable> &varyings)
160 {
161     // Note: this assumes nested structs can only be packed with one interpolation.
162     for (const auto &varying : varyings)
163     {
164         if (varying.interpolation == sh::INTERPOLATION_FLAT)
165         {
166             return true;
167         }
168     }
169 
170     return false;
171 }
172 
FindFlatInterpolationVaryingPerShader(gl::Shader * shader)173 bool FindFlatInterpolationVaryingPerShader(gl::Shader *shader)
174 {
175     ASSERT(shader);
176     switch (shader->getType())
177     {
178         case gl::ShaderType::Vertex:
179             return HasFlatInterpolationVarying(shader->getOutputVaryings());
180         case gl::ShaderType::Fragment:
181             return HasFlatInterpolationVarying(shader->getInputVaryings());
182         case gl::ShaderType::Geometry:
183             return HasFlatInterpolationVarying(shader->getInputVaryings()) ||
184                    HasFlatInterpolationVarying(shader->getOutputVaryings());
185         default:
186             UNREACHABLE();
187             return false;
188     }
189 }
190 
FindFlatInterpolationVarying(const gl::ShaderMap<gl::Shader * > & shaders)191 bool FindFlatInterpolationVarying(const gl::ShaderMap<gl::Shader *> &shaders)
192 {
193     for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
194     {
195         gl::Shader *shader = shaders[shaderType];
196         if (!shader)
197         {
198             continue;
199         }
200 
201         if (FindFlatInterpolationVaryingPerShader(shader))
202         {
203             return true;
204         }
205     }
206 
207     return false;
208 }
209 
210 // Helper class that gathers uniform info from the default uniform block.
211 class UniformEncodingVisitorD3D : public sh::BlockEncoderVisitor
212 {
213   public:
UniformEncodingVisitorD3D(gl::ShaderType shaderType,HLSLRegisterType registerType,sh::BlockLayoutEncoder * encoder,D3DUniformMap * uniformMapOut)214     UniformEncodingVisitorD3D(gl::ShaderType shaderType,
215                               HLSLRegisterType registerType,
216                               sh::BlockLayoutEncoder *encoder,
217                               D3DUniformMap *uniformMapOut)
218         : sh::BlockEncoderVisitor("", "", encoder),
219           mShaderType(shaderType),
220           mRegisterType(registerType),
221           mUniformMapOut(uniformMapOut)
222     {}
223 
visitNamedSampler(const sh::ShaderVariable & sampler,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)224     void visitNamedSampler(const sh::ShaderVariable &sampler,
225                            const std::string &name,
226                            const std::string &mappedName,
227                            const std::vector<unsigned int> &arraySizes) override
228     {
229         auto uniformMapEntry = mUniformMapOut->find(name);
230         if (uniformMapEntry == mUniformMapOut->end())
231         {
232             (*mUniformMapOut)[name] =
233                 new D3DUniform(sampler.type, mRegisterType, name, sampler.arraySizes, true);
234         }
235     }
236 
encodeVariable(const sh::ShaderVariable & variable,const sh::BlockMemberInfo & variableInfo,const std::string & name,const std::string & mappedName)237     void encodeVariable(const sh::ShaderVariable &variable,
238                         const sh::BlockMemberInfo &variableInfo,
239                         const std::string &name,
240                         const std::string &mappedName) override
241     {
242         auto uniformMapEntry   = mUniformMapOut->find(name);
243         D3DUniform *d3dUniform = nullptr;
244 
245         if (uniformMapEntry != mUniformMapOut->end())
246         {
247             d3dUniform = uniformMapEntry->second;
248         }
249         else
250         {
251             d3dUniform =
252                 new D3DUniform(variable.type, mRegisterType, name, variable.arraySizes, true);
253             (*mUniformMapOut)[name] = d3dUniform;
254         }
255 
256         d3dUniform->registerElement = static_cast<unsigned int>(
257             sh::BlockLayoutEncoder::GetBlockRegisterElement(variableInfo));
258         unsigned int reg =
259             static_cast<unsigned int>(sh::BlockLayoutEncoder::GetBlockRegister(variableInfo));
260 
261         ASSERT(mShaderType != gl::ShaderType::InvalidEnum);
262         d3dUniform->mShaderRegisterIndexes[mShaderType] = reg;
263     }
264 
265   private:
266     gl::ShaderType mShaderType;
267     HLSLRegisterType mRegisterType;
268     D3DUniformMap *mUniformMapOut;
269 };
270 
271 class HLSLBlockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
272 {
273   public:
makeEncoder()274     sh::BlockLayoutEncoder *makeEncoder() override
275     {
276         return new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
277     }
278 };
279 }  // anonymous namespace
280 
281 // D3DUniform Implementation
282 
D3DUniform(GLenum type,HLSLRegisterType reg,const std::string & nameIn,const std::vector<unsigned int> & arraySizesIn,bool defaultBlock)283 D3DUniform::D3DUniform(GLenum type,
284                        HLSLRegisterType reg,
285                        const std::string &nameIn,
286                        const std::vector<unsigned int> &arraySizesIn,
287                        bool defaultBlock)
288     : typeInfo(gl::GetUniformTypeInfo(type)),
289       name(nameIn),
290       arraySizes(arraySizesIn),
291       mShaderData({}),
292       regType(reg),
293       registerCount(0),
294       registerElement(0)
295 {
296     mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
297 
298     // We use data storage for default block uniforms to cache values that are sent to D3D during
299     // rendering
300     // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
301     if (defaultBlock)
302     {
303         // Use the row count as register count, will work for non-square matrices.
304         registerCount = typeInfo.rowCount * getArraySizeProduct();
305     }
306 }
307 
~D3DUniform()308 D3DUniform::~D3DUniform() {}
309 
getArraySizeProduct() const310 unsigned int D3DUniform::getArraySizeProduct() const
311 {
312     return gl::ArraySizeProduct(arraySizes);
313 }
314 
getDataPtrToElement(size_t elementIndex) const315 const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
316 {
317     ASSERT((!isArray() && elementIndex == 0) ||
318            (isArray() && elementIndex < getArraySizeProduct()));
319 
320     if (isSampler())
321     {
322         return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
323     }
324 
325     return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
326 }
327 
isSampler() const328 bool D3DUniform::isSampler() const
329 {
330     return typeInfo.isSampler;
331 }
332 
isImage() const333 bool D3DUniform::isImage() const
334 {
335     return typeInfo.isImageType;
336 }
337 
isImage2D() const338 bool D3DUniform::isImage2D() const
339 {
340     return gl::IsImage2DType(typeInfo.type);
341 }
342 
isReferencedByShader(gl::ShaderType shaderType) const343 bool D3DUniform::isReferencedByShader(gl::ShaderType shaderType) const
344 {
345     return mShaderRegisterIndexes[shaderType] != GL_INVALID_INDEX;
346 }
347 
firstNonNullData() const348 const uint8_t *D3DUniform::firstNonNullData() const
349 {
350     if (!mSamplerData.empty())
351     {
352         return reinterpret_cast<const uint8_t *>(mSamplerData.data());
353     }
354 
355     for (gl::ShaderType shaderType : gl::AllShaderTypes())
356     {
357         if (mShaderData[shaderType])
358         {
359             return mShaderData[shaderType];
360         }
361     }
362 
363     UNREACHABLE();
364     return nullptr;
365 }
366 
367 // D3DInterfaceBlock Implementation
D3DInterfaceBlock()368 D3DInterfaceBlock::D3DInterfaceBlock()
369 {
370     mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
371 }
372 
373 D3DInterfaceBlock::D3DInterfaceBlock(const D3DInterfaceBlock &other) = default;
374 
D3DUniformBlock()375 D3DUniformBlock::D3DUniformBlock()
376 {
377     mUseStructuredBuffers.fill(false);
378     mByteWidths.fill(0u);
379     mStructureByteStrides.fill(0u);
380 }
381 
382 D3DUniformBlock::D3DUniformBlock(const D3DUniformBlock &other) = default;
383 
384 // D3DVarying Implementation
385 
D3DVarying()386 D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) {}
387 
D3DVarying(const std::string & semanticNameIn,unsigned int semanticIndexIn,unsigned int componentCountIn,unsigned int outputSlotIn)388 D3DVarying::D3DVarying(const std::string &semanticNameIn,
389                        unsigned int semanticIndexIn,
390                        unsigned int componentCountIn,
391                        unsigned int outputSlotIn)
392     : semanticName(semanticNameIn),
393       semanticIndex(semanticIndexIn),
394       componentCount(componentCountIn),
395       outputSlot(outputSlotIn)
396 {}
397 
398 // ProgramD3DMetadata Implementation
399 
ProgramD3DMetadata(RendererD3D * renderer,const gl::ShaderMap<const ShaderD3D * > & attachedShaders,EGLenum clientType)400 ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
401                                        const gl::ShaderMap<const ShaderD3D *> &attachedShaders,
402                                        EGLenum clientType)
403     : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
404       mShaderModelSuffix(renderer->getShaderModelSuffix()),
405       mUsesInstancedPointSpriteEmulation(
406           renderer->getFeatures().useInstancedPointSpriteEmulation.enabled),
407       mUsesViewScale(renderer->presentPathFastEnabled()),
408       mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
409       mAttachedShaders(attachedShaders),
410       mClientType(clientType)
411 {}
412 
413 ProgramD3DMetadata::~ProgramD3DMetadata() = default;
414 
getRendererMajorShaderModel() const415 int ProgramD3DMetadata::getRendererMajorShaderModel() const
416 {
417     return mRendererMajorShaderModel;
418 }
419 
usesBroadcast(const gl::State & data) const420 bool ProgramD3DMetadata::usesBroadcast(const gl::State &data) const
421 {
422     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
423     return (shader && shader->usesFragColor() && shader->usesMultipleRenderTargets() &&
424             data.getClientMajorVersion() < 3);
425 }
426 
usesSecondaryColor() const427 bool ProgramD3DMetadata::usesSecondaryColor() const
428 {
429     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
430     return (shader && shader->usesSecondaryColor());
431 }
432 
usesFragDepth() const433 bool ProgramD3DMetadata::usesFragDepth() const
434 {
435     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
436     return (shader && shader->usesFragDepth());
437 }
438 
usesPointCoord() const439 bool ProgramD3DMetadata::usesPointCoord() const
440 {
441     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
442     return (shader && shader->usesPointCoord());
443 }
444 
usesFragCoord() const445 bool ProgramD3DMetadata::usesFragCoord() const
446 {
447     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
448     return (shader && shader->usesFragCoord());
449 }
450 
usesPointSize() const451 bool ProgramD3DMetadata::usesPointSize() const
452 {
453     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Vertex];
454     return (shader && shader->usesPointSize());
455 }
456 
usesInsertedPointCoordValue() const457 bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
458 {
459     return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
460            mRendererMajorShaderModel >= 4;
461 }
462 
usesViewScale() const463 bool ProgramD3DMetadata::usesViewScale() const
464 {
465     return mUsesViewScale;
466 }
467 
hasANGLEMultiviewEnabled() const468 bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
469 {
470     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Vertex];
471     return (shader && shader->hasANGLEMultiviewEnabled());
472 }
473 
usesVertexID() const474 bool ProgramD3DMetadata::usesVertexID() const
475 {
476     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Vertex];
477     return (shader && shader->usesVertexID());
478 }
479 
usesViewID() const480 bool ProgramD3DMetadata::usesViewID() const
481 {
482     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
483     return (shader && shader->usesViewID());
484 }
485 
canSelectViewInVertexShader() const486 bool ProgramD3DMetadata::canSelectViewInVertexShader() const
487 {
488     return mCanSelectViewInVertexShader;
489 }
490 
addsPointCoordToVertexShader() const491 bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
492 {
493     // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
494     // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
495     // Even with a geometry shader, the app can render triangles or lines and reference
496     // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
497     // simplicity, we always add this to the vertex shader when the fragment shader
498     // references gl_PointCoord, even if we could skip it in the geometry shader.
499     return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
500            usesInsertedPointCoordValue();
501 }
502 
usesTransformFeedbackGLPosition() const503 bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
504 {
505     // gl_Position only needs to be outputted from the vertex shader if transform feedback is
506     // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
507     // the vertex shader in this case. This saves us 1 output vector.
508     return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
509 }
510 
usesSystemValuePointSize() const511 bool ProgramD3DMetadata::usesSystemValuePointSize() const
512 {
513     return !mUsesInstancedPointSpriteEmulation && usesPointSize();
514 }
515 
usesMultipleFragmentOuts() const516 bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
517 {
518     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
519     return (shader && shader->usesMultipleRenderTargets());
520 }
521 
usesCustomOutVars() const522 bool ProgramD3DMetadata::usesCustomOutVars() const
523 {
524 
525     const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Vertex];
526     int version                 = shader ? shader->getData().getShaderVersion() : -1;
527 
528     switch (mClientType)
529     {
530         case EGL_OPENGL_API:
531             return version >= 130;
532         default:
533             return version >= 300;
534     }
535 }
536 
getFragmentShader() const537 const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
538 {
539     return mAttachedShaders[gl::ShaderType::Fragment];
540 }
541 
542 // ProgramD3D::GetExecutableTask class
543 class ProgramD3D::GetExecutableTask : public Closure, public d3d::Context
544 {
545   public:
GetExecutableTask(ProgramD3D * program)546     GetExecutableTask(ProgramD3D *program) : mProgram(program) {}
547 
548     virtual angle::Result run() = 0;
549 
operator ()()550     void operator()() override { mResult = run(); }
551 
getResult() const552     angle::Result getResult() const { return mResult; }
getInfoLog() const553     const gl::InfoLog &getInfoLog() const { return mInfoLog; }
getExecutable()554     ShaderExecutableD3D *getExecutable() { return mExecutable; }
555 
handleResult(HRESULT hr,const char * message,const char * file,const char * function,unsigned int line)556     void handleResult(HRESULT hr,
557                       const char *message,
558                       const char *file,
559                       const char *function,
560                       unsigned int line) override
561     {
562         mStoredHR       = hr;
563         mStoredMessage  = message;
564         mStoredFile     = file;
565         mStoredFunction = function;
566         mStoredLine     = line;
567     }
568 
popError(d3d::Context * context)569     void popError(d3d::Context *context)
570     {
571         ASSERT(mStoredFile);
572         ASSERT(mStoredFunction);
573         context->handleResult(mStoredHR, mStoredMessage.c_str(), mStoredFile, mStoredFunction,
574                               mStoredLine);
575     }
576 
577   protected:
578     ProgramD3D *mProgram  = nullptr;
579     angle::Result mResult = angle::Result::Continue;
580     gl::InfoLog mInfoLog;
581     ShaderExecutableD3D *mExecutable = nullptr;
582     HRESULT mStoredHR                = S_OK;
583     std::string mStoredMessage;
584     const char *mStoredFile     = nullptr;
585     const char *mStoredFunction = nullptr;
586     unsigned int mStoredLine    = 0;
587 };
588 
589 // ProgramD3D Implementation
590 
VertexExecutable(const gl::InputLayout & inputLayout,const Signature & signature,ShaderExecutableD3D * shaderExecutable)591 ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
592                                                const Signature &signature,
593                                                ShaderExecutableD3D *shaderExecutable)
594     : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
595 {}
596 
~VertexExecutable()597 ProgramD3D::VertexExecutable::~VertexExecutable()
598 {
599     SafeDelete(mShaderExecutable);
600 }
601 
602 // static
GetAttribType(GLenum type)603 ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
604     GLenum type)
605 {
606     switch (type)
607     {
608         case GL_INT:
609             return HLSLAttribType::SIGNED_INT;
610         case GL_UNSIGNED_INT:
611             return HLSLAttribType::UNSIGNED_INT;
612         case GL_SIGNED_NORMALIZED:
613         case GL_UNSIGNED_NORMALIZED:
614         case GL_FLOAT:
615             return HLSLAttribType::FLOAT;
616         default:
617             UNREACHABLE();
618             return HLSLAttribType::FLOAT;
619     }
620 }
621 
622 // static
getSignature(RendererD3D * renderer,const gl::InputLayout & inputLayout,Signature * signatureOut)623 void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
624                                                 const gl::InputLayout &inputLayout,
625                                                 Signature *signatureOut)
626 {
627     signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
628 
629     for (size_t index = 0; index < inputLayout.size(); ++index)
630     {
631         angle::FormatID vertexFormatID = inputLayout[index];
632         if (vertexFormatID == angle::FormatID::NONE)
633             continue;
634 
635         VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatID);
636         if ((conversionType & VERTEX_CONVERT_GPU) == 0)
637             continue;
638 
639         GLenum componentType   = renderer->getVertexComponentType(vertexFormatID);
640         (*signatureOut)[index] = GetAttribType(componentType);
641     }
642 }
643 
matchesSignature(const Signature & signature) const644 bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
645 {
646     size_t limit = std::max(mSignature.size(), signature.size());
647     for (size_t index = 0; index < limit; ++index)
648     {
649         // treat undefined indexes as FLOAT
650         auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
651         auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
652         if (a != b)
653             return false;
654     }
655 
656     return true;
657 }
658 
PixelExecutable(const std::vector<GLenum> & outputSignature,ShaderExecutableD3D * shaderExecutable)659 ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
660                                              ShaderExecutableD3D *shaderExecutable)
661     : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
662 {}
663 
~PixelExecutable()664 ProgramD3D::PixelExecutable::~PixelExecutable()
665 {
666     SafeDelete(mShaderExecutable);
667 }
668 
ComputeExecutable(const gl::ImageUnitTextureTypeMap & signature,std::unique_ptr<ShaderExecutableD3D> shaderExecutable)669 ProgramD3D::ComputeExecutable::ComputeExecutable(
670     const gl::ImageUnitTextureTypeMap &signature,
671     std::unique_ptr<ShaderExecutableD3D> shaderExecutable)
672     : mSignature(signature), mShaderExecutable(std::move(shaderExecutable))
673 {}
674 
~ComputeExecutable()675 ProgramD3D::ComputeExecutable::~ComputeExecutable() {}
676 
Sampler()677 ProgramD3D::Sampler::Sampler()
678     : active(false), logicalTextureUnit(0), textureType(gl::TextureType::_2D)
679 {}
680 
Image()681 ProgramD3D::Image::Image() : active(false), logicalImageUnit(0) {}
682 
683 unsigned int ProgramD3D::mCurrentSerial = 1;
684 
ProgramD3D(const gl::ProgramState & state,RendererD3D * renderer)685 ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
686     : ProgramImpl(state),
687       mRenderer(renderer),
688       mDynamicHLSL(nullptr),
689       mUsesPointSize(false),
690       mUsesFlatInterpolation(false),
691       mUsedShaderSamplerRanges({}),
692       mDirtySamplerMapping(true),
693       mUsedComputeImageRange(0, 0),
694       mUsedComputeReadonlyImageRange(0, 0),
695       mUsedComputeAtomicCounterRange(0, 0),
696       mSerial(issueSerial())
697 {
698     mDynamicHLSL = new DynamicHLSL(renderer);
699 }
700 
~ProgramD3D()701 ProgramD3D::~ProgramD3D()
702 {
703     reset();
704     SafeDelete(mDynamicHLSL);
705 }
706 
usesPointSpriteEmulation() const707 bool ProgramD3D::usesPointSpriteEmulation() const
708 {
709     return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
710 }
711 
usesGeometryShaderForPointSpriteEmulation() const712 bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
713 {
714     return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
715 }
716 
usesGetDimensionsIgnoresBaseLevel() const717 bool ProgramD3D::usesGetDimensionsIgnoresBaseLevel() const
718 {
719     return mRenderer->getFeatures().getDimensionsIgnoresBaseLevel.enabled;
720 }
721 
usesGeometryShader(const gl::State & state,const gl::PrimitiveMode drawMode) const722 bool ProgramD3D::usesGeometryShader(const gl::State &state, const gl::PrimitiveMode drawMode) const
723 {
724     if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
725     {
726         return true;
727     }
728     if (drawMode != gl::PrimitiveMode::Points)
729     {
730         if (!mUsesFlatInterpolation)
731         {
732             return false;
733         }
734         return state.getProvokingVertex() == gl::ProvokingVertexConvention::LastVertexConvention;
735     }
736     return usesGeometryShaderForPointSpriteEmulation();
737 }
738 
usesInstancedPointSpriteEmulation() const739 bool ProgramD3D::usesInstancedPointSpriteEmulation() const
740 {
741     return mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled;
742 }
743 
getSamplerMapping(gl::ShaderType type,unsigned int samplerIndex,const gl::Caps & caps) const744 GLint ProgramD3D::getSamplerMapping(gl::ShaderType type,
745                                     unsigned int samplerIndex,
746                                     const gl::Caps &caps) const
747 {
748     GLint logicalTextureUnit = -1;
749 
750     ASSERT(type != gl::ShaderType::InvalidEnum);
751 
752     ASSERT(samplerIndex < static_cast<unsigned int>(caps.maxShaderTextureImageUnits[type]));
753 
754     const auto &samplers = mShaderSamplers[type];
755     if (samplerIndex < samplers.size() && samplers[samplerIndex].active)
756     {
757         logicalTextureUnit = samplers[samplerIndex].logicalTextureUnit;
758     }
759 
760     if (logicalTextureUnit >= 0 && logicalTextureUnit < caps.maxCombinedTextureImageUnits)
761     {
762         return logicalTextureUnit;
763     }
764 
765     return -1;
766 }
767 
768 // Returns the texture type for a given Direct3D 9 sampler type and
769 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
getSamplerTextureType(gl::ShaderType type,unsigned int samplerIndex) const770 gl::TextureType ProgramD3D::getSamplerTextureType(gl::ShaderType type,
771                                                   unsigned int samplerIndex) const
772 {
773     ASSERT(type != gl::ShaderType::InvalidEnum);
774 
775     const auto &samplers = mShaderSamplers[type];
776     ASSERT(samplerIndex < samplers.size());
777     ASSERT(samplers[samplerIndex].active);
778 
779     return samplers[samplerIndex].textureType;
780 }
781 
getUsedSamplerRange(gl::ShaderType type) const782 gl::RangeUI ProgramD3D::getUsedSamplerRange(gl::ShaderType type) const
783 {
784     ASSERT(type != gl::ShaderType::InvalidEnum);
785     return mUsedShaderSamplerRanges[type];
786 }
787 
updateSamplerMapping()788 ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping()
789 {
790     if (!mDirtySamplerMapping)
791     {
792         return SamplerMapping::WasClean;
793     }
794 
795     mDirtySamplerMapping = false;
796 
797     // Retrieve sampler uniform values
798     for (const D3DUniform *d3dUniform : mD3DUniforms)
799     {
800         if (!d3dUniform->isSampler())
801             continue;
802 
803         int count = d3dUniform->getArraySizeProduct();
804 
805         for (gl::ShaderType shaderType : gl::AllShaderTypes())
806         {
807             if (!d3dUniform->isReferencedByShader(shaderType))
808             {
809                 continue;
810             }
811 
812             unsigned int firstIndex = d3dUniform->mShaderRegisterIndexes[shaderType];
813 
814             std::vector<Sampler> &samplers = mShaderSamplers[shaderType];
815             for (int i = 0; i < count; i++)
816             {
817                 unsigned int samplerIndex = firstIndex + i;
818 
819                 if (samplerIndex < samplers.size())
820                 {
821                     ASSERT(samplers[samplerIndex].active);
822                     samplers[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
823                 }
824             }
825         }
826     }
827 
828     return SamplerMapping::WasDirty;
829 }
830 
getImageMapping(gl::ShaderType type,unsigned int imageIndex,bool readonly,const gl::Caps & caps) const831 GLint ProgramD3D::getImageMapping(gl::ShaderType type,
832                                   unsigned int imageIndex,
833                                   bool readonly,
834                                   const gl::Caps &caps) const
835 {
836     GLint logicalImageUnit = -1;
837     ASSERT(imageIndex < static_cast<unsigned int>(caps.maxImageUnits));
838     switch (type)
839     {
840         case gl::ShaderType::Compute:
841             if (readonly && imageIndex < mReadonlyImagesCS.size() &&
842                 mReadonlyImagesCS[imageIndex].active)
843             {
844                 logicalImageUnit = mReadonlyImagesCS[imageIndex].logicalImageUnit;
845             }
846             else if (imageIndex < mImagesCS.size() && mImagesCS[imageIndex].active)
847             {
848                 logicalImageUnit = mImagesCS[imageIndex].logicalImageUnit;
849             }
850             break;
851         // TODO(xinghua.cao@intel.com): add image mapping for vertex shader and pixel shader.
852         default:
853             UNREACHABLE();
854     }
855 
856     if (logicalImageUnit >= 0 && logicalImageUnit < caps.maxImageUnits)
857     {
858         return logicalImageUnit;
859     }
860 
861     return -1;
862 }
863 
getUsedImageRange(gl::ShaderType type,bool readonly) const864 gl::RangeUI ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
865 {
866     switch (type)
867     {
868         case gl::ShaderType::Compute:
869             return readonly ? mUsedComputeReadonlyImageRange : mUsedComputeImageRange;
870         // TODO(xinghua.cao@intel.com): add real image range of vertex shader and pixel shader.
871         case gl::ShaderType::Vertex:
872         case gl::ShaderType::Fragment:
873             return {0, 0};
874         default:
875             UNREACHABLE();
876             return {0, 0};
877     }
878 }
879 
880 class ProgramD3D::LoadBinaryTask : public ProgramD3D::GetExecutableTask
881 {
882   public:
LoadBinaryTask(ProgramD3D * program,gl::BinaryInputStream * stream,gl::InfoLog & infoLog)883     LoadBinaryTask(ProgramD3D *program, gl::BinaryInputStream *stream, gl::InfoLog &infoLog)
884         : ProgramD3D::GetExecutableTask(program)
885     {
886         ASSERT(mProgram);
887         ASSERT(stream);
888 
889         // Copy the remaining data from the stream locally so that the client can't modify it when
890         // loading off thread.
891         size_t dataSize    = stream->remainingSize();
892         mDataCopySucceeded = mStreamData.resize(dataSize);
893         if (mDataCopySucceeded)
894         {
895             memcpy(mStreamData.data(), stream->data() + stream->offset(), dataSize);
896         }
897     }
898 
run()899     angle::Result run() override
900     {
901         if (!mDataCopySucceeded)
902         {
903             mInfoLog << "Failed to copy program binary data to local buffer.";
904             return angle::Result::Incomplete;
905         }
906 
907         gl::BinaryInputStream stream(mStreamData.data(), mStreamData.size());
908         return mProgram->loadBinaryShaderExecutables(this, &stream, mInfoLog);
909     }
910 
911   private:
912     bool mDataCopySucceeded;
913     angle::MemoryBuffer mStreamData;
914 };
915 
916 class ProgramD3D::LoadBinaryLinkEvent final : public LinkEvent
917 {
918   public:
LoadBinaryLinkEvent(std::shared_ptr<WorkerThreadPool> workerPool,ProgramD3D * program,gl::BinaryInputStream * stream,gl::InfoLog & infoLog)919     LoadBinaryLinkEvent(std::shared_ptr<WorkerThreadPool> workerPool,
920                         ProgramD3D *program,
921                         gl::BinaryInputStream *stream,
922                         gl::InfoLog &infoLog)
923         : mTask(std::make_shared<ProgramD3D::LoadBinaryTask>(program, stream, infoLog)),
924           mWaitableEvent(angle::WorkerThreadPool::PostWorkerTask(workerPool, mTask))
925     {}
926 
wait(const gl::Context * context)927     angle::Result wait(const gl::Context *context) override
928     {
929         mWaitableEvent->wait();
930 
931         // Continue and Incomplete are not errors. For Stop, pass the error to the ContextD3D.
932         if (mTask->getResult() != angle::Result::Stop)
933         {
934             return angle::Result::Continue;
935         }
936 
937         ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
938         mTask->popError(contextD3D);
939         return angle::Result::Stop;
940     }
941 
isLinking()942     bool isLinking() override { return !mWaitableEvent->isReady(); }
943 
944   private:
945     std::shared_ptr<ProgramD3D::LoadBinaryTask> mTask;
946     std::shared_ptr<WaitableEvent> mWaitableEvent;
947 };
948 
load(const gl::Context * context,gl::BinaryInputStream * stream,gl::InfoLog & infoLog)949 std::unique_ptr<rx::LinkEvent> ProgramD3D::load(const gl::Context *context,
950                                                 gl::BinaryInputStream *stream,
951                                                 gl::InfoLog &infoLog)
952 {
953 
954     // TODO(jmadill): Use Renderer from contextImpl.
955 
956     reset();
957 
958     DeviceIdentifier binaryDeviceIdentifier = {};
959     stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
960                       sizeof(DeviceIdentifier));
961 
962     DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
963     if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
964     {
965         infoLog << "Invalid program binary, device configuration has changed.";
966         return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
967     }
968 
969     int compileFlags = stream->readInt<int>();
970     if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
971     {
972         infoLog << "Mismatched compilation flags.";
973         return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
974     }
975 
976     for (int &index : mAttribLocationToD3DSemantic)
977     {
978         stream->readInt(&index);
979     }
980 
981     for (gl::ShaderType shaderType : gl::AllShaderTypes())
982     {
983         const unsigned int samplerCount = stream->readInt<unsigned int>();
984         for (unsigned int i = 0; i < samplerCount; ++i)
985         {
986             Sampler sampler;
987             stream->readBool(&sampler.active);
988             stream->readInt(&sampler.logicalTextureUnit);
989             stream->readEnum(&sampler.textureType);
990             mShaderSamplers[shaderType].push_back(sampler);
991         }
992 
993         unsigned int samplerRangeLow, samplerRangeHigh;
994         stream->readInt(&samplerRangeLow);
995         stream->readInt(&samplerRangeHigh);
996         mUsedShaderSamplerRanges[shaderType] = gl::RangeUI(samplerRangeLow, samplerRangeHigh);
997     }
998 
999     const unsigned int csImageCount = stream->readInt<unsigned int>();
1000     for (unsigned int i = 0; i < csImageCount; ++i)
1001     {
1002         Image image;
1003         stream->readBool(&image.active);
1004         stream->readInt(&image.logicalImageUnit);
1005         mImagesCS.push_back(image);
1006     }
1007 
1008     const unsigned int csReadonlyImageCount = stream->readInt<unsigned int>();
1009     for (unsigned int i = 0; i < csReadonlyImageCount; ++i)
1010     {
1011         Image image;
1012         stream->readBool(&image.active);
1013         stream->readInt(&image.logicalImageUnit);
1014         mReadonlyImagesCS.push_back(image);
1015     }
1016 
1017     unsigned int computeImageRangeLow, computeImageRangeHigh, computeReadonlyImageRangeLow,
1018         computeReadonlyImageRangeHigh;
1019     stream->readInt(&computeImageRangeLow);
1020     stream->readInt(&computeImageRangeHigh);
1021     stream->readInt(&computeReadonlyImageRangeLow);
1022     stream->readInt(&computeReadonlyImageRangeHigh);
1023     mUsedComputeImageRange = gl::RangeUI(computeImageRangeLow, computeImageRangeHigh);
1024     mUsedComputeReadonlyImageRange =
1025         gl::RangeUI(computeReadonlyImageRangeLow, computeReadonlyImageRangeHigh);
1026 
1027     unsigned int atomicCounterRangeLow, atomicCounterRangeHigh;
1028     stream->readInt(&atomicCounterRangeLow);
1029     stream->readInt(&atomicCounterRangeHigh);
1030     mUsedComputeAtomicCounterRange = gl::RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
1031 
1032     const unsigned int shaderStorageBlockCount = stream->readInt<unsigned int>();
1033     if (stream->error())
1034     {
1035         infoLog << "Invalid program binary.";
1036         return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
1037     }
1038 
1039     ASSERT(mD3DShaderStorageBlocks.empty());
1040     for (unsigned int blockIndex = 0; blockIndex < shaderStorageBlockCount; ++blockIndex)
1041     {
1042         D3DInterfaceBlock shaderStorageBlock;
1043         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1044         {
1045             stream->readInt(&shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
1046         }
1047         mD3DShaderStorageBlocks.push_back(shaderStorageBlock);
1048     }
1049 
1050     const unsigned int image2DUniformCount = stream->readInt<unsigned int>();
1051     if (stream->error())
1052     {
1053         infoLog << "Invalid program binary.";
1054         return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
1055     }
1056 
1057     ASSERT(mImage2DUniforms.empty());
1058     for (unsigned int image2DUniformIndex = 0; image2DUniformIndex < image2DUniformCount;
1059          ++image2DUniformIndex)
1060     {
1061         sh::ShaderVariable image2Duniform;
1062         gl::LoadShaderVar(stream, &image2Duniform);
1063         mImage2DUniforms.push_back(image2Duniform);
1064     }
1065 
1066     for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS; ++ii)
1067     {
1068         unsigned int index                             = stream->readInt<unsigned int>();
1069         mComputeAtomicCounterBufferRegisterIndices[ii] = index;
1070     }
1071 
1072     const unsigned int uniformCount = stream->readInt<unsigned int>();
1073     if (stream->error())
1074     {
1075         infoLog << "Invalid program binary.";
1076         return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
1077     }
1078 
1079     const auto &linkedUniforms = mState.getUniforms();
1080     ASSERT(mD3DUniforms.empty());
1081     for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
1082     {
1083         const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
1084 
1085         D3DUniform *d3dUniform =
1086             new D3DUniform(linkedUniform.type, HLSLRegisterType::None, linkedUniform.name,
1087                            linkedUniform.arraySizes, linkedUniform.isInDefaultBlock());
1088         stream->readInt<HLSLRegisterType>(&d3dUniform->regType);
1089         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1090         {
1091             stream->readInt(&d3dUniform->mShaderRegisterIndexes[shaderType]);
1092         }
1093         stream->readInt(&d3dUniform->registerCount);
1094         stream->readInt(&d3dUniform->registerElement);
1095 
1096         mD3DUniforms.push_back(d3dUniform);
1097     }
1098 
1099     const unsigned int blockCount = stream->readInt<unsigned int>();
1100     if (stream->error())
1101     {
1102         infoLog << "Invalid program binary.";
1103         return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
1104     }
1105 
1106     ASSERT(mD3DUniformBlocks.empty());
1107     for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
1108     {
1109         D3DUniformBlock uniformBlock;
1110         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1111         {
1112             stream->readInt(&uniformBlock.mShaderRegisterIndexes[shaderType]);
1113             stream->readBool(&uniformBlock.mUseStructuredBuffers[shaderType]);
1114             stream->readInt(&uniformBlock.mByteWidths[shaderType]);
1115             stream->readInt(&uniformBlock.mStructureByteStrides[shaderType]);
1116         }
1117         mD3DUniformBlocks.push_back(uniformBlock);
1118     }
1119 
1120     const unsigned int streamOutVaryingCount = stream->readInt<unsigned int>();
1121     mStreamOutVaryings.resize(streamOutVaryingCount);
1122     for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
1123     {
1124         D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
1125 
1126         stream->readString(&varying->semanticName);
1127         stream->readInt(&varying->semanticIndex);
1128         stream->readInt(&varying->componentCount);
1129         stream->readInt(&varying->outputSlot);
1130     }
1131 
1132     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1133     {
1134         stream->readString(&mShaderHLSL[shaderType]);
1135         stream->readBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
1136                           sizeof(angle::CompilerWorkaroundsD3D));
1137     }
1138 
1139     stream->readBool(&mUsesFragDepth);
1140     stream->readBool(&mHasANGLEMultiviewEnabled);
1141     stream->readBool(&mUsesVertexID);
1142     stream->readBool(&mUsesViewID);
1143     stream->readBool(&mUsesPointSize);
1144     stream->readBool(&mUsesFlatInterpolation);
1145 
1146     const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
1147     mPixelShaderKey.resize(pixelShaderKeySize);
1148     for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
1149          pixelShaderKeyIndex++)
1150     {
1151         stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
1152         stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
1153         stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
1154         stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputLocation);
1155         stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
1156     }
1157 
1158     stream->readString(&mGeometryShaderPreamble);
1159 
1160     return std::make_unique<LoadBinaryLinkEvent>(context->getWorkerThreadPool(), this, stream,
1161                                                  infoLog);
1162 }
1163 
loadBinaryShaderExecutables(d3d::Context * contextD3D,gl::BinaryInputStream * stream,gl::InfoLog & infoLog)1164 angle::Result ProgramD3D::loadBinaryShaderExecutables(d3d::Context *contextD3D,
1165                                                       gl::BinaryInputStream *stream,
1166                                                       gl::InfoLog &infoLog)
1167 {
1168     const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
1169 
1170     bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
1171 
1172     const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
1173     for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
1174          vertexShaderIndex++)
1175     {
1176         size_t inputLayoutSize = stream->readInt<size_t>();
1177         gl::InputLayout inputLayout(inputLayoutSize, angle::FormatID::NONE);
1178 
1179         for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
1180         {
1181             inputLayout[inputIndex] = stream->readInt<angle::FormatID>();
1182         }
1183 
1184         unsigned int vertexShaderSize             = stream->readInt<unsigned int>();
1185         const unsigned char *vertexShaderFunction = binary + stream->offset();
1186 
1187         ShaderExecutableD3D *shaderExecutable = nullptr;
1188 
1189         ANGLE_TRY(mRenderer->loadExecutable(contextD3D, vertexShaderFunction, vertexShaderSize,
1190                                             gl::ShaderType::Vertex, mStreamOutVaryings,
1191                                             separateAttribs, &shaderExecutable));
1192 
1193         if (!shaderExecutable)
1194         {
1195             infoLog << "Could not create vertex shader.";
1196             return angle::Result::Incomplete;
1197         }
1198 
1199         // generated converted input layout
1200         VertexExecutable::Signature signature;
1201         VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
1202 
1203         // add new binary
1204         mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
1205             new VertexExecutable(inputLayout, signature, shaderExecutable)));
1206 
1207         stream->skip(vertexShaderSize);
1208     }
1209 
1210     const size_t pixelShaderCount = stream->readInt<unsigned int>();
1211     for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
1212     {
1213         const size_t outputCount = stream->readInt<unsigned int>();
1214         std::vector<GLenum> outputs(outputCount);
1215         for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
1216         {
1217             stream->readInt(&outputs[outputIndex]);
1218         }
1219 
1220         const size_t pixelShaderSize             = stream->readInt<unsigned int>();
1221         const unsigned char *pixelShaderFunction = binary + stream->offset();
1222         ShaderExecutableD3D *shaderExecutable    = nullptr;
1223 
1224         ANGLE_TRY(mRenderer->loadExecutable(contextD3D, pixelShaderFunction, pixelShaderSize,
1225                                             gl::ShaderType::Fragment, mStreamOutVaryings,
1226                                             separateAttribs, &shaderExecutable));
1227 
1228         if (!shaderExecutable)
1229         {
1230             infoLog << "Could not create pixel shader.";
1231             return angle::Result::Incomplete;
1232         }
1233 
1234         // add new binary
1235         mPixelExecutables.push_back(
1236             std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
1237 
1238         stream->skip(pixelShaderSize);
1239     }
1240 
1241     for (auto &geometryExe : mGeometryExecutables)
1242     {
1243         unsigned int geometryShaderSize = stream->readInt<unsigned int>();
1244         if (geometryShaderSize == 0)
1245         {
1246             continue;
1247         }
1248 
1249         const unsigned char *geometryShaderFunction = binary + stream->offset();
1250 
1251         ShaderExecutableD3D *geometryExecutable = nullptr;
1252         ANGLE_TRY(mRenderer->loadExecutable(contextD3D, geometryShaderFunction, geometryShaderSize,
1253                                             gl::ShaderType::Geometry, mStreamOutVaryings,
1254                                             separateAttribs, &geometryExecutable));
1255 
1256         if (!geometryExecutable)
1257         {
1258             infoLog << "Could not create geometry shader.";
1259             return angle::Result::Incomplete;
1260         }
1261 
1262         geometryExe.reset(geometryExecutable);
1263 
1264         stream->skip(geometryShaderSize);
1265     }
1266 
1267     const size_t computeShaderCount = stream->readInt<unsigned int>();
1268     for (size_t computeShaderIndex = 0; computeShaderIndex < computeShaderCount;
1269          computeShaderIndex++)
1270     {
1271         const size_t signatureCount = stream->readInt<unsigned int>();
1272         gl::ImageUnitTextureTypeMap signatures;
1273         for (size_t signatureIndex = 0; signatureIndex < signatureCount; signatureIndex++)
1274         {
1275             unsigned int imageUint;
1276             gl::TextureType textureType;
1277             stream->readInt<unsigned int>(&imageUint);
1278             stream->readInt<gl::TextureType>(&textureType);
1279             signatures.insert(std::pair<unsigned int, gl::TextureType>(imageUint, textureType));
1280         }
1281 
1282         const size_t computeShaderSize             = stream->readInt<unsigned int>();
1283         const unsigned char *computeShaderFunction = binary + stream->offset();
1284 
1285         ShaderExecutableD3D *computeExecutable = nullptr;
1286         ANGLE_TRY(mRenderer->loadExecutable(contextD3D, computeShaderFunction, computeShaderSize,
1287                                             gl::ShaderType::Compute, std::vector<D3DVarying>(),
1288                                             false, &computeExecutable));
1289 
1290         if (!computeExecutable)
1291         {
1292             infoLog << "Could not create compute shader.";
1293             return angle::Result::Incomplete;
1294         }
1295 
1296         // add new binary
1297         mComputeExecutables.push_back(std::unique_ptr<ComputeExecutable>(new ComputeExecutable(
1298             signatures, std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
1299 
1300         stream->skip(computeShaderSize);
1301     }
1302 
1303     const size_t bindLayoutCount = stream->readInt<unsigned int>();
1304     for (size_t bindLayoutIndex = 0; bindLayoutIndex < bindLayoutCount; bindLayoutIndex++)
1305     {
1306         mComputeShaderImage2DBindLayoutCache.insert(std::pair<unsigned int, gl::TextureType>(
1307             stream->readInt<unsigned int>(), gl::TextureType::_2D));
1308     }
1309 
1310     initializeUniformStorage(mState.getProgramExecutable().getLinkedShaderStages());
1311 
1312     dirtyAllUniforms();
1313 
1314     return angle::Result::Continue;
1315 }
1316 
save(const gl::Context * context,gl::BinaryOutputStream * stream)1317 void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream)
1318 {
1319     // Output the DeviceIdentifier before we output any shader code
1320     // When we load the binary again later, we can validate the device identifier before trying to
1321     // compile any HLSL
1322     DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
1323     stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
1324                        sizeof(DeviceIdentifier));
1325 
1326     stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
1327 
1328     for (int d3dSemantic : mAttribLocationToD3DSemantic)
1329     {
1330         stream->writeInt(d3dSemantic);
1331     }
1332 
1333     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1334     {
1335         stream->writeInt(mShaderSamplers[shaderType].size());
1336         for (unsigned int i = 0; i < mShaderSamplers[shaderType].size(); ++i)
1337         {
1338             stream->writeInt(mShaderSamplers[shaderType][i].active);
1339             stream->writeInt(mShaderSamplers[shaderType][i].logicalTextureUnit);
1340             stream->writeEnum(mShaderSamplers[shaderType][i].textureType);
1341         }
1342 
1343         stream->writeInt(mUsedShaderSamplerRanges[shaderType].low());
1344         stream->writeInt(mUsedShaderSamplerRanges[shaderType].high());
1345     }
1346 
1347     stream->writeInt(mImagesCS.size());
1348     for (unsigned int i = 0; i < mImagesCS.size(); ++i)
1349     {
1350         stream->writeInt(mImagesCS[i].active);
1351         stream->writeInt(mImagesCS[i].logicalImageUnit);
1352     }
1353 
1354     stream->writeInt(mReadonlyImagesCS.size());
1355     for (unsigned int i = 0; i < mReadonlyImagesCS.size(); ++i)
1356     {
1357         stream->writeInt(mReadonlyImagesCS[i].active);
1358         stream->writeInt(mReadonlyImagesCS[i].logicalImageUnit);
1359     }
1360 
1361     stream->writeInt(mUsedComputeImageRange.low());
1362     stream->writeInt(mUsedComputeImageRange.high());
1363     stream->writeInt(mUsedComputeReadonlyImageRange.low());
1364     stream->writeInt(mUsedComputeReadonlyImageRange.high());
1365     stream->writeInt(mUsedComputeAtomicCounterRange.low());
1366     stream->writeInt(mUsedComputeAtomicCounterRange.high());
1367 
1368     stream->writeInt(mD3DShaderStorageBlocks.size());
1369     for (const D3DInterfaceBlock &shaderStorageBlock : mD3DShaderStorageBlocks)
1370     {
1371         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1372         {
1373             stream->writeIntOrNegOne(shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
1374         }
1375     }
1376 
1377     stream->writeInt(mImage2DUniforms.size());
1378     for (const sh::ShaderVariable &image2DUniform : mImage2DUniforms)
1379     {
1380         gl::WriteShaderVar(stream, image2DUniform);
1381     }
1382 
1383     for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS; ++ii)
1384     {
1385         stream->writeInt(mComputeAtomicCounterBufferRegisterIndices[ii]);
1386     }
1387 
1388     stream->writeInt(mD3DUniforms.size());
1389     for (const D3DUniform *uniform : mD3DUniforms)
1390     {
1391         // Type, name and arraySize are redundant, so aren't stored in the binary.
1392         stream->writeInt(static_cast<unsigned int>(uniform->regType));
1393         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1394         {
1395             stream->writeIntOrNegOne(uniform->mShaderRegisterIndexes[shaderType]);
1396         }
1397         stream->writeInt(uniform->registerCount);
1398         stream->writeInt(uniform->registerElement);
1399     }
1400 
1401     stream->writeInt(mD3DUniformBlocks.size());
1402     for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
1403     {
1404         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1405         {
1406             stream->writeIntOrNegOne(uniformBlock.mShaderRegisterIndexes[shaderType]);
1407             stream->writeInt(uniformBlock.mUseStructuredBuffers[shaderType]);
1408             stream->writeInt(uniformBlock.mByteWidths[shaderType]);
1409             stream->writeInt(uniformBlock.mStructureByteStrides[shaderType]);
1410         }
1411     }
1412 
1413     stream->writeInt(mStreamOutVaryings.size());
1414     for (const auto &varying : mStreamOutVaryings)
1415     {
1416         stream->writeString(varying.semanticName);
1417         stream->writeInt(varying.semanticIndex);
1418         stream->writeInt(varying.componentCount);
1419         stream->writeInt(varying.outputSlot);
1420     }
1421 
1422     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1423     {
1424         stream->writeString(mShaderHLSL[shaderType]);
1425         stream->writeBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
1426                            sizeof(angle::CompilerWorkaroundsD3D));
1427     }
1428 
1429     stream->writeInt(mUsesFragDepth);
1430     stream->writeInt(mHasANGLEMultiviewEnabled);
1431     stream->writeInt(mUsesVertexID);
1432     stream->writeInt(mUsesViewID);
1433     stream->writeInt(mUsesPointSize);
1434     stream->writeInt(mUsesFlatInterpolation);
1435 
1436     const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
1437     stream->writeInt(pixelShaderKey.size());
1438     for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
1439          pixelShaderKeyIndex++)
1440     {
1441         const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
1442         stream->writeInt(variable.type);
1443         stream->writeString(variable.name);
1444         stream->writeString(variable.source);
1445         stream->writeInt(variable.outputLocation);
1446         stream->writeInt(variable.outputIndex);
1447     }
1448 
1449     stream->writeString(mGeometryShaderPreamble);
1450 
1451     stream->writeInt(mVertexExecutables.size());
1452     for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
1453          vertexExecutableIndex++)
1454     {
1455         VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
1456 
1457         const auto &inputLayout = vertexExecutable->inputs();
1458         stream->writeInt(inputLayout.size());
1459 
1460         for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
1461         {
1462             stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex]));
1463         }
1464 
1465         size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1466         stream->writeInt(vertexShaderSize);
1467 
1468         const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
1469         stream->writeBytes(vertexBlob, vertexShaderSize);
1470     }
1471 
1472     stream->writeInt(mPixelExecutables.size());
1473     for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
1474          pixelExecutableIndex++)
1475     {
1476         PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
1477 
1478         const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
1479         stream->writeInt(outputs.size());
1480         for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1481         {
1482             stream->writeInt(outputs[outputIndex]);
1483         }
1484 
1485         size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1486         stream->writeInt(pixelShaderSize);
1487 
1488         const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
1489         stream->writeBytes(pixelBlob, pixelShaderSize);
1490     }
1491 
1492     for (auto const &geometryExecutable : mGeometryExecutables)
1493     {
1494         if (!geometryExecutable)
1495         {
1496             stream->writeInt(0);
1497             continue;
1498         }
1499 
1500         size_t geometryShaderSize = geometryExecutable->getLength();
1501         stream->writeInt(geometryShaderSize);
1502         stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
1503     }
1504 
1505     stream->writeInt(mComputeExecutables.size());
1506     for (size_t computeExecutableIndex = 0; computeExecutableIndex < mComputeExecutables.size();
1507          computeExecutableIndex++)
1508     {
1509         ComputeExecutable *computeExecutable = mComputeExecutables[computeExecutableIndex].get();
1510 
1511         const gl::ImageUnitTextureTypeMap signatures = computeExecutable->signature();
1512         stream->writeInt(signatures.size());
1513         for (const auto &signature : signatures)
1514         {
1515             stream->writeInt(signature.first);
1516             stream->writeInt(static_cast<unsigned int>(signature.second));
1517         }
1518 
1519         size_t computeShaderSize = computeExecutable->shaderExecutable()->getLength();
1520         stream->writeInt(computeShaderSize);
1521 
1522         const uint8_t *computeBlob = computeExecutable->shaderExecutable()->getFunction();
1523         stream->writeBytes(computeBlob, computeShaderSize);
1524     }
1525 
1526     stream->writeInt(mComputeShaderImage2DBindLayoutCache.size());
1527     for (auto &image2DBindLayout : mComputeShaderImage2DBindLayoutCache)
1528     {
1529         stream->writeInt(image2DBindLayout.first);
1530     }
1531 }
1532 
setBinaryRetrievableHint(bool)1533 void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */) {}
1534 
setSeparable(bool)1535 void ProgramD3D::setSeparable(bool /* separable */) {}
1536 
getPixelExecutableForCachedOutputLayout(d3d::Context * context,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1537 angle::Result ProgramD3D::getPixelExecutableForCachedOutputLayout(
1538     d3d::Context *context,
1539     ShaderExecutableD3D **outExecutable,
1540     gl::InfoLog *infoLog)
1541 {
1542     if (mCachedPixelExecutableIndex.valid())
1543     {
1544         *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
1545         return angle::Result::Continue;
1546     }
1547 
1548     std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
1549         mShaderHLSL[gl::ShaderType::Fragment], mPixelShaderKey, mUsesFragDepth,
1550         mPixelShaderOutputLayoutCache);
1551 
1552     // Generate new pixel executable
1553     ShaderExecutableD3D *pixelExecutable = nullptr;
1554 
1555     gl::InfoLog tempInfoLog;
1556     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1557 
1558     ANGLE_TRY(mRenderer->compileToExecutable(
1559         context, *currentInfoLog, finalPixelHLSL, gl::ShaderType::Fragment, mStreamOutVaryings,
1560         (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1561         mShaderWorkarounds[gl::ShaderType::Fragment], &pixelExecutable));
1562 
1563     if (pixelExecutable)
1564     {
1565         mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
1566             new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
1567         mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
1568     }
1569     else if (!infoLog)
1570     {
1571         ERR() << "Error compiling dynamic pixel executable:" << std::endl
1572               << tempInfoLog.str() << std::endl;
1573     }
1574 
1575     *outExecutable = pixelExecutable;
1576     return angle::Result::Continue;
1577 }
1578 
getVertexExecutableForCachedInputLayout(d3d::Context * context,ShaderExecutableD3D ** outExectuable,gl::InfoLog * infoLog)1579 angle::Result ProgramD3D::getVertexExecutableForCachedInputLayout(
1580     d3d::Context *context,
1581     ShaderExecutableD3D **outExectuable,
1582     gl::InfoLog *infoLog)
1583 {
1584     if (mCachedVertexExecutableIndex.valid())
1585     {
1586         *outExectuable =
1587             mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
1588         return angle::Result::Continue;
1589     }
1590 
1591     // Generate new dynamic layout with attribute conversions
1592     std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
1593         mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout, mState.getProgramInputs());
1594 
1595     // Generate new vertex executable
1596     ShaderExecutableD3D *vertexExecutable = nullptr;
1597 
1598     gl::InfoLog tempInfoLog;
1599     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1600 
1601     ANGLE_TRY(mRenderer->compileToExecutable(
1602         context, *currentInfoLog, finalVertexHLSL, gl::ShaderType::Vertex, mStreamOutVaryings,
1603         (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1604         mShaderWorkarounds[gl::ShaderType::Vertex], &vertexExecutable));
1605 
1606     if (vertexExecutable)
1607     {
1608         mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
1609             new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
1610         mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
1611     }
1612     else if (!infoLog)
1613     {
1614         ERR() << "Error compiling dynamic vertex executable:" << std::endl
1615               << tempInfoLog.str() << std::endl;
1616     }
1617 
1618     *outExectuable = vertexExecutable;
1619     return angle::Result::Continue;
1620 }
1621 
getGeometryExecutableForPrimitiveType(d3d::Context * context,const gl::State & state,gl::PrimitiveMode drawMode,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1622 angle::Result ProgramD3D::getGeometryExecutableForPrimitiveType(d3d::Context *context,
1623                                                                 const gl::State &state,
1624                                                                 gl::PrimitiveMode drawMode,
1625                                                                 ShaderExecutableD3D **outExecutable,
1626                                                                 gl::InfoLog *infoLog)
1627 {
1628     if (outExecutable)
1629     {
1630         *outExecutable = nullptr;
1631     }
1632 
1633     // Return a null shader if the current rendering doesn't use a geometry shader
1634     if (!usesGeometryShader(state, drawMode))
1635     {
1636         return angle::Result::Continue;
1637     }
1638 
1639     gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1640 
1641     if (mGeometryExecutables[geometryShaderType])
1642     {
1643         if (outExecutable)
1644         {
1645             *outExecutable = mGeometryExecutables[geometryShaderType].get();
1646         }
1647         return angle::Result::Continue;
1648     }
1649     const gl::Caps &caps     = state.getCaps();
1650     std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
1651         caps, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
1652         mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
1653         usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
1654 
1655     gl::InfoLog tempInfoLog;
1656     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1657 
1658     ShaderExecutableD3D *geometryExecutable = nullptr;
1659     angle::Result result                    = mRenderer->compileToExecutable(
1660         context, *currentInfoLog, geometryHLSL, gl::ShaderType::Geometry, mStreamOutVaryings,
1661         (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
1662         angle::CompilerWorkaroundsD3D(), &geometryExecutable);
1663 
1664     if (!infoLog && result == angle::Result::Stop)
1665     {
1666         ERR() << "Error compiling dynamic geometry executable:" << std::endl
1667               << tempInfoLog.str() << std::endl;
1668     }
1669 
1670     if (geometryExecutable != nullptr)
1671     {
1672         mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
1673     }
1674 
1675     if (outExecutable)
1676     {
1677         *outExecutable = mGeometryExecutables[geometryShaderType].get();
1678     }
1679     return result;
1680 }
1681 
1682 class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
1683 {
1684   public:
GetVertexExecutableTask(ProgramD3D * program)1685     GetVertexExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
run()1686     angle::Result run() override
1687     {
1688         if (!mProgram->mState.getAttachedShader(gl::ShaderType::Vertex))
1689         {
1690             return angle::Result::Continue;
1691         }
1692 
1693         mProgram->updateCachedInputLayoutFromShader();
1694 
1695         ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(this, &mExecutable, &mInfoLog));
1696 
1697         return angle::Result::Continue;
1698     }
1699 };
1700 
updateCachedInputLayoutFromShader()1701 void ProgramD3D::updateCachedInputLayoutFromShader()
1702 {
1703     GetDefaultInputLayoutFromShader(mState.getAttachedShader(gl::ShaderType::Vertex),
1704                                     &mCachedInputLayout);
1705     VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
1706     updateCachedVertexExecutableIndex();
1707 }
1708 
1709 class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
1710 {
1711   public:
GetPixelExecutableTask(ProgramD3D * program)1712     GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
run()1713     angle::Result run() override
1714     {
1715         if (!mProgram->mState.getAttachedShader(gl::ShaderType::Fragment))
1716         {
1717             return angle::Result::Continue;
1718         }
1719 
1720         mProgram->updateCachedOutputLayoutFromShader();
1721 
1722         ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(this, &mExecutable, &mInfoLog));
1723 
1724         return angle::Result::Continue;
1725     }
1726 };
1727 
updateCachedOutputLayoutFromShader()1728 void ProgramD3D::updateCachedOutputLayoutFromShader()
1729 {
1730     GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
1731     updateCachedPixelExecutableIndex();
1732 }
1733 
updateCachedImage2DBindLayoutFromComputeShader()1734 void ProgramD3D::updateCachedImage2DBindLayoutFromComputeShader()
1735 {
1736     GetDefaultImage2DBindLayoutFromComputeShader(mImage2DUniforms,
1737                                                  &mComputeShaderImage2DBindLayoutCache);
1738     updateCachedComputeExecutableIndex();
1739 }
1740 
1741 class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
1742 {
1743   public:
GetGeometryExecutableTask(ProgramD3D * program,const gl::State & state)1744     GetGeometryExecutableTask(ProgramD3D *program, const gl::State &state)
1745         : GetExecutableTask(program), mState(state)
1746     {}
1747 
run()1748     angle::Result run() override
1749     {
1750         // Auto-generate the geometry shader here, if we expect to be using point rendering in
1751         // D3D11.
1752         if (mProgram->usesGeometryShader(mState, gl::PrimitiveMode::Points))
1753         {
1754             ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(
1755                 this, mState, gl::PrimitiveMode::Points, &mExecutable, &mInfoLog));
1756         }
1757 
1758         return angle::Result::Continue;
1759     }
1760 
1761   private:
1762     const gl::State &mState;
1763 };
1764 
1765 class ProgramD3D::GetComputeExecutableTask : public ProgramD3D::GetExecutableTask
1766 {
1767   public:
GetComputeExecutableTask(ProgramD3D * program)1768     GetComputeExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
run()1769     angle::Result run() override
1770     {
1771         mProgram->updateCachedImage2DBindLayoutFromComputeShader();
1772         ShaderExecutableD3D *computeExecutable = nullptr;
1773         ANGLE_TRY(mProgram->getComputeExecutableForImage2DBindLayout(this, &computeExecutable,
1774                                                                      &mInfoLog));
1775 
1776         return computeExecutable ? angle::Result::Continue : angle::Result::Incomplete;
1777     }
1778 };
1779 
1780 // The LinkEvent implementation for linking a rendering(VS, FS, GS) program.
1781 class ProgramD3D::GraphicsProgramLinkEvent final : public LinkEvent
1782 {
1783   public:
GraphicsProgramLinkEvent(gl::InfoLog & infoLog,std::shared_ptr<WorkerThreadPool> workerPool,std::shared_ptr<ProgramD3D::GetVertexExecutableTask> vertexTask,std::shared_ptr<ProgramD3D::GetPixelExecutableTask> pixelTask,std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> geometryTask,bool useGS,const ShaderD3D * vertexShader,const ShaderD3D * fragmentShader)1784     GraphicsProgramLinkEvent(gl::InfoLog &infoLog,
1785                              std::shared_ptr<WorkerThreadPool> workerPool,
1786                              std::shared_ptr<ProgramD3D::GetVertexExecutableTask> vertexTask,
1787                              std::shared_ptr<ProgramD3D::GetPixelExecutableTask> pixelTask,
1788                              std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> geometryTask,
1789                              bool useGS,
1790                              const ShaderD3D *vertexShader,
1791                              const ShaderD3D *fragmentShader)
1792         : mInfoLog(infoLog),
1793           mVertexTask(vertexTask),
1794           mPixelTask(pixelTask),
1795           mGeometryTask(geometryTask),
1796           mWaitEvents({{std::shared_ptr<WaitableEvent>(
1797                             angle::WorkerThreadPool::PostWorkerTask(workerPool, mVertexTask)),
1798                         std::shared_ptr<WaitableEvent>(
1799                             angle::WorkerThreadPool::PostWorkerTask(workerPool, mPixelTask)),
1800                         std::shared_ptr<WaitableEvent>(
1801                             angle::WorkerThreadPool::PostWorkerTask(workerPool, mGeometryTask))}}),
1802           mUseGS(useGS),
1803           mVertexShader(vertexShader),
1804           mFragmentShader(fragmentShader)
1805     {}
1806 
wait(const gl::Context * context)1807     angle::Result wait(const gl::Context *context) override
1808     {
1809         WaitableEvent::WaitMany(&mWaitEvents);
1810 
1811         ANGLE_TRY(checkTask(context, mVertexTask.get()));
1812         ANGLE_TRY(checkTask(context, mPixelTask.get()));
1813         ANGLE_TRY(checkTask(context, mGeometryTask.get()));
1814 
1815         if (mVertexTask->getResult() == angle::Result::Incomplete ||
1816             mPixelTask->getResult() == angle::Result::Incomplete ||
1817             mGeometryTask->getResult() == angle::Result::Incomplete)
1818         {
1819             return angle::Result::Incomplete;
1820         }
1821 
1822         ShaderExecutableD3D *defaultVertexExecutable = mVertexTask->getExecutable();
1823         ShaderExecutableD3D *defaultPixelExecutable  = mPixelTask->getExecutable();
1824         ShaderExecutableD3D *pointGS                 = mGeometryTask->getExecutable();
1825 
1826         if (mUseGS && pointGS)
1827         {
1828             // Geometry shaders are currently only used internally, so there is no corresponding
1829             // shader object at the interface level. For now the geometry shader debug info is
1830             // prepended to the vertex shader.
1831             mVertexShader->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
1832             mVertexShader->appendDebugInfo(pointGS->getDebugInfo());
1833             mVertexShader->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
1834         }
1835 
1836         if (defaultVertexExecutable)
1837         {
1838             mVertexShader->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
1839         }
1840 
1841         if (defaultPixelExecutable)
1842         {
1843             mFragmentShader->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
1844         }
1845 
1846         bool isLinked = (defaultVertexExecutable && defaultPixelExecutable && (!mUseGS || pointGS));
1847         if (!isLinked)
1848         {
1849             mInfoLog << "Failed to create D3D Shaders";
1850         }
1851         return isLinked ? angle::Result::Continue : angle::Result::Incomplete;
1852     }
1853 
isLinking()1854     bool isLinking() override
1855     {
1856         for (auto &event : mWaitEvents)
1857         {
1858             if (!event->isReady())
1859             {
1860                 return true;
1861             }
1862         }
1863         return false;
1864     }
1865 
1866   private:
checkTask(const gl::Context * context,ProgramD3D::GetExecutableTask * task)1867     angle::Result checkTask(const gl::Context *context, ProgramD3D::GetExecutableTask *task)
1868     {
1869         if (!task->getInfoLog().empty())
1870         {
1871             mInfoLog << task->getInfoLog().str();
1872         }
1873 
1874         // Continue and Incomplete are not errors. For Stop, pass the error to the ContextD3D.
1875         if (task->getResult() != angle::Result::Stop)
1876         {
1877             return angle::Result::Continue;
1878         }
1879 
1880         ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
1881         task->popError(contextD3D);
1882         return angle::Result::Stop;
1883     }
1884 
1885     gl::InfoLog &mInfoLog;
1886     std::shared_ptr<ProgramD3D::GetVertexExecutableTask> mVertexTask;
1887     std::shared_ptr<ProgramD3D::GetPixelExecutableTask> mPixelTask;
1888     std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> mGeometryTask;
1889     std::array<std::shared_ptr<WaitableEvent>, 3> mWaitEvents;
1890     bool mUseGS;
1891     const ShaderD3D *mVertexShader;
1892     const ShaderD3D *mFragmentShader;
1893 };
1894 
1895 // The LinkEvent implementation for linking a computing program.
1896 class ProgramD3D::ComputeProgramLinkEvent final : public LinkEvent
1897 {
1898   public:
ComputeProgramLinkEvent(gl::InfoLog & infoLog,std::shared_ptr<ProgramD3D::GetComputeExecutableTask> computeTask,std::shared_ptr<WaitableEvent> event)1899     ComputeProgramLinkEvent(gl::InfoLog &infoLog,
1900                             std::shared_ptr<ProgramD3D::GetComputeExecutableTask> computeTask,
1901                             std::shared_ptr<WaitableEvent> event)
1902         : mInfoLog(infoLog), mComputeTask(computeTask), mWaitEvent(event)
1903     {}
1904 
isLinking()1905     bool isLinking() override { return !mWaitEvent->isReady(); }
1906 
wait(const gl::Context * context)1907     angle::Result wait(const gl::Context *context) override
1908     {
1909         mWaitEvent->wait();
1910 
1911         angle::Result result = mComputeTask->getResult();
1912         if (result != angle::Result::Continue)
1913         {
1914             mInfoLog << "Failed to create D3D compute shader.";
1915         }
1916         return result;
1917     }
1918 
1919   private:
1920     gl::InfoLog &mInfoLog;
1921     std::shared_ptr<ProgramD3D::GetComputeExecutableTask> mComputeTask;
1922     std::shared_ptr<WaitableEvent> mWaitEvent;
1923 };
1924 
compileProgramExecutables(const gl::Context * context,gl::InfoLog & infoLog)1925 std::unique_ptr<LinkEvent> ProgramD3D::compileProgramExecutables(const gl::Context *context,
1926                                                                  gl::InfoLog &infoLog)
1927 {
1928     // Ensure the compiler is initialized to avoid race conditions.
1929     angle::Result result = mRenderer->ensureHLSLCompilerInitialized(GetImplAs<ContextD3D>(context));
1930     if (result != angle::Result::Continue)
1931     {
1932         return std::make_unique<LinkEventDone>(result);
1933     }
1934 
1935     auto vertexTask   = std::make_shared<GetVertexExecutableTask>(this);
1936     auto pixelTask    = std::make_shared<GetPixelExecutableTask>(this);
1937     auto geometryTask = std::make_shared<GetGeometryExecutableTask>(this, context->getState());
1938     bool useGS        = usesGeometryShader(context->getState(), gl::PrimitiveMode::Points);
1939     gl::Shader *vertexShader         = mState.getAttachedShader(gl::ShaderType::Vertex);
1940     gl::Shader *fragmentShader       = mState.getAttachedShader(gl::ShaderType::Fragment);
1941     const ShaderD3D *vertexShaderD3D = vertexShader ? GetImplAs<ShaderD3D>(vertexShader) : nullptr;
1942     const ShaderD3D *fragmentShaderD3D =
1943         fragmentShader ? GetImplAs<ShaderD3D>(fragmentShader) : nullptr;
1944 
1945     return std::make_unique<GraphicsProgramLinkEvent>(infoLog, context->getWorkerThreadPool(),
1946                                                       vertexTask, pixelTask, geometryTask, useGS,
1947                                                       vertexShaderD3D, fragmentShaderD3D);
1948 }
1949 
compileComputeExecutable(const gl::Context * context,gl::InfoLog & infoLog)1950 std::unique_ptr<LinkEvent> ProgramD3D::compileComputeExecutable(const gl::Context *context,
1951                                                                 gl::InfoLog &infoLog)
1952 {
1953     // Ensure the compiler is initialized to avoid race conditions.
1954     angle::Result result = mRenderer->ensureHLSLCompilerInitialized(GetImplAs<ContextD3D>(context));
1955     if (result != angle::Result::Continue)
1956     {
1957         return std::make_unique<LinkEventDone>(result);
1958     }
1959     auto computeTask = std::make_shared<GetComputeExecutableTask>(this);
1960 
1961     std::shared_ptr<WaitableEvent> waitableEvent;
1962 
1963     // TODO(jie.a.chen@intel.com): Fix the flaky bug.
1964     // http://anglebug.com/3349
1965     bool compileInParallel = false;
1966     if (!compileInParallel)
1967     {
1968         (*computeTask)();
1969         waitableEvent = std::make_shared<WaitableEventDone>();
1970     }
1971     else
1972     {
1973         waitableEvent =
1974             WorkerThreadPool::PostWorkerTask(context->getWorkerThreadPool(), computeTask);
1975     }
1976 
1977     return std::make_unique<ComputeProgramLinkEvent>(infoLog, computeTask, waitableEvent);
1978 }
1979 
getComputeExecutableForImage2DBindLayout(d3d::Context * context,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1980 angle::Result ProgramD3D::getComputeExecutableForImage2DBindLayout(
1981     d3d::Context *context,
1982     ShaderExecutableD3D **outExecutable,
1983     gl::InfoLog *infoLog)
1984 {
1985     if (mCachedComputeExecutableIndex.valid())
1986     {
1987         *outExecutable =
1988             mComputeExecutables[mCachedComputeExecutableIndex.value()]->shaderExecutable();
1989         return angle::Result::Continue;
1990     }
1991 
1992     std::string finalComputeHLSL = mDynamicHLSL->generateComputeShaderForImage2DBindSignature(
1993         context, *this, mState, mImage2DUniforms, mComputeShaderImage2DBindLayoutCache);
1994 
1995     // Generate new compute executable
1996     ShaderExecutableD3D *computeExecutable = nullptr;
1997 
1998     gl::InfoLog tempInfoLog;
1999     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
2000 
2001     ANGLE_TRY(mRenderer->compileToExecutable(
2002         context, *currentInfoLog, finalComputeHLSL, gl::ShaderType::Compute,
2003         std::vector<D3DVarying>(), false, angle::CompilerWorkaroundsD3D(), &computeExecutable));
2004 
2005     if (computeExecutable)
2006     {
2007         mComputeExecutables.push_back(std::unique_ptr<ComputeExecutable>(
2008             new ComputeExecutable(mComputeShaderImage2DBindLayoutCache,
2009                                   std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
2010         mCachedComputeExecutableIndex = mComputeExecutables.size() - 1;
2011     }
2012     else if (!infoLog)
2013     {
2014         ERR() << "Error compiling dynamic compute executable:" << std::endl
2015               << tempInfoLog.str() << std::endl;
2016     }
2017     *outExecutable = computeExecutable;
2018 
2019     return angle::Result::Continue;
2020 }
2021 
link(const gl::Context * context,const gl::ProgramLinkedResources & resources,gl::InfoLog & infoLog)2022 std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context,
2023                                             const gl::ProgramLinkedResources &resources,
2024                                             gl::InfoLog &infoLog)
2025 {
2026     const auto &data = context->getState();
2027 
2028     reset();
2029 
2030     gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
2031     if (computeShader)
2032     {
2033         mShaderSamplers[gl::ShaderType::Compute].resize(
2034             data.getCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]);
2035         mImagesCS.resize(data.getCaps().maxImageUnits);
2036         mReadonlyImagesCS.resize(data.getCaps().maxImageUnits);
2037 
2038         mShaderUniformsDirty.set(gl::ShaderType::Compute);
2039 
2040         linkResources(resources);
2041 
2042         for (const sh::ShaderVariable &uniform : computeShader->getUniforms())
2043         {
2044             if (gl::IsImageType(uniform.type) && gl::IsImage2DType(uniform.type))
2045             {
2046                 mImage2DUniforms.push_back(uniform);
2047             }
2048         }
2049 
2050         defineUniformsAndAssignRegisters();
2051 
2052         return compileComputeExecutable(context, infoLog);
2053     }
2054     else
2055     {
2056         gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
2057         for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
2058         {
2059             if (mState.getAttachedShader(shaderType))
2060             {
2061                 shadersD3D[shaderType] = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
2062 
2063                 mShaderSamplers[shaderType].resize(
2064                     data.getCaps().maxShaderTextureImageUnits[shaderType]);
2065 
2066                 shadersD3D[shaderType]->generateWorkarounds(&mShaderWorkarounds[shaderType]);
2067 
2068                 mShaderUniformsDirty.set(shaderType);
2069             }
2070         }
2071 
2072         if (mRenderer->getNativeLimitations().noFrontFacingSupport)
2073         {
2074             const ShaderD3D *fragmentShader = shadersD3D[gl::ShaderType::Fragment];
2075             if (fragmentShader && fragmentShader->usesFrontFacing())
2076             {
2077                 infoLog << "The current renderer doesn't support gl_FrontFacing";
2078                 return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
2079             }
2080         }
2081 
2082         ProgramD3DMetadata metadata(mRenderer, shadersD3D, context->getClientType());
2083         BuiltinVaryingsD3D builtins(metadata, resources.varyingPacking);
2084 
2085         mDynamicHLSL->generateShaderLinkHLSL(context->getCaps(), mState, metadata,
2086                                              resources.varyingPacking, builtins, &mShaderHLSL);
2087 
2088         const ShaderD3D *vertexShader = shadersD3D[gl::ShaderType::Vertex];
2089         mUsesPointSize                = vertexShader && vertexShader->usesPointSize();
2090         mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
2091         mUsesFragDepth            = metadata.usesFragDepth();
2092         mUsesVertexID             = metadata.usesVertexID();
2093         mUsesViewID               = metadata.usesViewID();
2094         mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
2095 
2096         // Cache if we use flat shading
2097         mUsesFlatInterpolation = FindFlatInterpolationVarying(mState.getAttachedShaders());
2098 
2099         if (mRenderer->getMajorShaderModel() >= 4)
2100         {
2101             mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
2102                 resources.varyingPacking, builtins, mHasANGLEMultiviewEnabled,
2103                 metadata.canSelectViewInVertexShader());
2104         }
2105 
2106         initAttribLocationsToD3DSemantic();
2107 
2108         defineUniformsAndAssignRegisters();
2109 
2110         gatherTransformFeedbackVaryings(resources.varyingPacking, builtins[gl::ShaderType::Vertex]);
2111 
2112         linkResources(resources);
2113 
2114         return compileProgramExecutables(context, infoLog);
2115     }
2116 }
2117 
validate(const gl::Caps &,gl::InfoLog *)2118 GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
2119 {
2120     // TODO(jmadill): Do something useful here?
2121     return GL_TRUE;
2122 }
2123 
initializeShaderStorageBlocks()2124 void ProgramD3D::initializeShaderStorageBlocks()
2125 {
2126     if (mState.getShaderStorageBlocks().empty())
2127     {
2128         return;
2129     }
2130 
2131     ASSERT(mD3DShaderStorageBlocks.empty());
2132 
2133     // Assign registers and update sizes.
2134     gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
2135     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2136     {
2137         shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
2138     }
2139 
2140     for (const gl::InterfaceBlock &shaderStorageBlock : mState.getShaderStorageBlocks())
2141     {
2142         unsigned int shaderStorageBlockElement =
2143             shaderStorageBlock.isArray ? shaderStorageBlock.arrayElement : 0;
2144 
2145         D3DInterfaceBlock d3dShaderStorageBlock;
2146 
2147         for (gl::ShaderType shaderType : gl::AllShaderTypes())
2148         {
2149             if (shaderStorageBlock.isActive(shaderType))
2150             {
2151                 ASSERT(shadersD3D[shaderType]);
2152                 unsigned int baseRegister =
2153                     shadersD3D[shaderType]->getShaderStorageBlockRegister(shaderStorageBlock.name);
2154                 d3dShaderStorageBlock.mShaderRegisterIndexes[shaderType] =
2155                     baseRegister + shaderStorageBlockElement;
2156             }
2157         }
2158 
2159         mD3DShaderStorageBlocks.push_back(d3dShaderStorageBlock);
2160     }
2161 }
2162 
initializeUniformBlocks()2163 void ProgramD3D::initializeUniformBlocks()
2164 {
2165     if (mState.getUniformBlocks().empty())
2166     {
2167         return;
2168     }
2169 
2170     ASSERT(mD3DUniformBlocks.empty());
2171 
2172     // Assign registers and update sizes.
2173     gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
2174     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2175     {
2176         shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
2177     }
2178 
2179     for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
2180     {
2181         unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
2182 
2183         D3DUniformBlock d3dUniformBlock;
2184 
2185         for (gl::ShaderType shaderType : gl::AllShaderTypes())
2186         {
2187             if (uniformBlock.isActive(shaderType))
2188             {
2189                 ASSERT(shadersD3D[shaderType]);
2190                 unsigned int baseRegister =
2191                     shadersD3D[shaderType]->getUniformBlockRegister(uniformBlock.name);
2192                 d3dUniformBlock.mShaderRegisterIndexes[shaderType] =
2193                     baseRegister + uniformBlockElement;
2194                 bool useStructuredBuffer =
2195                     shadersD3D[shaderType]->shouldUniformBlockUseStructuredBuffer(
2196                         uniformBlock.name);
2197                 if (useStructuredBuffer)
2198                 {
2199                     d3dUniformBlock.mUseStructuredBuffers[shaderType] = true;
2200                     d3dUniformBlock.mByteWidths[shaderType]           = uniformBlock.dataSize;
2201                     d3dUniformBlock.mStructureByteStrides[shaderType] =
2202                         uniformBlock.firstFieldArraySize == 0u
2203                             ? uniformBlock.dataSize
2204                             : uniformBlock.dataSize / uniformBlock.firstFieldArraySize;
2205                 }
2206             }
2207         }
2208 
2209         mD3DUniformBlocks.push_back(d3dUniformBlock);
2210     }
2211 }
2212 
initializeUniformStorage(const gl::ShaderBitSet & availableShaderStages)2213 void ProgramD3D::initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages)
2214 {
2215     // Compute total default block size
2216     gl::ShaderMap<unsigned int> shaderRegisters = {};
2217     for (const D3DUniform *d3dUniform : mD3DUniforms)
2218     {
2219         if (d3dUniform->isSampler())
2220         {
2221             continue;
2222         }
2223 
2224         for (gl::ShaderType shaderType : availableShaderStages)
2225         {
2226             if (d3dUniform->isReferencedByShader(shaderType))
2227             {
2228                 shaderRegisters[shaderType] = std::max(
2229                     shaderRegisters[shaderType],
2230                     d3dUniform->mShaderRegisterIndexes[shaderType] + d3dUniform->registerCount);
2231             }
2232         }
2233     }
2234 
2235     // We only reset uniform storages for the shader stages available in the program (attached
2236     // shaders in ProgramD3D::link() and linkedShaderStages in ProgramD3D::load()).
2237     for (gl::ShaderType shaderType : availableShaderStages)
2238     {
2239         mShaderUniformStorages[shaderType].reset(
2240             mRenderer->createUniformStorage(shaderRegisters[shaderType] * 16u));
2241     }
2242 
2243     // Iterate the uniforms again to assign data pointers to default block uniforms.
2244     for (D3DUniform *d3dUniform : mD3DUniforms)
2245     {
2246         if (d3dUniform->isSampler())
2247         {
2248             d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
2249             continue;
2250         }
2251 
2252         for (gl::ShaderType shaderType : availableShaderStages)
2253         {
2254             if (d3dUniform->isReferencedByShader(shaderType))
2255             {
2256                 d3dUniform->mShaderData[shaderType] =
2257                     mShaderUniformStorages[shaderType]->getDataPointer(
2258                         d3dUniform->mShaderRegisterIndexes[shaderType],
2259                         d3dUniform->registerElement);
2260             }
2261         }
2262     }
2263 }
2264 
updateUniformBufferCache(const gl::Caps & caps)2265 void ProgramD3D::updateUniformBufferCache(const gl::Caps &caps)
2266 {
2267     if (mState.getUniformBlocks().empty())
2268     {
2269         return;
2270     }
2271 
2272     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2273     {
2274         mShaderUBOCaches[shaderType].clear();
2275         mShaderUBOCachesUseSB[shaderType].clear();
2276     }
2277 
2278     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
2279          uniformBlockIndex++)
2280     {
2281         const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
2282         GLuint blockBinding                 = mState.getUniformBlockBinding(uniformBlockIndex);
2283 
2284         // Unnecessary to apply an unreferenced standard or shared UBO
2285         for (gl::ShaderType shaderType : gl::AllShaderTypes())
2286         {
2287             if (!uniformBlock.activeInShader(shaderType))
2288             {
2289                 continue;
2290             }
2291 
2292             bool useStructuredBuffer   = uniformBlock.mUseStructuredBuffers[shaderType];
2293             unsigned int registerIndex = uniformBlock.mShaderRegisterIndexes[shaderType];
2294             if (useStructuredBuffer)
2295             {
2296                 D3DUBOCacheUseSB cacheUseSB;
2297                 cacheUseSB.registerIndex       = registerIndex;
2298                 cacheUseSB.binding             = blockBinding;
2299                 cacheUseSB.byteWidth           = uniformBlock.mByteWidths[shaderType];
2300                 cacheUseSB.structureByteStride = uniformBlock.mStructureByteStrides[shaderType];
2301                 mShaderUBOCachesUseSB[shaderType].push_back(cacheUseSB);
2302             }
2303             else
2304             {
2305                 ASSERT(registerIndex <
2306                        static_cast<unsigned int>(caps.maxShaderUniformBlocks[shaderType]));
2307                 D3DUBOCache cache;
2308                 cache.registerIndex = registerIndex;
2309                 cache.binding       = blockBinding;
2310                 mShaderUBOCaches[shaderType].push_back(cache);
2311             }
2312         }
2313     }
2314 
2315     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2316     {
2317         GLuint uniformBlockCount = static_cast<GLuint>(mShaderUBOCaches[shaderType].size() +
2318                                                        mShaderUBOCachesUseSB[shaderType].size());
2319         ASSERT(uniformBlockCount <=
2320                static_cast<unsigned int>(caps.maxShaderUniformBlocks[shaderType]));
2321     }
2322 }
2323 
getAtomicCounterBufferRegisterIndex(GLuint binding,gl::ShaderType shaderType) const2324 unsigned int ProgramD3D::getAtomicCounterBufferRegisterIndex(GLuint binding,
2325                                                              gl::ShaderType shaderType) const
2326 {
2327     if (shaderType != gl::ShaderType::Compute)
2328     {
2329         // Implement atomic counters for non-compute shaders
2330         // http://anglebug.com/1729
2331         UNIMPLEMENTED();
2332     }
2333     return mComputeAtomicCounterBufferRegisterIndices[binding];
2334 }
2335 
getShaderStorageBufferRegisterIndex(GLuint blockIndex,gl::ShaderType shaderType) const2336 unsigned int ProgramD3D::getShaderStorageBufferRegisterIndex(GLuint blockIndex,
2337                                                              gl::ShaderType shaderType) const
2338 {
2339     return mD3DShaderStorageBlocks[blockIndex].mShaderRegisterIndexes[shaderType];
2340 }
2341 
getShaderUniformBufferCache(gl::ShaderType shaderType) const2342 const std::vector<D3DUBOCache> &ProgramD3D::getShaderUniformBufferCache(
2343     gl::ShaderType shaderType) const
2344 {
2345     return mShaderUBOCaches[shaderType];
2346 }
2347 
getShaderUniformBufferCacheUseSB(gl::ShaderType shaderType) const2348 const std::vector<D3DUBOCacheUseSB> &ProgramD3D::getShaderUniformBufferCacheUseSB(
2349     gl::ShaderType shaderType) const
2350 {
2351     return mShaderUBOCachesUseSB[shaderType];
2352 }
2353 
dirtyAllUniforms()2354 void ProgramD3D::dirtyAllUniforms()
2355 {
2356     mShaderUniformsDirty = mState.getProgramExecutable().getLinkedShaderStages();
2357 }
2358 
markUniformsClean()2359 void ProgramD3D::markUniformsClean()
2360 {
2361     mShaderUniformsDirty.reset();
2362 }
2363 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)2364 void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
2365 {
2366     setUniformInternal(location, count, v, GL_FLOAT);
2367 }
2368 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)2369 void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2370 {
2371     setUniformInternal(location, count, v, GL_FLOAT_VEC2);
2372 }
2373 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)2374 void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2375 {
2376     setUniformInternal(location, count, v, GL_FLOAT_VEC3);
2377 }
2378 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)2379 void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2380 {
2381     setUniformInternal(location, count, v, GL_FLOAT_VEC4);
2382 }
2383 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2384 void ProgramD3D::setUniformMatrix2fv(GLint location,
2385                                      GLsizei count,
2386                                      GLboolean transpose,
2387                                      const GLfloat *value)
2388 {
2389     setUniformMatrixfvInternal<2, 2>(location, count, transpose, value);
2390 }
2391 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2392 void ProgramD3D::setUniformMatrix3fv(GLint location,
2393                                      GLsizei count,
2394                                      GLboolean transpose,
2395                                      const GLfloat *value)
2396 {
2397     setUniformMatrixfvInternal<3, 3>(location, count, transpose, value);
2398 }
2399 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2400 void ProgramD3D::setUniformMatrix4fv(GLint location,
2401                                      GLsizei count,
2402                                      GLboolean transpose,
2403                                      const GLfloat *value)
2404 {
2405     setUniformMatrixfvInternal<4, 4>(location, count, transpose, value);
2406 }
2407 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2408 void ProgramD3D::setUniformMatrix2x3fv(GLint location,
2409                                        GLsizei count,
2410                                        GLboolean transpose,
2411                                        const GLfloat *value)
2412 {
2413     setUniformMatrixfvInternal<2, 3>(location, count, transpose, value);
2414 }
2415 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2416 void ProgramD3D::setUniformMatrix3x2fv(GLint location,
2417                                        GLsizei count,
2418                                        GLboolean transpose,
2419                                        const GLfloat *value)
2420 {
2421     setUniformMatrixfvInternal<3, 2>(location, count, transpose, value);
2422 }
2423 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2424 void ProgramD3D::setUniformMatrix2x4fv(GLint location,
2425                                        GLsizei count,
2426                                        GLboolean transpose,
2427                                        const GLfloat *value)
2428 {
2429     setUniformMatrixfvInternal<2, 4>(location, count, transpose, value);
2430 }
2431 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2432 void ProgramD3D::setUniformMatrix4x2fv(GLint location,
2433                                        GLsizei count,
2434                                        GLboolean transpose,
2435                                        const GLfloat *value)
2436 {
2437     setUniformMatrixfvInternal<4, 2>(location, count, transpose, value);
2438 }
2439 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2440 void ProgramD3D::setUniformMatrix3x4fv(GLint location,
2441                                        GLsizei count,
2442                                        GLboolean transpose,
2443                                        const GLfloat *value)
2444 {
2445     setUniformMatrixfvInternal<3, 4>(location, count, transpose, value);
2446 }
2447 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2448 void ProgramD3D::setUniformMatrix4x3fv(GLint location,
2449                                        GLsizei count,
2450                                        GLboolean transpose,
2451                                        const GLfloat *value)
2452 {
2453     setUniformMatrixfvInternal<4, 3>(location, count, transpose, value);
2454 }
2455 
setUniform1iv(GLint location,GLsizei count,const GLint * v)2456 void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
2457 {
2458     setUniformInternal(location, count, v, GL_INT);
2459 }
2460 
setUniform2iv(GLint location,GLsizei count,const GLint * v)2461 void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
2462 {
2463     setUniformInternal(location, count, v, GL_INT_VEC2);
2464 }
2465 
setUniform3iv(GLint location,GLsizei count,const GLint * v)2466 void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
2467 {
2468     setUniformInternal(location, count, v, GL_INT_VEC3);
2469 }
2470 
setUniform4iv(GLint location,GLsizei count,const GLint * v)2471 void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
2472 {
2473     setUniformInternal(location, count, v, GL_INT_VEC4);
2474 }
2475 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)2476 void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
2477 {
2478     setUniformInternal(location, count, v, GL_UNSIGNED_INT);
2479 }
2480 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)2481 void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
2482 {
2483     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
2484 }
2485 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)2486 void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2487 {
2488     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
2489 }
2490 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)2491 void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2492 {
2493     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
2494 }
2495 
defineUniformsAndAssignRegisters()2496 void ProgramD3D::defineUniformsAndAssignRegisters()
2497 {
2498     D3DUniformMap uniformMap;
2499 
2500     gl::ShaderBitSet attachedShaders;
2501     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2502     {
2503         gl::Shader *shader = mState.getAttachedShader(shaderType);
2504         if (shader)
2505         {
2506             for (const sh::ShaderVariable &uniform : shader->getUniforms())
2507             {
2508                 if (uniform.active)
2509                 {
2510                     defineUniformBase(shader, uniform, &uniformMap);
2511                 }
2512             }
2513 
2514             attachedShaders.set(shader->getType());
2515         }
2516     }
2517 
2518     // Initialize the D3DUniform list to mirror the indexing of the GL layer.
2519     for (const gl::LinkedUniform &glUniform : mState.getUniforms())
2520     {
2521         if (!glUniform.isInDefaultBlock())
2522             continue;
2523 
2524         std::string name = glUniform.name;
2525         if (glUniform.isArray())
2526         {
2527             // In the program state, array uniform names include [0] as in the program resource
2528             // spec. Here we don't include it.
2529             // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL
2530             // layer.
2531             ASSERT(angle::EndsWith(name, "[0]"));
2532             name.resize(name.length() - 3);
2533         }
2534         auto mapEntry = uniformMap.find(name);
2535         ASSERT(mapEntry != uniformMap.end());
2536         mD3DUniforms.push_back(mapEntry->second);
2537     }
2538 
2539     assignAllSamplerRegisters();
2540     assignAllAtomicCounterRegisters();
2541     // Samplers and readonly images share shader input resource slot, adjust low value of
2542     // readonly image range.
2543     mUsedComputeReadonlyImageRange =
2544         gl::RangeUI(mUsedShaderSamplerRanges[gl::ShaderType::Compute].high(),
2545                     mUsedShaderSamplerRanges[gl::ShaderType::Compute].high());
2546     // Atomic counter buffers and non-readonly images share input resource slots
2547     mUsedComputeImageRange =
2548         gl::RangeUI(mUsedComputeAtomicCounterRange.high(), mUsedComputeAtomicCounterRange.high());
2549     assignAllImageRegisters();
2550     initializeUniformStorage(attachedShaders);
2551 }
2552 
defineUniformBase(const gl::Shader * shader,const sh::ShaderVariable & uniform,D3DUniformMap * uniformMap)2553 void ProgramD3D::defineUniformBase(const gl::Shader *shader,
2554                                    const sh::ShaderVariable &uniform,
2555                                    D3DUniformMap *uniformMap)
2556 {
2557     sh::DummyBlockEncoder dummyEncoder;
2558 
2559     // Samplers get their registers assigned in assignAllSamplerRegisters, and images get their
2560     // registers assigned in assignAllImageRegisters.
2561     if (gl::IsSamplerType(uniform.type))
2562     {
2563         UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::Texture,
2564                                           &dummyEncoder, uniformMap);
2565         sh::TraverseShaderVariable(uniform, false, &visitor);
2566         return;
2567     }
2568 
2569     if (gl::IsImageType(uniform.type))
2570     {
2571         if (uniform.readonly)
2572         {
2573             UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::Texture,
2574                                               &dummyEncoder, uniformMap);
2575             sh::TraverseShaderVariable(uniform, false, &visitor);
2576         }
2577         else
2578         {
2579             UniformEncodingVisitorD3D visitor(shader->getType(),
2580                                               HLSLRegisterType::UnorderedAccessView, &dummyEncoder,
2581                                               uniformMap);
2582             sh::TraverseShaderVariable(uniform, false, &visitor);
2583         }
2584         mImageBindingMap[uniform.name] = uniform.binding;
2585         return;
2586     }
2587 
2588     if (uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn())
2589     {
2590         UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::None, &dummyEncoder,
2591                                           uniformMap);
2592         sh::TraverseShaderVariable(uniform, false, &visitor);
2593         return;
2594     }
2595     else if (gl::IsAtomicCounterType(uniform.type))
2596     {
2597         UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::UnorderedAccessView,
2598                                           &dummyEncoder, uniformMap);
2599         sh::TraverseShaderVariable(uniform, false, &visitor);
2600         mAtomicBindingMap[uniform.name] = uniform.binding;
2601         return;
2602     }
2603 
2604     const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
2605     unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
2606     ShShaderOutput outputType  = shaderD3D->getCompilerOutputType();
2607     sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
2608     encoder.skipRegisters(startRegister);
2609 
2610     UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::None, &encoder,
2611                                       uniformMap);
2612     sh::TraverseShaderVariable(uniform, false, &visitor);
2613 }
2614 
hasNamedUniform(const std::string & name)2615 bool ProgramD3D::hasNamedUniform(const std::string &name)
2616 {
2617     for (D3DUniform *d3dUniform : mD3DUniforms)
2618     {
2619         if (d3dUniform->name == name)
2620         {
2621             return true;
2622         }
2623     }
2624 
2625     return false;
2626 }
2627 
2628 // Assume count is already clamped.
2629 template <typename T>
setUniformImpl(const gl::VariableLocation & locationInfo,GLsizei count,const T * v,uint8_t * targetData,GLenum uniformType)2630 void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
2631                                 GLsizei count,
2632                                 const T *v,
2633                                 uint8_t *targetData,
2634                                 GLenum uniformType)
2635 {
2636     D3DUniform *targetUniform             = mD3DUniforms[locationInfo.index];
2637     const int components                  = targetUniform->typeInfo.componentCount;
2638     const unsigned int arrayElementOffset = locationInfo.arrayIndex;
2639 
2640     if (targetUniform->typeInfo.type == uniformType)
2641     {
2642         T *dest         = reinterpret_cast<T *>(targetData) + arrayElementOffset * 4;
2643         const T *source = v;
2644 
2645         for (GLint i = 0; i < count; i++, dest += 4, source += components)
2646         {
2647             memcpy(dest, source, components * sizeof(T));
2648         }
2649     }
2650     else
2651     {
2652         ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
2653         GLint *boolParams = reinterpret_cast<GLint *>(targetData) + arrayElementOffset * 4;
2654 
2655         for (GLint i = 0; i < count; i++)
2656         {
2657             GLint *dest     = boolParams + (i * 4);
2658             const T *source = v + (i * components);
2659 
2660             for (int c = 0; c < components; c++)
2661             {
2662                 dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
2663             }
2664         }
2665     }
2666 }
2667 
2668 template <typename T>
setUniformInternal(GLint location,GLsizei count,const T * v,GLenum uniformType)2669 void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType)
2670 {
2671     const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
2672     D3DUniform *targetUniform                = mD3DUniforms[locationInfo.index];
2673 
2674     if (targetUniform->typeInfo.isSampler)
2675     {
2676         ASSERT(uniformType == GL_INT);
2677         size_t size = count * sizeof(T);
2678         GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
2679         if (memcmp(dest, v, size) != 0)
2680         {
2681             memcpy(dest, v, size);
2682             mDirtySamplerMapping = true;
2683         }
2684         return;
2685     }
2686 
2687     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2688     {
2689         if (targetUniform->mShaderData[shaderType])
2690         {
2691             setUniformImpl(locationInfo, count, v, targetUniform->mShaderData[shaderType],
2692                            uniformType);
2693             mShaderUniformsDirty.set(shaderType);
2694         }
2695     }
2696 }
2697 
2698 template <int cols, int rows>
setUniformMatrixfvInternal(GLint location,GLsizei countIn,GLboolean transpose,const GLfloat * value)2699 void ProgramD3D::setUniformMatrixfvInternal(GLint location,
2700                                             GLsizei countIn,
2701                                             GLboolean transpose,
2702                                             const GLfloat *value)
2703 {
2704     D3DUniform *targetUniform                   = getD3DUniformFromLocation(location);
2705     const gl::VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2706     unsigned int arrayElementOffset             = uniformLocation.arrayIndex;
2707     unsigned int elementCount                   = targetUniform->getArraySizeProduct();
2708 
2709     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2710     {
2711         if (targetUniform->mShaderData[shaderType])
2712         {
2713             SetFloatUniformMatrixHLSL<cols, rows>::Run(arrayElementOffset, elementCount, countIn,
2714                                                        transpose, value,
2715                                                        targetUniform->mShaderData[shaderType]);
2716             mShaderUniformsDirty.set(shaderType);
2717         }
2718     }
2719 }
2720 
assignAllSamplerRegisters()2721 void ProgramD3D::assignAllSamplerRegisters()
2722 {
2723     for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2724     {
2725         if (mD3DUniforms[uniformIndex]->isSampler())
2726         {
2727             assignSamplerRegisters(uniformIndex);
2728         }
2729     }
2730 }
2731 
assignSamplerRegisters(size_t uniformIndex)2732 void ProgramD3D::assignSamplerRegisters(size_t uniformIndex)
2733 {
2734     D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2735     ASSERT(d3dUniform->isSampler());
2736     // If the uniform is an array of arrays, then we have separate entries for each inner array in
2737     // mD3DUniforms. However, the sampler register info is stored in the shader only for the
2738     // outermost array.
2739     std::vector<unsigned int> subscripts;
2740     const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2741     unsigned int registerOffset =
2742         mState.getUniforms()[uniformIndex].parentArrayIndex() * d3dUniform->getArraySizeProduct();
2743 
2744     bool hasUniform = false;
2745     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2746     {
2747         if (!mState.getAttachedShader(shaderType))
2748         {
2749             continue;
2750         }
2751 
2752         const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
2753         if (shaderD3D->hasUniform(baseName))
2754         {
2755             d3dUniform->mShaderRegisterIndexes[shaderType] =
2756                 shaderD3D->getUniformRegister(baseName) + registerOffset;
2757             ASSERT(d3dUniform->mShaderRegisterIndexes[shaderType] != GL_INVALID_VALUE);
2758 
2759             AssignSamplers(d3dUniform->mShaderRegisterIndexes[shaderType], d3dUniform->typeInfo,
2760                            d3dUniform->getArraySizeProduct(), mShaderSamplers[shaderType],
2761                            &mUsedShaderSamplerRanges[shaderType]);
2762             hasUniform = true;
2763         }
2764     }
2765 
2766     ASSERT(hasUniform);
2767 }
2768 
2769 // static
AssignSamplers(unsigned int startSamplerIndex,const gl::UniformTypeInfo & typeInfo,unsigned int samplerCount,std::vector<Sampler> & outSamplers,gl::RangeUI * outUsedRange)2770 void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
2771                                 const gl::UniformTypeInfo &typeInfo,
2772                                 unsigned int samplerCount,
2773                                 std::vector<Sampler> &outSamplers,
2774                                 gl::RangeUI *outUsedRange)
2775 {
2776     unsigned int samplerIndex = startSamplerIndex;
2777     unsigned int low          = outUsedRange->low();
2778     unsigned int high         = outUsedRange->high();
2779 
2780     do
2781     {
2782         ASSERT(samplerIndex < outSamplers.size());
2783         Sampler *sampler            = &outSamplers[samplerIndex];
2784         sampler->active             = true;
2785         sampler->textureType        = gl::FromGLenum<gl::TextureType>(typeInfo.textureType);
2786         sampler->logicalTextureUnit = 0;
2787         low                         = std::min(samplerIndex, low);
2788         high                        = std::max(samplerIndex + 1, high);
2789         samplerIndex++;
2790     } while (samplerIndex < startSamplerIndex + samplerCount);
2791 
2792     ASSERT(low < high);
2793     *outUsedRange = gl::RangeUI(low, high);
2794 }
2795 
assignAllImageRegisters()2796 void ProgramD3D::assignAllImageRegisters()
2797 {
2798     for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2799     {
2800         if (mD3DUniforms[uniformIndex]->isImage() && !mD3DUniforms[uniformIndex]->isImage2D())
2801         {
2802             assignImageRegisters(uniformIndex);
2803         }
2804     }
2805 }
2806 
assignAllAtomicCounterRegisters()2807 void ProgramD3D::assignAllAtomicCounterRegisters()
2808 {
2809     if (mAtomicBindingMap.empty())
2810     {
2811         return;
2812     }
2813     gl::ShaderType shaderType       = gl::ShaderType::Compute;
2814     const gl::Shader *computeShader = mState.getAttachedShader(shaderType);
2815     if (computeShader)
2816     {
2817         const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(computeShader);
2818         auto &registerIndices             = mComputeAtomicCounterBufferRegisterIndices;
2819         unsigned int firstRegister        = GL_INVALID_VALUE;
2820         unsigned int lastRegister         = 0;
2821         for (auto &atomicBinding : mAtomicBindingMap)
2822         {
2823             ASSERT(computeShaderD3D->hasUniform(atomicBinding.first));
2824             unsigned int currentRegister =
2825                 computeShaderD3D->getUniformRegister(atomicBinding.first);
2826             ASSERT(currentRegister != GL_INVALID_INDEX);
2827             const int kBinding = atomicBinding.second;
2828 
2829             registerIndices[kBinding] = currentRegister;
2830 
2831             firstRegister = std::min(firstRegister, currentRegister);
2832             lastRegister  = std::max(lastRegister, currentRegister);
2833         }
2834         ASSERT(firstRegister != GL_INVALID_VALUE);
2835         ASSERT(lastRegister != GL_INVALID_VALUE);
2836         mUsedComputeAtomicCounterRange = gl::RangeUI(firstRegister, lastRegister + 1);
2837     }
2838     else
2839     {
2840         // Implement atomic counters for non-compute shaders
2841         // http://anglebug.com/1729
2842         UNIMPLEMENTED();
2843     }
2844 }
2845 
assignImageRegisters(size_t uniformIndex)2846 void ProgramD3D::assignImageRegisters(size_t uniformIndex)
2847 {
2848     D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2849     ASSERT(d3dUniform->isImage());
2850     // If the uniform is an array of arrays, then we have separate entries for each inner array in
2851     // mD3DUniforms. However, the image register info is stored in the shader only for the
2852     // outermost array.
2853     std::vector<unsigned int> subscripts;
2854     const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2855     unsigned int registerOffset =
2856         mState.getUniforms()[uniformIndex].parentArrayIndex() * d3dUniform->getArraySizeProduct();
2857 
2858     const gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
2859     if (computeShader)
2860     {
2861         const ShaderD3D *computeShaderD3D =
2862             GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Compute));
2863         ASSERT(computeShaderD3D->hasUniform(baseName));
2864         d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] =
2865             computeShaderD3D->getUniformRegister(baseName) + registerOffset;
2866         ASSERT(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] != GL_INVALID_INDEX);
2867         auto bindingIter = mImageBindingMap.find(baseName);
2868         ASSERT(bindingIter != mImageBindingMap.end());
2869         if (d3dUniform->regType == HLSLRegisterType::Texture)
2870         {
2871             AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2872                          bindingIter->second, d3dUniform->getArraySizeProduct(), mReadonlyImagesCS,
2873                          &mUsedComputeReadonlyImageRange);
2874         }
2875         else if (d3dUniform->regType == HLSLRegisterType::UnorderedAccessView)
2876         {
2877             AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2878                          bindingIter->second, d3dUniform->getArraySizeProduct(), mImagesCS,
2879                          &mUsedComputeImageRange);
2880         }
2881         else
2882         {
2883             UNREACHABLE();
2884         }
2885     }
2886     else
2887     {
2888         // TODO(xinghua.cao@intel.com): Implement image variables in vertex shader and pixel shader.
2889         UNIMPLEMENTED();
2890     }
2891 }
2892 
2893 // static
AssignImages(unsigned int startImageIndex,int startLogicalImageUnit,unsigned int imageCount,std::vector<Image> & outImages,gl::RangeUI * outUsedRange)2894 void ProgramD3D::AssignImages(unsigned int startImageIndex,
2895                               int startLogicalImageUnit,
2896                               unsigned int imageCount,
2897                               std::vector<Image> &outImages,
2898                               gl::RangeUI *outUsedRange)
2899 {
2900     unsigned int imageIndex = startImageIndex;
2901     unsigned int low        = outUsedRange->low();
2902     unsigned int high       = outUsedRange->high();
2903 
2904     // If declare without a binding qualifier, any uniform image variable (include all elements of
2905     // unbound image array) shoud be bound to unit zero.
2906     if (startLogicalImageUnit == -1)
2907     {
2908         ASSERT(imageIndex < outImages.size());
2909         Image *image            = &outImages[imageIndex];
2910         image->active           = true;
2911         image->logicalImageUnit = 0;
2912         low                     = std::min(imageIndex, low);
2913         high                    = std::max(imageIndex + 1, high);
2914         ASSERT(low < high);
2915         *outUsedRange = gl::RangeUI(low, high);
2916         return;
2917     }
2918 
2919     unsigned int logcalImageUnit = startLogicalImageUnit;
2920     do
2921     {
2922         ASSERT(imageIndex < outImages.size());
2923         Image *image            = &outImages[imageIndex];
2924         image->active           = true;
2925         image->logicalImageUnit = logcalImageUnit;
2926         low                     = std::min(imageIndex, low);
2927         high                    = std::max(imageIndex + 1, high);
2928         imageIndex++;
2929         logcalImageUnit++;
2930     } while (imageIndex < startImageIndex + imageCount);
2931 
2932     ASSERT(low < high);
2933     *outUsedRange = gl::RangeUI(low, high);
2934 }
2935 
assignImage2DRegisters(unsigned int startImageIndex,int startLogicalImageUnit,bool readonly)2936 void ProgramD3D::assignImage2DRegisters(unsigned int startImageIndex,
2937                                         int startLogicalImageUnit,
2938                                         bool readonly)
2939 {
2940     if (readonly)
2941     {
2942         AssignImages(startImageIndex, startLogicalImageUnit, 1, mReadonlyImagesCS,
2943                      &mUsedComputeReadonlyImageRange);
2944     }
2945     else
2946     {
2947         AssignImages(startImageIndex, startLogicalImageUnit, 1, mImagesCS, &mUsedComputeImageRange);
2948     }
2949 }
2950 
reset()2951 void ProgramD3D::reset()
2952 {
2953     mVertexExecutables.clear();
2954     mPixelExecutables.clear();
2955     mComputeExecutables.clear();
2956 
2957     for (auto &geometryExecutable : mGeometryExecutables)
2958     {
2959         geometryExecutable.reset(nullptr);
2960     }
2961 
2962     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2963     {
2964         mShaderHLSL[shaderType].clear();
2965     }
2966 
2967     mUsesFragDepth            = false;
2968     mHasANGLEMultiviewEnabled = false;
2969     mUsesVertexID             = false;
2970     mUsesViewID               = false;
2971     mPixelShaderKey.clear();
2972     mUsesPointSize         = false;
2973     mUsesFlatInterpolation = false;
2974 
2975     SafeDeleteContainer(mD3DUniforms);
2976     mD3DUniformBlocks.clear();
2977     mD3DShaderStorageBlocks.clear();
2978     mComputeAtomicCounterBufferRegisterIndices.fill({});
2979 
2980     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2981     {
2982         mShaderUniformStorages[shaderType].reset();
2983         mShaderSamplers[shaderType].clear();
2984     }
2985 
2986     mImagesCS.clear();
2987     mReadonlyImagesCS.clear();
2988 
2989     mUsedShaderSamplerRanges.fill({0, 0});
2990     mUsedComputeAtomicCounterRange = {0, 0};
2991     mDirtySamplerMapping           = true;
2992     mUsedComputeImageRange         = {0, 0};
2993     mUsedComputeReadonlyImageRange = {0, 0};
2994 
2995     mAttribLocationToD3DSemantic.fill(-1);
2996 
2997     mStreamOutVaryings.clear();
2998 
2999     mGeometryShaderPreamble.clear();
3000 
3001     markUniformsClean();
3002 
3003     mCachedPixelExecutableIndex.reset();
3004     mCachedVertexExecutableIndex.reset();
3005 }
3006 
getSerial() const3007 unsigned int ProgramD3D::getSerial() const
3008 {
3009     return mSerial;
3010 }
3011 
issueSerial()3012 unsigned int ProgramD3D::issueSerial()
3013 {
3014     return mCurrentSerial++;
3015 }
3016 
initAttribLocationsToD3DSemantic()3017 void ProgramD3D::initAttribLocationsToD3DSemantic()
3018 {
3019     gl::Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
3020     if (!vertexShader)
3021     {
3022         return;
3023     }
3024 
3025     // Init semantic index
3026     int semanticIndex = 0;
3027     for (const sh::ShaderVariable &attribute : vertexShader->getActiveAttributes())
3028     {
3029         int regCount    = gl::VariableRegisterCount(attribute.type);
3030         GLuint location = mState.getAttributeLocation(attribute.name);
3031         ASSERT(location != std::numeric_limits<GLuint>::max());
3032 
3033         for (int reg = 0; reg < regCount; ++reg)
3034         {
3035             mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
3036         }
3037     }
3038 }
3039 
updateCachedInputLayout(Serial associatedSerial,const gl::State & state)3040 void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state)
3041 {
3042     if (mCurrentVertexArrayStateSerial == associatedSerial)
3043     {
3044         return;
3045     }
3046 
3047     mCurrentVertexArrayStateSerial = associatedSerial;
3048     mCachedInputLayout.clear();
3049 
3050     const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
3051     const gl::AttributesMask &attributesMask =
3052         mState.getProgramExecutable().getActiveAttribLocationsMask();
3053 
3054     for (size_t locationIndex : attributesMask)
3055     {
3056         int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
3057 
3058         if (d3dSemantic != -1)
3059         {
3060             if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
3061             {
3062                 mCachedInputLayout.resize(d3dSemantic + 1, angle::FormatID::NONE);
3063             }
3064             mCachedInputLayout[d3dSemantic] =
3065                 GetVertexFormatID(vertexAttributes[locationIndex],
3066                                   state.getVertexAttribCurrentValue(locationIndex).Type);
3067         }
3068     }
3069 
3070     VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
3071 
3072     updateCachedVertexExecutableIndex();
3073 }
3074 
updateCachedOutputLayout(const gl::Context * context,const gl::Framebuffer * framebuffer)3075 void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
3076                                           const gl::Framebuffer *framebuffer)
3077 {
3078     mPixelShaderOutputLayoutCache.clear();
3079 
3080     FramebufferD3D *fboD3D   = GetImplAs<FramebufferD3D>(framebuffer);
3081     const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
3082 
3083     for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
3084     {
3085         const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
3086 
3087         if (colorbuffer)
3088         {
3089             auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
3090                                                                 : colorbuffer->getBinding();
3091             size_t maxIndex = binding != GL_NONE ? GetMaxOutputIndex(mPixelShaderKey,
3092                                                                      binding - GL_COLOR_ATTACHMENT0)
3093                                                  : 0;
3094             mPixelShaderOutputLayoutCache.insert(mPixelShaderOutputLayoutCache.end(), maxIndex + 1,
3095                                                  binding);
3096         }
3097         else
3098         {
3099             mPixelShaderOutputLayoutCache.push_back(GL_NONE);
3100         }
3101     }
3102 
3103     updateCachedPixelExecutableIndex();
3104 }
3105 
updateCachedComputeImage2DBindLayout(const gl::Context * context)3106 void ProgramD3D::updateCachedComputeImage2DBindLayout(const gl::Context *context)
3107 {
3108     const auto &glState = context->getState();
3109     for (auto &image2DBindLayout : mComputeShaderImage2DBindLayoutCache)
3110     {
3111         const gl::ImageUnit &imageUnit = glState.getImageUnit(image2DBindLayout.first);
3112         if (imageUnit.texture.get())
3113         {
3114             image2DBindLayout.second = imageUnit.texture->getType();
3115         }
3116         else
3117         {
3118             image2DBindLayout.second = gl::TextureType::_2D;
3119         }
3120     }
3121 
3122     updateCachedComputeExecutableIndex();
3123 }
3124 
gatherTransformFeedbackVaryings(const gl::VaryingPacking & varyingPacking,const BuiltinInfo & builtins)3125 void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
3126                                                  const BuiltinInfo &builtins)
3127 {
3128     const std::string &varyingSemantic =
3129         GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
3130 
3131     // Gather the linked varyings that are used for transform feedback, they should all exist.
3132     mStreamOutVaryings.clear();
3133 
3134     const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
3135     for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
3136          ++outputSlot)
3137     {
3138         const auto &tfVaryingName = tfVaryingNames[outputSlot];
3139         if (tfVaryingName == "gl_Position")
3140         {
3141             if (builtins.glPosition.enabled)
3142             {
3143                 mStreamOutVaryings.emplace_back(builtins.glPosition.semantic,
3144                                                 builtins.glPosition.index, 4, outputSlot);
3145             }
3146         }
3147         else if (tfVaryingName == "gl_FragCoord")
3148         {
3149             if (builtins.glFragCoord.enabled)
3150             {
3151                 mStreamOutVaryings.emplace_back(builtins.glFragCoord.semantic,
3152                                                 builtins.glFragCoord.index, 4, outputSlot);
3153             }
3154         }
3155         else if (tfVaryingName == "gl_PointSize")
3156         {
3157             if (builtins.glPointSize.enabled)
3158             {
3159                 mStreamOutVaryings.emplace_back("PSIZE", 0, 1, outputSlot);
3160             }
3161         }
3162         else
3163         {
3164             const auto &registerInfos = varyingPacking.getRegisterList();
3165             for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
3166             {
3167                 const auto &registerInfo = registerInfos[registerIndex];
3168                 const auto &varying      = registerInfo.packedVarying->varying();
3169                 GLenum transposedType    = gl::TransposeMatrixType(varying.type);
3170                 int componentCount       = gl::VariableColumnCount(transposedType);
3171                 ASSERT(!varying.isBuiltIn() && !varying.isStruct());
3172 
3173                 // There can be more than one register assigned to a particular varying, and each
3174                 // register needs its own stream out entry.
3175                 if (registerInfo.tfVaryingName() == tfVaryingName)
3176                 {
3177                     mStreamOutVaryings.emplace_back(varyingSemantic, registerIndex, componentCount,
3178                                                     outputSlot);
3179                 }
3180             }
3181         }
3182     }
3183 }
3184 
getD3DUniformFromLocation(GLint location)3185 D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
3186 {
3187     return mD3DUniforms[mState.getUniformLocations()[location].index];
3188 }
3189 
getD3DUniformFromLocation(GLint location) const3190 const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const
3191 {
3192     return mD3DUniforms[mState.getUniformLocations()[location].index];
3193 }
3194 
hasVertexExecutableForCachedInputLayout()3195 bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
3196 {
3197     return mCachedVertexExecutableIndex.valid();
3198 }
3199 
hasGeometryExecutableForPrimitiveType(const gl::State & state,gl::PrimitiveMode drawMode)3200 bool ProgramD3D::hasGeometryExecutableForPrimitiveType(const gl::State &state,
3201                                                        gl::PrimitiveMode drawMode)
3202 {
3203     if (!usesGeometryShader(state, drawMode))
3204     {
3205         // No shader necessary mean we have the required (null) executable.
3206         return true;
3207     }
3208 
3209     gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
3210     return mGeometryExecutables[geometryShaderType].get() != nullptr;
3211 }
3212 
hasPixelExecutableForCachedOutputLayout()3213 bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
3214 {
3215     return mCachedPixelExecutableIndex.valid();
3216 }
3217 
hasComputeExecutableForCachedImage2DBindLayout()3218 bool ProgramD3D::hasComputeExecutableForCachedImage2DBindLayout()
3219 {
3220     return mCachedComputeExecutableIndex.valid();
3221 }
3222 
3223 template <typename DestT>
getUniformInternal(GLint location,DestT * dataOut) const3224 void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const
3225 {
3226     const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
3227     const gl::LinkedUniform &uniform         = mState.getUniforms()[locationInfo.index];
3228 
3229     const D3DUniform *targetUniform = getD3DUniformFromLocation(location);
3230     const uint8_t *srcPointer       = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
3231 
3232     if (gl::IsMatrixType(uniform.type))
3233     {
3234         GetMatrixUniform(uniform.type, dataOut, reinterpret_cast<const DestT *>(srcPointer), true);
3235     }
3236     else
3237     {
3238         memcpy(dataOut, srcPointer, uniform.getElementSize());
3239     }
3240 }
3241 
getUniformfv(const gl::Context * context,GLint location,GLfloat * params) const3242 void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
3243 {
3244     getUniformInternal(location, params);
3245 }
3246 
getUniformiv(const gl::Context * context,GLint location,GLint * params) const3247 void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
3248 {
3249     getUniformInternal(location, params);
3250 }
3251 
getUniformuiv(const gl::Context * context,GLint location,GLuint * params) const3252 void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
3253 {
3254     getUniformInternal(location, params);
3255 }
3256 
updateCachedVertexExecutableIndex()3257 void ProgramD3D::updateCachedVertexExecutableIndex()
3258 {
3259     mCachedVertexExecutableIndex.reset();
3260     for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
3261     {
3262         if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
3263         {
3264             mCachedVertexExecutableIndex = executableIndex;
3265             break;
3266         }
3267     }
3268 }
3269 
updateCachedPixelExecutableIndex()3270 void ProgramD3D::updateCachedPixelExecutableIndex()
3271 {
3272     mCachedPixelExecutableIndex.reset();
3273     for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
3274     {
3275         if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
3276         {
3277             mCachedPixelExecutableIndex = executableIndex;
3278             break;
3279         }
3280     }
3281 }
3282 
updateCachedComputeExecutableIndex()3283 void ProgramD3D::updateCachedComputeExecutableIndex()
3284 {
3285     mCachedComputeExecutableIndex.reset();
3286     for (size_t executableIndex = 0; executableIndex < mComputeExecutables.size();
3287          executableIndex++)
3288     {
3289         if (mComputeExecutables[executableIndex]->matchesSignature(
3290                 mComputeShaderImage2DBindLayoutCache))
3291         {
3292             mCachedComputeExecutableIndex = executableIndex;
3293             break;
3294         }
3295     }
3296 }
3297 
linkResources(const gl::ProgramLinkedResources & resources)3298 void ProgramD3D::linkResources(const gl::ProgramLinkedResources &resources)
3299 {
3300     HLSLBlockLayoutEncoderFactory hlslEncoderFactory;
3301     gl::ProgramLinkedResourcesLinker linker(&hlslEncoderFactory);
3302 
3303     linker.linkResources(mState, resources);
3304 
3305     initializeUniformBlocks();
3306     initializeShaderStorageBlocks();
3307 }
3308 
3309 }  // namespace rx
3310