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