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