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