xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/d3d/ProgramExecutableD3D.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2023 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 // ProgramExecutableD3D.cpp: Implementation of ProgramExecutableD3D.
7 
8 #include "libANGLE/renderer/d3d/ProgramExecutableD3D.h"
9 
10 #include "common/bitset_utils.h"
11 #include "common/string_utils.h"
12 #include "libANGLE/Framebuffer.h"
13 #include "libANGLE/FramebufferAttachment.h"
14 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
15 #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
16 #include "libANGLE/trace.h"
17 
18 namespace rx
19 {
20 namespace
21 {
GetDefaultInputLayoutFromShader(const gl::SharedCompiledShaderState & vertexShader,gl::InputLayout * inputLayoutOut)22 void GetDefaultInputLayoutFromShader(const gl::SharedCompiledShaderState &vertexShader,
23                                      gl::InputLayout *inputLayoutOut)
24 {
25     inputLayoutOut->clear();
26 
27     if (!vertexShader)
28     {
29         return;
30     }
31 
32     for (const sh::ShaderVariable &shaderAttr : vertexShader->activeAttributes)
33     {
34         if (shaderAttr.type != GL_NONE)
35         {
36             GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
37 
38             for (size_t rowIndex = 0;
39                  static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
40             {
41                 GLenum componentType = gl::VariableComponentType(transposedType);
42                 GLuint components    = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
43                 bool pureInt         = (componentType != GL_FLOAT);
44 
45                 gl::VertexAttribType attribType =
46                     gl::FromGLenum<gl::VertexAttribType>(componentType);
47 
48                 angle::FormatID defaultID =
49                     gl::GetVertexFormatID(attribType, GL_FALSE, components, pureInt);
50 
51                 inputLayoutOut->push_back(defaultID);
52             }
53         }
54     }
55 }
56 
GetMaxOutputIndex(const std::vector<PixelShaderOutputVariable> & shaderOutputVars,size_t location)57 size_t GetMaxOutputIndex(const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
58                          size_t location)
59 {
60     size_t maxIndex = 0;
61     for (auto &outputVar : shaderOutputVars)
62     {
63         if (outputVar.outputLocation == location)
64         {
65             maxIndex = std::max(maxIndex, outputVar.outputIndex);
66         }
67     }
68     return maxIndex;
69 }
70 
GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> & shaderOutputVars,std::vector<GLenum> * outputLayoutOut)71 void GetDefaultOutputLayoutFromShader(
72     const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
73     std::vector<GLenum> *outputLayoutOut)
74 {
75     outputLayoutOut->clear();
76 
77     if (!shaderOutputVars.empty())
78     {
79         size_t location = shaderOutputVars[0].outputLocation;
80         size_t maxIndex = GetMaxOutputIndex(shaderOutputVars, location);
81         outputLayoutOut->assign(maxIndex + 1,
82                                 GL_COLOR_ATTACHMENT0 + static_cast<unsigned int>(location));
83     }
84 }
85 
GetDefaultImage2DBindLayoutFromShader(const std::vector<sh::ShaderVariable> & image2DUniforms,gl::ImageUnitTextureTypeMap * image2DBindLayout)86 void GetDefaultImage2DBindLayoutFromShader(const std::vector<sh::ShaderVariable> &image2DUniforms,
87                                            gl::ImageUnitTextureTypeMap *image2DBindLayout)
88 {
89     image2DBindLayout->clear();
90 
91     for (const sh::ShaderVariable &image2D : image2DUniforms)
92     {
93         if (gl::IsImage2DType(image2D.type))
94         {
95             if (image2D.binding == -1)
96             {
97                 image2DBindLayout->insert(std::make_pair(0, gl::TextureType::_2D));
98             }
99             else
100             {
101                 for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++)
102                 {
103                     image2DBindLayout->insert(
104                         std::make_pair(image2D.binding + index, gl::TextureType::_2D));
105                 }
106             }
107         }
108     }
109 }
110 
GetGeometryShaderTypeFromDrawMode(gl::PrimitiveMode drawMode)111 gl::PrimitiveMode GetGeometryShaderTypeFromDrawMode(gl::PrimitiveMode drawMode)
112 {
113     switch (drawMode)
114     {
115         // Uses the point sprite geometry shader.
116         case gl::PrimitiveMode::Points:
117             return gl::PrimitiveMode::Points;
118 
119         // All line drawing uses the same geometry shader.
120         case gl::PrimitiveMode::Lines:
121         case gl::PrimitiveMode::LineStrip:
122         case gl::PrimitiveMode::LineLoop:
123             return gl::PrimitiveMode::Lines;
124 
125         // The triangle fan primitive is emulated with strips in D3D11.
126         case gl::PrimitiveMode::Triangles:
127         case gl::PrimitiveMode::TriangleFan:
128             return gl::PrimitiveMode::Triangles;
129 
130         // Special case for triangle strips.
131         case gl::PrimitiveMode::TriangleStrip:
132             return gl::PrimitiveMode::TriangleStrip;
133 
134         default:
135             UNREACHABLE();
136             return gl::PrimitiveMode::InvalidEnum;
137     }
138 }
139 
140 // Helper class that gathers uniform info from the default uniform block.
141 class UniformEncodingVisitorD3D : public sh::BlockEncoderVisitor
142 {
143   public:
UniformEncodingVisitorD3D(gl::ShaderType shaderType,HLSLRegisterType registerType,sh::BlockLayoutEncoder * encoder,D3DUniformMap * uniformMapOut)144     UniformEncodingVisitorD3D(gl::ShaderType shaderType,
145                               HLSLRegisterType registerType,
146                               sh::BlockLayoutEncoder *encoder,
147                               D3DUniformMap *uniformMapOut)
148         : sh::BlockEncoderVisitor("", "", encoder),
149           mShaderType(shaderType),
150           mRegisterType(registerType),
151           mUniformMapOut(uniformMapOut)
152     {}
153 
visitNamedOpaqueObject(const sh::ShaderVariable & sampler,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)154     void visitNamedOpaqueObject(const sh::ShaderVariable &sampler,
155                                 const std::string &name,
156                                 const std::string &mappedName,
157                                 const std::vector<unsigned int> &arraySizes) override
158     {
159         auto uniformMapEntry = mUniformMapOut->find(name);
160         if (uniformMapEntry == mUniformMapOut->end())
161         {
162             (*mUniformMapOut)[name] =
163                 new D3DUniform(sampler.type, mRegisterType, name, sampler.arraySizes, true);
164         }
165     }
166 
encodeVariable(const sh::ShaderVariable & variable,const sh::BlockMemberInfo & variableInfo,const std::string & name,const std::string & mappedName)167     void encodeVariable(const sh::ShaderVariable &variable,
168                         const sh::BlockMemberInfo &variableInfo,
169                         const std::string &name,
170                         const std::string &mappedName) override
171     {
172         auto uniformMapEntry   = mUniformMapOut->find(name);
173         D3DUniform *d3dUniform = nullptr;
174 
175         if (uniformMapEntry != mUniformMapOut->end())
176         {
177             d3dUniform = uniformMapEntry->second;
178         }
179         else
180         {
181             d3dUniform =
182                 new D3DUniform(variable.type, mRegisterType, name, variable.arraySizes, true);
183             (*mUniformMapOut)[name] = d3dUniform;
184         }
185 
186         d3dUniform->registerElement = static_cast<unsigned int>(
187             sh::BlockLayoutEncoder::GetBlockRegisterElement(variableInfo));
188         unsigned int reg =
189             static_cast<unsigned int>(sh::BlockLayoutEncoder::GetBlockRegister(variableInfo));
190 
191         ASSERT(mShaderType != gl::ShaderType::InvalidEnum);
192         d3dUniform->mShaderRegisterIndexes[mShaderType] = reg;
193     }
194 
195   private:
196     gl::ShaderType mShaderType;
197     HLSLRegisterType mRegisterType;
198     D3DUniformMap *mUniformMapOut;
199 };
200 
201 }  // anonymous namespace
202 
203 // D3DUniform Implementation
D3DUniform(GLenum type,HLSLRegisterType reg,const std::string & nameIn,const std::vector<unsigned int> & arraySizesIn,bool defaultBlock)204 D3DUniform::D3DUniform(GLenum type,
205                        HLSLRegisterType reg,
206                        const std::string &nameIn,
207                        const std::vector<unsigned int> &arraySizesIn,
208                        bool defaultBlock)
209     : typeInfo(gl::GetUniformTypeInfo(type)),
210       name(nameIn),
211       arraySizes(arraySizesIn),
212       mShaderData({}),
213       regType(reg),
214       registerCount(0),
215       registerElement(0)
216 {
217     mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
218 
219     // We use data storage for default block uniforms to cache values that are sent to D3D during
220     // rendering
221     // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
222     if (defaultBlock)
223     {
224         // Use the row count as register count, will work for non-square matrices.
225         registerCount = typeInfo.rowCount * getArraySizeProduct();
226     }
227 }
228 
~D3DUniform()229 D3DUniform::~D3DUniform() {}
230 
getArraySizeProduct() const231 unsigned int D3DUniform::getArraySizeProduct() const
232 {
233     return gl::ArraySizeProduct(arraySizes);
234 }
235 
getDataPtrToElement(size_t elementIndex) const236 const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
237 {
238     ASSERT((!isArray() && elementIndex == 0) ||
239            (isArray() && elementIndex < getArraySizeProduct()));
240 
241     if (isSampler())
242     {
243         return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
244     }
245 
246     return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
247 }
248 
isSampler() const249 bool D3DUniform::isSampler() const
250 {
251     return typeInfo.isSampler;
252 }
253 
isImage() const254 bool D3DUniform::isImage() const
255 {
256     return typeInfo.isImageType;
257 }
258 
isImage2D() const259 bool D3DUniform::isImage2D() const
260 {
261     return gl::IsImage2DType(typeInfo.type);
262 }
263 
isReferencedByShader(gl::ShaderType shaderType) const264 bool D3DUniform::isReferencedByShader(gl::ShaderType shaderType) const
265 {
266     return mShaderRegisterIndexes[shaderType] != GL_INVALID_INDEX;
267 }
268 
firstNonNullData() const269 const uint8_t *D3DUniform::firstNonNullData() const
270 {
271     if (!mSamplerData.empty())
272     {
273         return reinterpret_cast<const uint8_t *>(mSamplerData.data());
274     }
275 
276     for (gl::ShaderType shaderType : gl::AllShaderTypes())
277     {
278         if (mShaderData[shaderType])
279         {
280             return mShaderData[shaderType];
281         }
282     }
283 
284     UNREACHABLE();
285     return nullptr;
286 }
287 
288 // D3DInterfaceBlock Implementation
D3DInterfaceBlock()289 D3DInterfaceBlock::D3DInterfaceBlock()
290 {
291     mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
292 }
293 
294 D3DInterfaceBlock::D3DInterfaceBlock(const D3DInterfaceBlock &other) = default;
295 
D3DUniformBlock()296 D3DUniformBlock::D3DUniformBlock()
297 {
298     mUseStructuredBuffers.fill(false);
299     mByteWidths.fill(0u);
300     mStructureByteStrides.fill(0u);
301 }
302 
303 D3DUniformBlock::D3DUniformBlock(const D3DUniformBlock &other) = default;
304 
305 // D3DVarying Implementation
D3DVarying()306 D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) {}
307 
D3DVarying(const std::string & semanticNameIn,unsigned int semanticIndexIn,unsigned int componentCountIn,unsigned int outputSlotIn)308 D3DVarying::D3DVarying(const std::string &semanticNameIn,
309                        unsigned int semanticIndexIn,
310                        unsigned int componentCountIn,
311                        unsigned int outputSlotIn)
312     : semanticName(semanticNameIn),
313       semanticIndex(semanticIndexIn),
314       componentCount(componentCountIn),
315       outputSlot(outputSlotIn)
316 {}
317 
D3DVertexExecutable(const gl::InputLayout & inputLayout,const Signature & signature,ShaderExecutableD3D * shaderExecutable)318 D3DVertexExecutable::D3DVertexExecutable(const gl::InputLayout &inputLayout,
319                                          const Signature &signature,
320                                          ShaderExecutableD3D *shaderExecutable)
321     : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
322 {}
323 
~D3DVertexExecutable()324 D3DVertexExecutable::~D3DVertexExecutable()
325 {
326     SafeDelete(mShaderExecutable);
327 }
328 
329 // static
GetAttribType(GLenum type)330 D3DVertexExecutable::HLSLAttribType D3DVertexExecutable::GetAttribType(GLenum type)
331 {
332     switch (type)
333     {
334         case GL_INT:
335             return HLSLAttribType::SIGNED_INT;
336         case GL_UNSIGNED_INT:
337             return HLSLAttribType::UNSIGNED_INT;
338         case GL_SIGNED_NORMALIZED:
339         case GL_UNSIGNED_NORMALIZED:
340         case GL_FLOAT:
341             return HLSLAttribType::FLOAT;
342         default:
343             UNREACHABLE();
344             return HLSLAttribType::FLOAT;
345     }
346 }
347 
348 // static
getSignature(RendererD3D * renderer,const gl::InputLayout & inputLayout,Signature * signatureOut)349 void D3DVertexExecutable::getSignature(RendererD3D *renderer,
350                                        const gl::InputLayout &inputLayout,
351                                        Signature *signatureOut)
352 {
353     signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
354 
355     for (size_t index = 0; index < inputLayout.size(); ++index)
356     {
357         angle::FormatID vertexFormatID = inputLayout[index];
358         if (vertexFormatID == angle::FormatID::NONE)
359             continue;
360 
361         VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatID);
362         if ((conversionType & VERTEX_CONVERT_GPU) == 0)
363             continue;
364 
365         GLenum componentType   = renderer->getVertexComponentType(vertexFormatID);
366         (*signatureOut)[index] = GetAttribType(componentType);
367     }
368 }
369 
matchesSignature(const Signature & signature) const370 bool D3DVertexExecutable::matchesSignature(const Signature &signature) const
371 {
372     size_t limit = std::max(mSignature.size(), signature.size());
373     for (size_t index = 0; index < limit; ++index)
374     {
375         // treat undefined indexes as FLOAT
376         auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
377         auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
378         if (a != b)
379             return false;
380     }
381 
382     return true;
383 }
384 
D3DPixelExecutable(const std::vector<GLenum> & outputSignature,const gl::ImageUnitTextureTypeMap & image2DSignature,ShaderExecutableD3D * shaderExecutable)385 D3DPixelExecutable::D3DPixelExecutable(const std::vector<GLenum> &outputSignature,
386                                        const gl::ImageUnitTextureTypeMap &image2DSignature,
387                                        ShaderExecutableD3D *shaderExecutable)
388     : mOutputSignature(outputSignature),
389       mImage2DSignature(image2DSignature),
390       mShaderExecutable(shaderExecutable)
391 {}
392 
~D3DPixelExecutable()393 D3DPixelExecutable::~D3DPixelExecutable()
394 {
395     SafeDelete(mShaderExecutable);
396 }
397 
D3DComputeExecutable(const gl::ImageUnitTextureTypeMap & signature,std::unique_ptr<ShaderExecutableD3D> shaderExecutable)398 D3DComputeExecutable::D3DComputeExecutable(const gl::ImageUnitTextureTypeMap &signature,
399                                            std::unique_ptr<ShaderExecutableD3D> shaderExecutable)
400     : mSignature(signature), mShaderExecutable(std::move(shaderExecutable))
401 {}
402 
~D3DComputeExecutable()403 D3DComputeExecutable::~D3DComputeExecutable() {}
404 
D3DSampler()405 D3DSampler::D3DSampler() : active(false), logicalTextureUnit(0), textureType(gl::TextureType::_2D)
406 {}
407 
D3DImage()408 D3DImage::D3DImage() : active(false), logicalImageUnit(0) {}
409 
410 unsigned int ProgramExecutableD3D::mCurrentSerial = 1;
411 
ProgramExecutableD3D(const gl::ProgramExecutable * executable)412 ProgramExecutableD3D::ProgramExecutableD3D(const gl::ProgramExecutable *executable)
413     : ProgramExecutableImpl(executable),
414       mUsesPointSize(false),
415       mUsesFlatInterpolation(false),
416       mUsedShaderSamplerRanges({}),
417       mDirtySamplerMapping(true),
418       mUsedImageRange({}),
419       mUsedReadonlyImageRange({}),
420       mUsedAtomicCounterRange({}),
421       mSerial(issueSerial())
422 {
423     reset();
424 }
425 
~ProgramExecutableD3D()426 ProgramExecutableD3D::~ProgramExecutableD3D() {}
427 
destroy(const gl::Context * context)428 void ProgramExecutableD3D::destroy(const gl::Context *context) {}
429 
reset()430 void ProgramExecutableD3D::reset()
431 {
432     mVertexExecutables.clear();
433     mPixelExecutables.clear();
434     mComputeExecutables.clear();
435 
436     for (auto &geometryExecutable : mGeometryExecutables)
437     {
438         geometryExecutable.reset(nullptr);
439     }
440 
441     for (gl::ShaderType shaderType : gl::AllShaderTypes())
442     {
443         mShaderHLSL[shaderType].clear();
444     }
445 
446     mFragDepthUsage      = FragDepthUsage::Unused;
447     mUsesSampleMask      = false;
448     mHasMultiviewEnabled = false;
449     mUsesVertexID        = false;
450     mUsesViewID          = false;
451     mPixelShaderKey.clear();
452     mUsesPointSize         = false;
453     mUsesFlatInterpolation = false;
454 
455     SafeDeleteContainer(mD3DUniforms);
456     mD3DUniformBlocks.clear();
457     mD3DShaderStorageBlocks.clear();
458     mComputeAtomicCounterBufferRegisterIndices.fill({});
459 
460     for (gl::ShaderType shaderType : gl::AllShaderTypes())
461     {
462         mShaderUniformStorages[shaderType].reset();
463         mShaderSamplers[shaderType].clear();
464         mImages[shaderType].clear();
465         mReadonlyImages[shaderType].clear();
466     }
467 
468     mUsedShaderSamplerRanges.fill({0, 0});
469     mUsedAtomicCounterRange.fill({0, 0});
470     mDirtySamplerMapping = true;
471     mUsedImageRange.fill({0, 0});
472     mUsedReadonlyImageRange.fill({0, 0});
473 
474     mAttribLocationToD3DSemantic.fill(-1);
475 
476     mStreamOutVaryings.clear();
477 
478     mGeometryShaderPreamble.clear();
479 
480     markUniformsClean();
481 
482     mCachedPixelExecutableIndex.reset();
483     mCachedVertexExecutableIndex.reset();
484 }
485 
load(const gl::Context * context,RendererD3D * renderer,gl::BinaryInputStream * stream)486 bool ProgramExecutableD3D::load(const gl::Context *context,
487                                 RendererD3D *renderer,
488                                 gl::BinaryInputStream *stream)
489 {
490     gl::InfoLog &infoLog = mExecutable->getInfoLog();
491 
492     reset();
493 
494     DeviceIdentifier binaryDeviceIdentifier = {};
495     stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
496                       sizeof(DeviceIdentifier));
497 
498     DeviceIdentifier identifier = renderer->getAdapterIdentifier();
499     if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
500     {
501         infoLog << "Invalid program binary, device configuration has changed.";
502         return false;
503     }
504 
505     int compileFlags = stream->readInt<int>();
506     if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
507     {
508         infoLog << "Mismatched compilation flags.";
509         return false;
510     }
511 
512     for (int &index : mAttribLocationToD3DSemantic)
513     {
514         stream->readInt(&index);
515     }
516 
517     for (gl::ShaderType shaderType : gl::AllShaderTypes())
518     {
519         size_t samplerCount = stream->readInt<size_t>();
520         for (size_t sampleIndex = 0; sampleIndex < samplerCount; ++sampleIndex)
521         {
522             D3DSampler sampler;
523             stream->readBool(&sampler.active);
524             stream->readInt(&sampler.logicalTextureUnit);
525             stream->readEnum(&sampler.textureType);
526             mShaderSamplers[shaderType].push_back(sampler);
527         }
528 
529         unsigned int samplerRangeLow, samplerRangeHigh;
530         stream->readInt(&samplerRangeLow);
531         stream->readInt(&samplerRangeHigh);
532         mUsedShaderSamplerRanges[shaderType] = gl::RangeUI(samplerRangeLow, samplerRangeHigh);
533     }
534 
535     for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
536     {
537         size_t imageCount = stream->readInt<size_t>();
538         for (size_t imageIndex = 0; imageIndex < imageCount; ++imageIndex)
539         {
540             D3DImage image;
541             stream->readBool(&image.active);
542             stream->readInt(&image.logicalImageUnit);
543             mImages[shaderType].push_back(image);
544         }
545 
546         size_t readonlyImageCount = stream->readInt<size_t>();
547         for (size_t imageIndex = 0; imageIndex < readonlyImageCount; ++imageIndex)
548         {
549             D3DImage image;
550             stream->readBool(&image.active);
551             stream->readInt(&image.logicalImageUnit);
552             mReadonlyImages[shaderType].push_back(image);
553         }
554 
555         unsigned int imageRangeLow, imageRangeHigh, readonlyImageRangeLow, readonlyImageRangeHigh;
556         stream->readInt(&imageRangeLow);
557         stream->readInt(&imageRangeHigh);
558         stream->readInt(&readonlyImageRangeLow);
559         stream->readInt(&readonlyImageRangeHigh);
560         mUsedImageRange[shaderType] = gl::RangeUI(imageRangeLow, imageRangeHigh);
561         mUsedReadonlyImageRange[shaderType] =
562             gl::RangeUI(readonlyImageRangeLow, readonlyImageRangeHigh);
563 
564         unsigned int atomicCounterRangeLow, atomicCounterRangeHigh;
565         stream->readInt(&atomicCounterRangeLow);
566         stream->readInt(&atomicCounterRangeHigh);
567         mUsedAtomicCounterRange[shaderType] =
568             gl::RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
569     }
570 
571     size_t shaderStorageBlockCount = stream->readInt<size_t>();
572     if (stream->error())
573     {
574         infoLog << "Invalid program binary.";
575         return false;
576     }
577 
578     ASSERT(mD3DShaderStorageBlocks.empty());
579     for (size_t blockIndex = 0; blockIndex < shaderStorageBlockCount; ++blockIndex)
580     {
581         D3DInterfaceBlock shaderStorageBlock;
582         for (gl::ShaderType shaderType : gl::AllShaderTypes())
583         {
584             stream->readInt(&shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
585         }
586         mD3DShaderStorageBlocks.push_back(shaderStorageBlock);
587     }
588 
589     for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
590     {
591         size_t image2DUniformCount = stream->readInt<size_t>();
592         if (stream->error())
593         {
594             infoLog << "Invalid program binary.";
595             return false;
596         }
597 
598         ASSERT(mImage2DUniforms[shaderType].empty());
599         for (size_t image2DUniformIndex = 0; image2DUniformIndex < image2DUniformCount;
600              ++image2DUniformIndex)
601         {
602             sh::ShaderVariable image2Duniform;
603             gl::LoadShaderVar(stream, &image2Duniform);
604             mImage2DUniforms[shaderType].push_back(image2Duniform);
605         }
606     }
607 
608     for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS; ++ii)
609     {
610         unsigned int index                             = stream->readInt<unsigned int>();
611         mComputeAtomicCounterBufferRegisterIndices[ii] = index;
612     }
613 
614     size_t uniformCount = stream->readInt<size_t>();
615     if (stream->error())
616     {
617         infoLog << "Invalid program binary.";
618         return false;
619     }
620 
621     const auto &linkedUniforms = mExecutable->getUniforms();
622     ASSERT(mD3DUniforms.empty());
623     for (size_t uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
624     {
625         const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
626         // Could D3DUniform just change to use unsigned int instead of std::vector for arraySizes?
627         // Frontend always flatten the array to at most 1D array.
628         std::vector<unsigned int> arraySizes;
629         if (linkedUniform.isArray())
630         {
631             arraySizes.push_back(linkedUniform.getBasicTypeElementCount());
632         }
633         D3DUniform *d3dUniform = new D3DUniform(linkedUniform.getType(), HLSLRegisterType::None,
634                                                 mExecutable->getUniformNames()[uniformIndex],
635                                                 arraySizes, linkedUniform.isInDefaultBlock());
636         stream->readEnum(&d3dUniform->regType);
637         for (gl::ShaderType shaderType : gl::AllShaderTypes())
638         {
639             stream->readInt(&d3dUniform->mShaderRegisterIndexes[shaderType]);
640         }
641         stream->readInt(&d3dUniform->registerCount);
642         stream->readInt(&d3dUniform->registerElement);
643 
644         mD3DUniforms.push_back(d3dUniform);
645     }
646 
647     size_t blockCount = stream->readInt<size_t>();
648     if (stream->error())
649     {
650         infoLog << "Invalid program binary.";
651         return false;
652     }
653 
654     ASSERT(mD3DUniformBlocks.empty());
655     for (size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
656     {
657         D3DUniformBlock uniformBlock;
658         for (gl::ShaderType shaderType : gl::AllShaderTypes())
659         {
660             stream->readInt(&uniformBlock.mShaderRegisterIndexes[shaderType]);
661             stream->readBool(&uniformBlock.mUseStructuredBuffers[shaderType]);
662             stream->readInt(&uniformBlock.mByteWidths[shaderType]);
663             stream->readInt(&uniformBlock.mStructureByteStrides[shaderType]);
664         }
665         mD3DUniformBlocks.push_back(uniformBlock);
666     }
667 
668     size_t streamOutVaryingCount = stream->readInt<size_t>();
669     mStreamOutVaryings.resize(streamOutVaryingCount);
670     for (size_t varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
671     {
672         D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
673 
674         stream->readString(&varying->semanticName);
675         stream->readInt(&varying->semanticIndex);
676         stream->readInt(&varying->componentCount);
677         stream->readInt(&varying->outputSlot);
678     }
679 
680     for (gl::ShaderType shaderType : gl::AllShaderTypes())
681     {
682         stream->readString(&mShaderHLSL[shaderType]);
683         stream->readBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
684                           sizeof(CompilerWorkaroundsD3D));
685     }
686 
687     stream->readEnum(&mFragDepthUsage);
688     stream->readBool(&mUsesSampleMask);
689     stream->readBool(&mHasMultiviewEnabled);
690     stream->readBool(&mUsesVertexID);
691     stream->readBool(&mUsesViewID);
692     stream->readBool(&mUsesPointSize);
693     stream->readBool(&mUsesFlatInterpolation);
694 
695     const size_t pixelShaderKeySize = stream->readInt<size_t>();
696     mPixelShaderKey.resize(pixelShaderKeySize);
697     for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
698          pixelShaderKeyIndex++)
699     {
700         stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
701         stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
702         stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
703         stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputLocation);
704         stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
705     }
706 
707     stream->readString(&mGeometryShaderPreamble);
708 
709     return true;
710 }
711 
loadBinaryShaderExecutables(d3d::Context * contextD3D,RendererD3D * renderer,gl::BinaryInputStream * stream)712 angle::Result ProgramExecutableD3D::loadBinaryShaderExecutables(d3d::Context *contextD3D,
713                                                                 RendererD3D *renderer,
714                                                                 gl::BinaryInputStream *stream)
715 {
716     gl::InfoLog &infoLog        = mExecutable->getInfoLog();
717     const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
718 
719     bool separateAttribs = mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS;
720 
721     size_t vertexShaderCount = stream->readInt<size_t>();
722     for (size_t vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
723     {
724         size_t inputLayoutSize = stream->readInt<size_t>();
725         gl::InputLayout inputLayout(inputLayoutSize, angle::FormatID::NONE);
726 
727         for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
728         {
729             inputLayout[inputIndex] = stream->readEnum<angle::FormatID>();
730         }
731 
732         size_t vertexShaderSize                   = stream->readInt<size_t>();
733         const unsigned char *vertexShaderFunction = binary + stream->offset();
734 
735         ShaderExecutableD3D *shaderExecutable = nullptr;
736 
737         ANGLE_TRY(renderer->loadExecutable(contextD3D, vertexShaderFunction, vertexShaderSize,
738                                            gl::ShaderType::Vertex, mStreamOutVaryings,
739                                            separateAttribs, &shaderExecutable));
740 
741         if (!shaderExecutable)
742         {
743             infoLog << "Could not create vertex shader.";
744             return angle::Result::Stop;
745         }
746 
747         // generated converted input layout
748         D3DVertexExecutable::Signature signature;
749         D3DVertexExecutable::getSignature(renderer, inputLayout, &signature);
750 
751         // add new binary
752         mVertexExecutables.push_back(std::unique_ptr<D3DVertexExecutable>(
753             new D3DVertexExecutable(inputLayout, signature, shaderExecutable)));
754 
755         stream->skip(vertexShaderSize);
756     }
757 
758     size_t pixelShaderCount = stream->readInt<size_t>();
759     for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
760     {
761         size_t outputCount = stream->readInt<size_t>();
762         std::vector<GLenum> outputs(outputCount);
763         for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
764         {
765             stream->readInt(&outputs[outputIndex]);
766         }
767 
768         const size_t image2DCount = stream->readInt<size_t>();
769         gl::ImageUnitTextureTypeMap image2Ds;
770         for (size_t index = 0; index < image2DCount; index++)
771         {
772             unsigned int imageUint;
773             gl::TextureType textureType;
774             stream->readInt(&imageUint);
775             stream->readEnum(&textureType);
776             image2Ds.insert({imageUint, textureType});
777         }
778 
779         size_t pixelShaderSize                   = stream->readInt<size_t>();
780         const unsigned char *pixelShaderFunction = binary + stream->offset();
781         ShaderExecutableD3D *shaderExecutable    = nullptr;
782 
783         ANGLE_TRY(renderer->loadExecutable(contextD3D, pixelShaderFunction, pixelShaderSize,
784                                            gl::ShaderType::Fragment, mStreamOutVaryings,
785                                            separateAttribs, &shaderExecutable));
786 
787         if (!shaderExecutable)
788         {
789             infoLog << "Could not create pixel shader.";
790             return angle::Result::Stop;
791         }
792 
793         // add new binary
794         mPixelExecutables.push_back(std::unique_ptr<D3DPixelExecutable>(
795             new D3DPixelExecutable(outputs, image2Ds, shaderExecutable)));
796 
797         stream->skip(pixelShaderSize);
798     }
799 
800     for (std::unique_ptr<ShaderExecutableD3D> &geometryExe : mGeometryExecutables)
801     {
802         size_t geometryShaderSize = stream->readInt<size_t>();
803         if (geometryShaderSize == 0)
804         {
805             continue;
806         }
807 
808         const unsigned char *geometryShaderFunction = binary + stream->offset();
809 
810         ShaderExecutableD3D *geometryExecutable = nullptr;
811         ANGLE_TRY(renderer->loadExecutable(contextD3D, geometryShaderFunction, geometryShaderSize,
812                                            gl::ShaderType::Geometry, mStreamOutVaryings,
813                                            separateAttribs, &geometryExecutable));
814 
815         if (!geometryExecutable)
816         {
817             infoLog << "Could not create geometry shader.";
818             return angle::Result::Stop;
819         }
820 
821         geometryExe.reset(geometryExecutable);
822 
823         stream->skip(geometryShaderSize);
824     }
825 
826     size_t computeShaderCount = stream->readInt<size_t>();
827     for (size_t computeShaderIndex = 0; computeShaderIndex < computeShaderCount;
828          computeShaderIndex++)
829     {
830         size_t signatureCount = stream->readInt<size_t>();
831         gl::ImageUnitTextureTypeMap signatures;
832         for (size_t signatureIndex = 0; signatureIndex < signatureCount; signatureIndex++)
833         {
834             unsigned int imageUint;
835             gl::TextureType textureType;
836             stream->readInt(&imageUint);
837             stream->readEnum(&textureType);
838             signatures.insert(std::pair<unsigned int, gl::TextureType>(imageUint, textureType));
839         }
840 
841         size_t computeShaderSize                   = stream->readInt<size_t>();
842         const unsigned char *computeShaderFunction = binary + stream->offset();
843 
844         ShaderExecutableD3D *computeExecutable = nullptr;
845         ANGLE_TRY(renderer->loadExecutable(contextD3D, computeShaderFunction, computeShaderSize,
846                                            gl::ShaderType::Compute, std::vector<D3DVarying>(),
847                                            false, &computeExecutable));
848 
849         if (!computeExecutable)
850         {
851             infoLog << "Could not create compute shader.";
852             return angle::Result::Stop;
853         }
854 
855         // add new binary
856         mComputeExecutables.push_back(
857             std::unique_ptr<D3DComputeExecutable>(new D3DComputeExecutable(
858                 signatures, std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
859 
860         stream->skip(computeShaderSize);
861     }
862 
863     for (const gl::ShaderType shaderType :
864          {gl::ShaderType::Vertex, gl::ShaderType::Fragment, gl::ShaderType::Compute})
865     {
866         size_t bindLayoutCount = stream->readInt<size_t>();
867         for (size_t bindLayoutIndex = 0; bindLayoutIndex < bindLayoutCount; bindLayoutIndex++)
868         {
869             mImage2DBindLayoutCache[shaderType].insert(std::pair<unsigned int, gl::TextureType>(
870                 stream->readInt<unsigned int>(), gl::TextureType::_2D));
871         }
872     }
873 
874     initializeUniformStorage(renderer, mExecutable->getLinkedShaderStages());
875 
876     dirtyAllUniforms();
877 
878     return angle::Result::Continue;
879 }
880 
save(const gl::Context * context,RendererD3D * renderer,gl::BinaryOutputStream * stream)881 void ProgramExecutableD3D::save(const gl::Context *context,
882                                 RendererD3D *renderer,
883                                 gl::BinaryOutputStream *stream)
884 {
885     // Output the DeviceIdentifier before we output any shader code
886     // When we load the binary again later, we can validate the device identifier before trying to
887     // compile any HLSL
888     DeviceIdentifier binaryIdentifier = renderer->getAdapterIdentifier();
889     stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
890                        sizeof(DeviceIdentifier));
891 
892     stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
893 
894     for (int d3dSemantic : mAttribLocationToD3DSemantic)
895     {
896         stream->writeInt(d3dSemantic);
897     }
898 
899     for (gl::ShaderType shaderType : gl::AllShaderTypes())
900     {
901         stream->writeInt(mShaderSamplers[shaderType].size());
902         for (unsigned int i = 0; i < mShaderSamplers[shaderType].size(); ++i)
903         {
904             stream->writeBool(mShaderSamplers[shaderType][i].active);
905             stream->writeInt(mShaderSamplers[shaderType][i].logicalTextureUnit);
906             stream->writeEnum(mShaderSamplers[shaderType][i].textureType);
907         }
908 
909         stream->writeInt(mUsedShaderSamplerRanges[shaderType].low());
910         stream->writeInt(mUsedShaderSamplerRanges[shaderType].high());
911     }
912 
913     for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
914     {
915         stream->writeInt(mImages[shaderType].size());
916         for (size_t imageIndex = 0; imageIndex < mImages[shaderType].size(); ++imageIndex)
917         {
918             stream->writeBool(mImages[shaderType][imageIndex].active);
919             stream->writeInt(mImages[shaderType][imageIndex].logicalImageUnit);
920         }
921 
922         stream->writeInt(mReadonlyImages[shaderType].size());
923         for (size_t imageIndex = 0; imageIndex < mReadonlyImages[shaderType].size(); ++imageIndex)
924         {
925             stream->writeBool(mReadonlyImages[shaderType][imageIndex].active);
926             stream->writeInt(mReadonlyImages[shaderType][imageIndex].logicalImageUnit);
927         }
928 
929         stream->writeInt(mUsedImageRange[shaderType].low());
930         stream->writeInt(mUsedImageRange[shaderType].high());
931         stream->writeInt(mUsedReadonlyImageRange[shaderType].low());
932         stream->writeInt(mUsedReadonlyImageRange[shaderType].high());
933         stream->writeInt(mUsedAtomicCounterRange[shaderType].low());
934         stream->writeInt(mUsedAtomicCounterRange[shaderType].high());
935     }
936 
937     stream->writeInt(mD3DShaderStorageBlocks.size());
938     for (const D3DInterfaceBlock &shaderStorageBlock : mD3DShaderStorageBlocks)
939     {
940         for (gl::ShaderType shaderType : gl::AllShaderTypes())
941         {
942             stream->writeIntOrNegOne(shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
943         }
944     }
945 
946     for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
947     {
948         stream->writeInt(mImage2DUniforms[shaderType].size());
949         for (const sh::ShaderVariable &image2DUniform : mImage2DUniforms[shaderType])
950         {
951             gl::WriteShaderVar(stream, image2DUniform);
952         }
953     }
954 
955     for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS; ++ii)
956     {
957         stream->writeInt(mComputeAtomicCounterBufferRegisterIndices[ii]);
958     }
959 
960     stream->writeInt(mD3DUniforms.size());
961     for (const D3DUniform *uniform : mD3DUniforms)
962     {
963         // Type, name and arraySize are redundant, so aren't stored in the binary.
964         stream->writeEnum(uniform->regType);
965         for (gl::ShaderType shaderType : gl::AllShaderTypes())
966         {
967             stream->writeIntOrNegOne(uniform->mShaderRegisterIndexes[shaderType]);
968         }
969         stream->writeInt(uniform->registerCount);
970         stream->writeInt(uniform->registerElement);
971     }
972 
973     stream->writeInt(mD3DUniformBlocks.size());
974     for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
975     {
976         for (gl::ShaderType shaderType : gl::AllShaderTypes())
977         {
978             stream->writeIntOrNegOne(uniformBlock.mShaderRegisterIndexes[shaderType]);
979             stream->writeBool(uniformBlock.mUseStructuredBuffers[shaderType]);
980             stream->writeInt(uniformBlock.mByteWidths[shaderType]);
981             stream->writeInt(uniformBlock.mStructureByteStrides[shaderType]);
982         }
983     }
984 
985     stream->writeInt(mStreamOutVaryings.size());
986     for (const D3DVarying &varying : mStreamOutVaryings)
987     {
988         stream->writeString(varying.semanticName);
989         stream->writeInt(varying.semanticIndex);
990         stream->writeInt(varying.componentCount);
991         stream->writeInt(varying.outputSlot);
992     }
993 
994     for (gl::ShaderType shaderType : gl::AllShaderTypes())
995     {
996         stream->writeString(mShaderHLSL[shaderType]);
997         stream->writeBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
998                            sizeof(CompilerWorkaroundsD3D));
999     }
1000 
1001     stream->writeEnum(mFragDepthUsage);
1002     stream->writeBool(mUsesSampleMask);
1003     stream->writeBool(mHasMultiviewEnabled);
1004     stream->writeBool(mUsesVertexID);
1005     stream->writeBool(mUsesViewID);
1006     stream->writeBool(mUsesPointSize);
1007     stream->writeBool(mUsesFlatInterpolation);
1008 
1009     const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
1010     stream->writeInt(pixelShaderKey.size());
1011     for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
1012          pixelShaderKeyIndex++)
1013     {
1014         const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
1015         stream->writeInt(variable.type);
1016         stream->writeString(variable.name);
1017         stream->writeString(variable.source);
1018         stream->writeInt(variable.outputLocation);
1019         stream->writeInt(variable.outputIndex);
1020     }
1021 
1022     stream->writeString(mGeometryShaderPreamble);
1023 
1024     stream->writeInt(mVertexExecutables.size());
1025     for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
1026          vertexExecutableIndex++)
1027     {
1028         D3DVertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
1029 
1030         const gl::InputLayout &inputLayout = vertexExecutable->inputs();
1031         stream->writeInt(inputLayout.size());
1032 
1033         for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
1034         {
1035             stream->writeEnum(inputLayout[inputIndex]);
1036         }
1037 
1038         size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1039         stream->writeInt(vertexShaderSize);
1040 
1041         const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
1042         stream->writeBytes(vertexBlob, vertexShaderSize);
1043     }
1044 
1045     stream->writeInt(mPixelExecutables.size());
1046     for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
1047          pixelExecutableIndex++)
1048     {
1049         D3DPixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
1050 
1051         const std::vector<GLenum> &outputs = pixelExecutable->outputSignature();
1052         stream->writeInt(outputs.size());
1053         for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
1054         {
1055             stream->writeInt(outputs[outputIndex]);
1056         }
1057 
1058         const gl::ImageUnitTextureTypeMap &image2Ds = pixelExecutable->image2DSignature();
1059         stream->writeInt(image2Ds.size());
1060         for (const auto &image2D : image2Ds)
1061         {
1062             stream->writeInt(image2D.first);
1063             stream->writeEnum(image2D.second);
1064         }
1065 
1066         size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
1067         stream->writeInt(pixelShaderSize);
1068 
1069         const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
1070         stream->writeBytes(pixelBlob, pixelShaderSize);
1071     }
1072 
1073     for (auto const &geometryExecutable : mGeometryExecutables)
1074     {
1075         if (!geometryExecutable)
1076         {
1077             stream->writeInt<size_t>(0);
1078             continue;
1079         }
1080 
1081         size_t geometryShaderSize = geometryExecutable->getLength();
1082         stream->writeInt(geometryShaderSize);
1083         stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
1084     }
1085 
1086     stream->writeInt(mComputeExecutables.size());
1087     for (size_t computeExecutableIndex = 0; computeExecutableIndex < mComputeExecutables.size();
1088          computeExecutableIndex++)
1089     {
1090         D3DComputeExecutable *computeExecutable = mComputeExecutables[computeExecutableIndex].get();
1091 
1092         const gl::ImageUnitTextureTypeMap signatures = computeExecutable->signature();
1093         stream->writeInt(signatures.size());
1094         for (const auto &signature : signatures)
1095         {
1096             stream->writeInt(signature.first);
1097             stream->writeEnum(signature.second);
1098         }
1099 
1100         size_t computeShaderSize = computeExecutable->shaderExecutable()->getLength();
1101         stream->writeInt(computeShaderSize);
1102 
1103         const uint8_t *computeBlob = computeExecutable->shaderExecutable()->getFunction();
1104         stream->writeBytes(computeBlob, computeShaderSize);
1105     }
1106 
1107     for (const gl::ShaderType shaderType :
1108          {gl::ShaderType::Vertex, gl::ShaderType::Fragment, gl::ShaderType::Compute})
1109     {
1110         stream->writeInt(mImage2DBindLayoutCache[shaderType].size());
1111         for (auto &image2DBindLayout : mImage2DBindLayoutCache[shaderType])
1112         {
1113             stream->writeInt(image2DBindLayout.first);
1114         }
1115     }
1116 }
1117 
hasVertexExecutableForCachedInputLayout()1118 bool ProgramExecutableD3D::hasVertexExecutableForCachedInputLayout()
1119 {
1120     return mCachedVertexExecutableIndex.valid();
1121 }
1122 
hasGeometryExecutableForPrimitiveType(RendererD3D * renderer,const gl::State & state,gl::PrimitiveMode drawMode)1123 bool ProgramExecutableD3D::hasGeometryExecutableForPrimitiveType(RendererD3D *renderer,
1124                                                                  const gl::State &state,
1125                                                                  gl::PrimitiveMode drawMode)
1126 {
1127     if (!usesGeometryShader(renderer, state.getProvokingVertex(), drawMode))
1128     {
1129         // No shader necessary mean we have the required (null) executable.
1130         return true;
1131     }
1132 
1133     gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1134     return mGeometryExecutables[geometryShaderType].get() != nullptr;
1135 }
1136 
hasPixelExecutableForCachedOutputLayout()1137 bool ProgramExecutableD3D::hasPixelExecutableForCachedOutputLayout()
1138 {
1139     return mCachedPixelExecutableIndex.valid();
1140 }
1141 
hasComputeExecutableForCachedImage2DBindLayout()1142 bool ProgramExecutableD3D::hasComputeExecutableForCachedImage2DBindLayout()
1143 {
1144     return mCachedComputeExecutableIndex.valid();
1145 }
1146 
dirtyAllUniforms()1147 void ProgramExecutableD3D::dirtyAllUniforms()
1148 {
1149     mShaderUniformsDirty = mExecutable->getLinkedShaderStages();
1150 }
1151 
markUniformsClean()1152 void ProgramExecutableD3D::markUniformsClean()
1153 {
1154     mShaderUniformsDirty.reset();
1155 }
1156 
getAtomicCounterBufferRegisterIndex(GLuint binding,gl::ShaderType shaderType) const1157 unsigned int ProgramExecutableD3D::getAtomicCounterBufferRegisterIndex(
1158     GLuint binding,
1159     gl::ShaderType shaderType) const
1160 {
1161     if (shaderType != gl::ShaderType::Compute)
1162     {
1163         // Implement atomic counters for non-compute shaders
1164         // http://anglebug.com/42260658
1165         UNIMPLEMENTED();
1166     }
1167     return mComputeAtomicCounterBufferRegisterIndices[binding];
1168 }
1169 
getShaderStorageBufferRegisterIndex(GLuint blockIndex,gl::ShaderType shaderType) const1170 unsigned int ProgramExecutableD3D::getShaderStorageBufferRegisterIndex(
1171     GLuint blockIndex,
1172     gl::ShaderType shaderType) const
1173 {
1174     return mD3DShaderStorageBlocks[blockIndex].mShaderRegisterIndexes[shaderType];
1175 }
1176 
getShaderUniformBufferCache(gl::ShaderType shaderType) const1177 const std::vector<D3DUBOCache> &ProgramExecutableD3D::getShaderUniformBufferCache(
1178     gl::ShaderType shaderType) const
1179 {
1180     return mShaderUBOCaches[shaderType];
1181 }
1182 
getShaderUniformBufferCacheUseSB(gl::ShaderType shaderType) const1183 const std::vector<D3DUBOCacheUseSB> &ProgramExecutableD3D::getShaderUniformBufferCacheUseSB(
1184     gl::ShaderType shaderType) const
1185 {
1186     return mShaderUBOCachesUseSB[shaderType];
1187 }
1188 
getSamplerMapping(gl::ShaderType type,unsigned int samplerIndex,const gl::Caps & caps) const1189 GLint ProgramExecutableD3D::getSamplerMapping(gl::ShaderType type,
1190                                               unsigned int samplerIndex,
1191                                               const gl::Caps &caps) const
1192 {
1193     GLint logicalTextureUnit = -1;
1194 
1195     ASSERT(type != gl::ShaderType::InvalidEnum);
1196 
1197     ASSERT(samplerIndex < static_cast<unsigned int>(caps.maxShaderTextureImageUnits[type]));
1198 
1199     const auto &samplers = mShaderSamplers[type];
1200     if (samplerIndex < samplers.size() && samplers[samplerIndex].active)
1201     {
1202         logicalTextureUnit = samplers[samplerIndex].logicalTextureUnit;
1203     }
1204 
1205     if (logicalTextureUnit >= 0 && logicalTextureUnit < caps.maxCombinedTextureImageUnits)
1206     {
1207         return logicalTextureUnit;
1208     }
1209 
1210     return -1;
1211 }
1212 
1213 // Returns the texture type for a given Direct3D 9 sampler type and
1214 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
getSamplerTextureType(gl::ShaderType type,unsigned int samplerIndex) const1215 gl::TextureType ProgramExecutableD3D::getSamplerTextureType(gl::ShaderType type,
1216                                                             unsigned int samplerIndex) const
1217 {
1218     ASSERT(type != gl::ShaderType::InvalidEnum);
1219 
1220     const auto &samplers = mShaderSamplers[type];
1221     ASSERT(samplerIndex < samplers.size());
1222     ASSERT(samplers[samplerIndex].active);
1223 
1224     return samplers[samplerIndex].textureType;
1225 }
1226 
getUsedSamplerRange(gl::ShaderType type) const1227 gl::RangeUI ProgramExecutableD3D::getUsedSamplerRange(gl::ShaderType type) const
1228 {
1229     ASSERT(type != gl::ShaderType::InvalidEnum);
1230     return mUsedShaderSamplerRanges[type];
1231 }
1232 
updateSamplerMapping()1233 void ProgramExecutableD3D::updateSamplerMapping()
1234 {
1235     ASSERT(mDirtySamplerMapping);
1236 
1237     mDirtySamplerMapping = false;
1238 
1239     // Retrieve sampler uniform values
1240     for (const D3DUniform *d3dUniform : mD3DUniforms)
1241     {
1242         if (!d3dUniform->isSampler())
1243             continue;
1244 
1245         int count = d3dUniform->getArraySizeProduct();
1246 
1247         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1248         {
1249             if (!d3dUniform->isReferencedByShader(shaderType))
1250             {
1251                 continue;
1252             }
1253 
1254             unsigned int firstIndex = d3dUniform->mShaderRegisterIndexes[shaderType];
1255 
1256             std::vector<D3DSampler> &samplers = mShaderSamplers[shaderType];
1257             for (int i = 0; i < count; i++)
1258             {
1259                 unsigned int samplerIndex = firstIndex + i;
1260 
1261                 if (samplerIndex < samplers.size())
1262                 {
1263                     ASSERT(samplers[samplerIndex].active);
1264                     samplers[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
1265                 }
1266             }
1267         }
1268     }
1269 }
1270 
getImageMapping(gl::ShaderType type,unsigned int imageIndex,bool readonly,const gl::Caps & caps) const1271 GLint ProgramExecutableD3D::getImageMapping(gl::ShaderType type,
1272                                             unsigned int imageIndex,
1273                                             bool readonly,
1274                                             const gl::Caps &caps) const
1275 {
1276     GLint logicalImageUnit = -1;
1277     ASSERT(imageIndex < static_cast<unsigned int>(caps.maxImageUnits));
1278     if (readonly && imageIndex < mReadonlyImages[type].size() &&
1279         mReadonlyImages[type][imageIndex].active)
1280     {
1281         logicalImageUnit = mReadonlyImages[type][imageIndex].logicalImageUnit;
1282     }
1283     else if (imageIndex < mImages[type].size() && mImages[type][imageIndex].active)
1284     {
1285         logicalImageUnit = mImages[type][imageIndex].logicalImageUnit;
1286     }
1287 
1288     if (logicalImageUnit >= 0 && logicalImageUnit < caps.maxImageUnits)
1289     {
1290         return logicalImageUnit;
1291     }
1292 
1293     return -1;
1294 }
1295 
getUsedImageRange(gl::ShaderType type,bool readonly) const1296 gl::RangeUI ProgramExecutableD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
1297 {
1298     return readonly ? mUsedReadonlyImageRange[type] : mUsedImageRange[type];
1299 }
1300 
usesPointSpriteEmulation(RendererD3D * renderer) const1301 bool ProgramExecutableD3D::usesPointSpriteEmulation(RendererD3D *renderer) const
1302 {
1303     return mUsesPointSize && renderer->getMajorShaderModel() >= 4;
1304 }
1305 
usesGeometryShaderForPointSpriteEmulation(RendererD3D * renderer) const1306 bool ProgramExecutableD3D::usesGeometryShaderForPointSpriteEmulation(RendererD3D *renderer) const
1307 {
1308     return usesPointSpriteEmulation(renderer);
1309 }
1310 
usesGeometryShader(RendererD3D * renderer,const gl::ProvokingVertexConvention provokingVertex,const gl::PrimitiveMode drawMode) const1311 bool ProgramExecutableD3D::usesGeometryShader(RendererD3D *renderer,
1312                                               const gl::ProvokingVertexConvention provokingVertex,
1313                                               const gl::PrimitiveMode drawMode) const
1314 {
1315     if (mHasMultiviewEnabled && !renderer->canSelectViewInVertexShader())
1316     {
1317         return true;
1318     }
1319     if (drawMode != gl::PrimitiveMode::Points)
1320     {
1321         if (!mUsesFlatInterpolation)
1322         {
1323             return false;
1324         }
1325         return provokingVertex == gl::ProvokingVertexConvention::LastVertexConvention;
1326     }
1327     return usesGeometryShaderForPointSpriteEmulation(renderer);
1328 }
1329 
getVertexExecutableForCachedInputLayout(d3d::Context * context,RendererD3D * renderer,ShaderExecutableD3D ** outExectuable,gl::InfoLog * infoLog)1330 angle::Result ProgramExecutableD3D::getVertexExecutableForCachedInputLayout(
1331     d3d::Context *context,
1332     RendererD3D *renderer,
1333     ShaderExecutableD3D **outExectuable,
1334     gl::InfoLog *infoLog)
1335 {
1336     if (mCachedVertexExecutableIndex.valid())
1337     {
1338         *outExectuable =
1339             mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
1340         return angle::Result::Continue;
1341     }
1342 
1343     // Generate new dynamic layout with attribute conversions
1344     std::string vertexHLSL = DynamicHLSL::GenerateVertexShaderForInputLayout(
1345         renderer, mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout,
1346         mExecutable->getProgramInputs(), mShaderStorageBlocks[gl::ShaderType::Vertex],
1347         mPixelShaderKey.size());
1348     std::string finalVertexHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature(
1349         *this, gl::ShaderType::Vertex, mAttachedShaders[gl::ShaderType::Vertex], vertexHLSL,
1350         mImage2DUniforms[gl::ShaderType::Vertex], mImage2DBindLayoutCache[gl::ShaderType::Vertex],
1351         static_cast<unsigned int>(mPixelShaderKey.size()));
1352 
1353     // Generate new vertex executable
1354     ShaderExecutableD3D *vertexExecutable = nullptr;
1355 
1356     gl::InfoLog tempInfoLog;
1357     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1358 
1359     ANGLE_TRY(renderer->compileToExecutable(
1360         context, *currentInfoLog, finalVertexHLSL, gl::ShaderType::Vertex, mStreamOutVaryings,
1361         mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS,
1362         mShaderWorkarounds[gl::ShaderType::Vertex], &vertexExecutable));
1363 
1364     if (vertexExecutable)
1365     {
1366         mVertexExecutables.push_back(std::unique_ptr<D3DVertexExecutable>(
1367             new D3DVertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
1368         mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
1369     }
1370     else if (!infoLog)
1371     {
1372         ERR() << "Error compiling dynamic vertex executable:" << std::endl
1373               << tempInfoLog.str() << std::endl;
1374     }
1375 
1376     *outExectuable = vertexExecutable;
1377     return angle::Result::Continue;
1378 }
1379 
getGeometryExecutableForPrimitiveType(d3d::Context * context,RendererD3D * renderer,const gl::Caps & caps,gl::ProvokingVertexConvention provokingVertex,gl::PrimitiveMode drawMode,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1380 angle::Result ProgramExecutableD3D::getGeometryExecutableForPrimitiveType(
1381     d3d::Context *context,
1382     RendererD3D *renderer,
1383     const gl::Caps &caps,
1384     gl::ProvokingVertexConvention provokingVertex,
1385     gl::PrimitiveMode drawMode,
1386     ShaderExecutableD3D **outExecutable,
1387     gl::InfoLog *infoLog)
1388 {
1389     if (outExecutable)
1390     {
1391         *outExecutable = nullptr;
1392     }
1393 
1394     // Return a null shader if the current rendering doesn't use a geometry shader
1395     if (!usesGeometryShader(renderer, provokingVertex, drawMode))
1396     {
1397         return angle::Result::Continue;
1398     }
1399 
1400     gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1401 
1402     if (mGeometryExecutables[geometryShaderType])
1403     {
1404         if (outExecutable)
1405         {
1406             *outExecutable = mGeometryExecutables[geometryShaderType].get();
1407         }
1408         return angle::Result::Continue;
1409     }
1410 
1411     std::string geometryHLSL = DynamicHLSL::GenerateGeometryShaderHLSL(
1412         renderer, caps, geometryShaderType, renderer->presentPathFastEnabled(),
1413         mHasMultiviewEnabled, renderer->canSelectViewInVertexShader(),
1414         usesGeometryShaderForPointSpriteEmulation(renderer), mGeometryShaderPreamble);
1415 
1416     gl::InfoLog tempInfoLog;
1417     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1418 
1419     ShaderExecutableD3D *geometryExecutable = nullptr;
1420     angle::Result result                    = renderer->compileToExecutable(
1421         context, *currentInfoLog, geometryHLSL, gl::ShaderType::Geometry, mStreamOutVaryings,
1422         mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS,
1423         CompilerWorkaroundsD3D(), &geometryExecutable);
1424 
1425     if (!infoLog && result == angle::Result::Stop)
1426     {
1427         ERR() << "Error compiling dynamic geometry executable:" << std::endl
1428               << tempInfoLog.str() << std::endl;
1429     }
1430 
1431     if (geometryExecutable != nullptr)
1432     {
1433         mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
1434     }
1435 
1436     if (outExecutable)
1437     {
1438         *outExecutable = mGeometryExecutables[geometryShaderType].get();
1439     }
1440     return result;
1441 }
1442 
getPixelExecutableForCachedOutputLayout(d3d::Context * context,RendererD3D * renderer,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1443 angle::Result ProgramExecutableD3D::getPixelExecutableForCachedOutputLayout(
1444     d3d::Context *context,
1445     RendererD3D *renderer,
1446     ShaderExecutableD3D **outExecutable,
1447     gl::InfoLog *infoLog)
1448 {
1449     if (mCachedPixelExecutableIndex.valid())
1450     {
1451         *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
1452         return angle::Result::Continue;
1453     }
1454 
1455     std::string pixelHLSL = DynamicHLSL::GeneratePixelShaderForOutputSignature(
1456         renderer, mShaderHLSL[gl::ShaderType::Fragment], mPixelShaderKey, mFragDepthUsage,
1457         mUsesSampleMask, mPixelShaderOutputLayoutCache,
1458         mShaderStorageBlocks[gl::ShaderType::Fragment], mPixelShaderKey.size());
1459 
1460     std::string finalPixelHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature(
1461         *this, gl::ShaderType::Fragment, mAttachedShaders[gl::ShaderType::Fragment], pixelHLSL,
1462         mImage2DUniforms[gl::ShaderType::Fragment],
1463         mImage2DBindLayoutCache[gl::ShaderType::Fragment],
1464         static_cast<unsigned int>(mPixelShaderKey.size()));
1465 
1466     // Generate new pixel executable
1467     ShaderExecutableD3D *pixelExecutable = nullptr;
1468 
1469     gl::InfoLog tempInfoLog;
1470     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1471 
1472     ANGLE_TRY(renderer->compileToExecutable(
1473         context, *currentInfoLog, finalPixelHLSL, gl::ShaderType::Fragment, mStreamOutVaryings,
1474         mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS,
1475         mShaderWorkarounds[gl::ShaderType::Fragment], &pixelExecutable));
1476 
1477     if (pixelExecutable)
1478     {
1479         mPixelExecutables.push_back(std::unique_ptr<D3DPixelExecutable>(new D3DPixelExecutable(
1480             mPixelShaderOutputLayoutCache, mImage2DBindLayoutCache[gl::ShaderType::Fragment],
1481             pixelExecutable)));
1482         mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
1483     }
1484     else if (!infoLog)
1485     {
1486         ERR() << "Error compiling dynamic pixel executable:" << std::endl
1487               << tempInfoLog.str() << std::endl;
1488     }
1489 
1490     *outExecutable = pixelExecutable;
1491     return angle::Result::Continue;
1492 }
1493 
getComputeExecutableForImage2DBindLayout(d3d::Context * context,RendererD3D * renderer,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1494 angle::Result ProgramExecutableD3D::getComputeExecutableForImage2DBindLayout(
1495     d3d::Context *context,
1496     RendererD3D *renderer,
1497     ShaderExecutableD3D **outExecutable,
1498     gl::InfoLog *infoLog)
1499 {
1500     ANGLE_TRACE_EVENT0("gpu.angle",
1501                        "ProgramExecutableD3D::getComputeExecutableForImage2DBindLayout");
1502     if (mCachedComputeExecutableIndex.valid())
1503     {
1504         *outExecutable =
1505             mComputeExecutables[mCachedComputeExecutableIndex.value()]->shaderExecutable();
1506         return angle::Result::Continue;
1507     }
1508 
1509     std::string finalComputeHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature(
1510         *this, gl::ShaderType::Compute, mAttachedShaders[gl::ShaderType::Compute],
1511         mShaderHLSL[gl::ShaderType::Compute], mImage2DUniforms[gl::ShaderType::Compute],
1512         mImage2DBindLayoutCache[gl::ShaderType::Compute], 0u);
1513 
1514     // Generate new compute executable
1515     ShaderExecutableD3D *computeExecutable = nullptr;
1516 
1517     gl::InfoLog tempInfoLog;
1518     gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1519 
1520     ANGLE_TRY(renderer->compileToExecutable(context, *currentInfoLog, finalComputeHLSL,
1521                                             gl::ShaderType::Compute, std::vector<D3DVarying>(),
1522                                             false, CompilerWorkaroundsD3D(), &computeExecutable));
1523 
1524     if (computeExecutable)
1525     {
1526         mComputeExecutables.push_back(std::unique_ptr<D3DComputeExecutable>(
1527             new D3DComputeExecutable(mImage2DBindLayoutCache[gl::ShaderType::Compute],
1528                                      std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
1529         mCachedComputeExecutableIndex = mComputeExecutables.size() - 1;
1530     }
1531     else if (!infoLog)
1532     {
1533         ERR() << "Error compiling dynamic compute executable:" << std::endl
1534               << tempInfoLog.str() << std::endl;
1535     }
1536     *outExecutable = computeExecutable;
1537 
1538     return angle::Result::Continue;
1539 }
1540 
hasNamedUniform(const std::string & name)1541 bool ProgramExecutableD3D::hasNamedUniform(const std::string &name)
1542 {
1543     for (D3DUniform *d3dUniform : mD3DUniforms)
1544     {
1545         if (d3dUniform->name == name)
1546         {
1547             return true;
1548         }
1549     }
1550 
1551     return false;
1552 }
1553 
initAttribLocationsToD3DSemantic(const gl::SharedCompiledShaderState & vertexShader)1554 void ProgramExecutableD3D::initAttribLocationsToD3DSemantic(
1555     const gl::SharedCompiledShaderState &vertexShader)
1556 {
1557     if (!vertexShader)
1558     {
1559         return;
1560     }
1561 
1562     // Init semantic index
1563     int semanticIndex = 0;
1564     for (const sh::ShaderVariable &attribute : vertexShader->activeAttributes)
1565     {
1566         int regCount    = gl::VariableRegisterCount(attribute.type);
1567         GLuint location = mExecutable->getAttributeLocation(attribute.name);
1568         ASSERT(location != std::numeric_limits<GLuint>::max());
1569 
1570         for (int reg = 0; reg < regCount; ++reg)
1571         {
1572             mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
1573         }
1574     }
1575 }
1576 
initializeUniformBlocks()1577 void ProgramExecutableD3D::initializeUniformBlocks()
1578 {
1579     if (mExecutable->getUniformBlocks().empty())
1580     {
1581         return;
1582     }
1583 
1584     ASSERT(mD3DUniformBlocks.empty());
1585 
1586     // Assign registers and update sizes.
1587     for (const gl::InterfaceBlock &uniformBlock : mExecutable->getUniformBlocks())
1588     {
1589         unsigned int uniformBlockElement =
1590             uniformBlock.pod.isArray ? uniformBlock.pod.arrayElement : 0;
1591 
1592         D3DUniformBlock d3dUniformBlock;
1593 
1594         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1595         {
1596             if (uniformBlock.isActive(shaderType))
1597             {
1598                 ASSERT(mAttachedShaders[shaderType]);
1599                 unsigned int baseRegister =
1600                     mAttachedShaders[shaderType]->getUniformBlockRegister(uniformBlock.name);
1601                 d3dUniformBlock.mShaderRegisterIndexes[shaderType] =
1602                     baseRegister + uniformBlockElement;
1603                 bool useStructuredBuffer =
1604                     mAttachedShaders[shaderType]->shouldUniformBlockUseStructuredBuffer(
1605                         uniformBlock.name);
1606                 if (useStructuredBuffer)
1607                 {
1608                     d3dUniformBlock.mUseStructuredBuffers[shaderType] = true;
1609                     d3dUniformBlock.mByteWidths[shaderType]           = uniformBlock.pod.dataSize;
1610                     d3dUniformBlock.mStructureByteStrides[shaderType] =
1611                         uniformBlock.pod.firstFieldArraySize == 0u
1612                             ? uniformBlock.pod.dataSize
1613                             : uniformBlock.pod.dataSize / uniformBlock.pod.firstFieldArraySize;
1614                 }
1615             }
1616         }
1617 
1618         mD3DUniformBlocks.push_back(d3dUniformBlock);
1619     }
1620 }
1621 
initializeShaderStorageBlocks(const gl::ShaderMap<gl::SharedCompiledShaderState> & shaders)1622 void ProgramExecutableD3D::initializeShaderStorageBlocks(
1623     const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders)
1624 {
1625     if (mExecutable->getShaderStorageBlocks().empty())
1626     {
1627         return;
1628     }
1629 
1630     ASSERT(mD3DShaderStorageBlocks.empty());
1631 
1632     // Assign registers and update sizes.
1633     for (const gl::InterfaceBlock &shaderStorageBlock : mExecutable->getShaderStorageBlocks())
1634     {
1635         unsigned int shaderStorageBlockElement =
1636             shaderStorageBlock.pod.isArray ? shaderStorageBlock.pod.arrayElement : 0;
1637         D3DInterfaceBlock d3dShaderStorageBlock;
1638 
1639         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1640         {
1641             if (shaderStorageBlock.isActive(shaderType))
1642             {
1643                 ASSERT(mAttachedShaders[shaderType]);
1644                 unsigned int baseRegister =
1645                     mAttachedShaders[shaderType]->getShaderStorageBlockRegister(
1646                         shaderStorageBlock.name);
1647 
1648                 d3dShaderStorageBlock.mShaderRegisterIndexes[shaderType] =
1649                     baseRegister + shaderStorageBlockElement;
1650             }
1651         }
1652         mD3DShaderStorageBlocks.push_back(d3dShaderStorageBlock);
1653     }
1654 
1655     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1656     {
1657         const gl::SharedCompiledShaderState &shader = shaders[shaderType];
1658         if (!shader)
1659         {
1660             continue;
1661         }
1662         for (const sh::InterfaceBlock &ssbo : shader->shaderStorageBlocks)
1663         {
1664             if (!ssbo.active)
1665             {
1666                 continue;
1667             }
1668             ShaderStorageBlock block;
1669             block.name      = !ssbo.instanceName.empty() ? ssbo.instanceName : ssbo.name;
1670             block.arraySize = ssbo.isArray() ? ssbo.arraySize : 0;
1671             block.registerIndex =
1672                 mAttachedShaders[shaderType]->getShaderStorageBlockRegister(ssbo.name);
1673             mShaderStorageBlocks[shaderType].push_back(block);
1674         }
1675     }
1676 }
1677 
initializeUniformStorage(RendererD3D * renderer,const gl::ShaderBitSet & availableShaderStages)1678 void ProgramExecutableD3D::initializeUniformStorage(RendererD3D *renderer,
1679                                                     const gl::ShaderBitSet &availableShaderStages)
1680 {
1681     // Compute total default block size
1682     gl::ShaderMap<unsigned int> shaderRegisters = {};
1683     for (const D3DUniform *d3dUniform : mD3DUniforms)
1684     {
1685         if (d3dUniform->isSampler())
1686         {
1687             continue;
1688         }
1689 
1690         for (gl::ShaderType shaderType : availableShaderStages)
1691         {
1692             if (d3dUniform->isReferencedByShader(shaderType))
1693             {
1694                 shaderRegisters[shaderType] = std::max(
1695                     shaderRegisters[shaderType],
1696                     d3dUniform->mShaderRegisterIndexes[shaderType] + d3dUniform->registerCount);
1697             }
1698         }
1699     }
1700 
1701     // We only reset uniform storages for the shader stages available in the program (attached
1702     // shaders in ProgramExecutableD3D::link() and linkedShaderStages in
1703     // ProgramExecutableD3D::load()).
1704     for (gl::ShaderType shaderType : availableShaderStages)
1705     {
1706         mShaderUniformStorages[shaderType].reset(
1707             renderer->createUniformStorage(shaderRegisters[shaderType] * 16u));
1708     }
1709 
1710     // Iterate the uniforms again to assign data pointers to default block uniforms.
1711     for (D3DUniform *d3dUniform : mD3DUniforms)
1712     {
1713         if (d3dUniform->isSampler())
1714         {
1715             d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
1716             continue;
1717         }
1718 
1719         for (gl::ShaderType shaderType : availableShaderStages)
1720         {
1721             if (d3dUniform->isReferencedByShader(shaderType))
1722             {
1723                 d3dUniform->mShaderData[shaderType] =
1724                     mShaderUniformStorages[shaderType]->getDataPointer(
1725                         d3dUniform->mShaderRegisterIndexes[shaderType],
1726                         d3dUniform->registerElement);
1727             }
1728         }
1729     }
1730 }
1731 
updateCachedInputLayoutFromShader(RendererD3D * renderer,const gl::SharedCompiledShaderState & vertexShader)1732 void ProgramExecutableD3D::updateCachedInputLayoutFromShader(
1733     RendererD3D *renderer,
1734     const gl::SharedCompiledShaderState &vertexShader)
1735 {
1736     GetDefaultInputLayoutFromShader(vertexShader, &mCachedInputLayout);
1737     D3DVertexExecutable::getSignature(renderer, mCachedInputLayout, &mCachedVertexSignature);
1738     updateCachedVertexExecutableIndex();
1739 }
1740 
updateCachedOutputLayoutFromShader()1741 void ProgramExecutableD3D::updateCachedOutputLayoutFromShader()
1742 {
1743     GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
1744     updateCachedPixelExecutableIndex();
1745 }
1746 
updateCachedImage2DBindLayoutFromShader(gl::ShaderType shaderType)1747 void ProgramExecutableD3D::updateCachedImage2DBindLayoutFromShader(gl::ShaderType shaderType)
1748 {
1749     GetDefaultImage2DBindLayoutFromShader(mImage2DUniforms[shaderType],
1750                                           &mImage2DBindLayoutCache[shaderType]);
1751     switch (shaderType)
1752     {
1753         case gl::ShaderType::Compute:
1754             updateCachedComputeExecutableIndex();
1755             break;
1756         case gl::ShaderType::Fragment:
1757             updateCachedPixelExecutableIndex();
1758             break;
1759         case gl::ShaderType::Vertex:
1760             updateCachedVertexExecutableIndex();
1761             break;
1762         default:
1763             ASSERT(false);
1764             break;
1765     }
1766 }
1767 
updateCachedInputLayout(RendererD3D * renderer,UniqueSerial associatedSerial,const gl::State & state)1768 void ProgramExecutableD3D::updateCachedInputLayout(RendererD3D *renderer,
1769                                                    UniqueSerial associatedSerial,
1770                                                    const gl::State &state)
1771 {
1772     if (mCurrentVertexArrayStateSerial == associatedSerial)
1773     {
1774         return;
1775     }
1776 
1777     mCurrentVertexArrayStateSerial = associatedSerial;
1778     mCachedInputLayout.clear();
1779 
1780     const auto &vertexAttributes             = state.getVertexArray()->getVertexAttributes();
1781     const gl::AttributesMask &attributesMask = mExecutable->getActiveAttribLocationsMask();
1782 
1783     for (size_t locationIndex : attributesMask)
1784     {
1785         int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
1786 
1787         if (d3dSemantic != -1)
1788         {
1789             if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
1790             {
1791                 mCachedInputLayout.resize(d3dSemantic + 1, angle::FormatID::NONE);
1792             }
1793             mCachedInputLayout[d3dSemantic] =
1794                 GetVertexFormatID(vertexAttributes[locationIndex],
1795                                   state.getVertexAttribCurrentValue(locationIndex).Type);
1796         }
1797     }
1798 
1799     D3DVertexExecutable::getSignature(renderer, mCachedInputLayout, &mCachedVertexSignature);
1800 
1801     updateCachedVertexExecutableIndex();
1802 }
1803 
updateCachedOutputLayout(const gl::Context * context,const gl::Framebuffer * framebuffer)1804 void ProgramExecutableD3D::updateCachedOutputLayout(const gl::Context *context,
1805                                                     const gl::Framebuffer *framebuffer)
1806 {
1807     mPixelShaderOutputLayoutCache.clear();
1808 
1809     FramebufferD3D *fboD3D   = GetImplAs<FramebufferD3D>(framebuffer);
1810     const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
1811 
1812     for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
1813     {
1814         const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
1815 
1816         if (colorbuffer)
1817         {
1818             auto binding    = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
1819                                                                    : colorbuffer->getBinding();
1820             size_t maxIndex = binding != GL_NONE ? GetMaxOutputIndex(mPixelShaderKey,
1821                                                                      binding - GL_COLOR_ATTACHMENT0)
1822                                                  : 0;
1823             mPixelShaderOutputLayoutCache.insert(mPixelShaderOutputLayoutCache.end(), maxIndex + 1,
1824                                                  binding);
1825         }
1826         else
1827         {
1828             mPixelShaderOutputLayoutCache.push_back(GL_NONE);
1829         }
1830     }
1831 
1832     updateCachedPixelExecutableIndex();
1833 }
1834 
updateCachedImage2DBindLayout(const gl::Context * context,const gl::ShaderType shaderType)1835 void ProgramExecutableD3D::updateCachedImage2DBindLayout(const gl::Context *context,
1836                                                          const gl::ShaderType shaderType)
1837 {
1838     const auto &glState = context->getState();
1839     for (auto &image2DBindLayout : mImage2DBindLayoutCache[shaderType])
1840     {
1841         const gl::ImageUnit &imageUnit = glState.getImageUnit(image2DBindLayout.first);
1842         if (imageUnit.texture.get())
1843         {
1844             image2DBindLayout.second = imageUnit.texture->getType();
1845         }
1846         else
1847         {
1848             image2DBindLayout.second = gl::TextureType::_2D;
1849         }
1850     }
1851 
1852     switch (shaderType)
1853     {
1854         case gl::ShaderType::Vertex:
1855             updateCachedVertexExecutableIndex();
1856             break;
1857         case gl::ShaderType::Fragment:
1858             updateCachedPixelExecutableIndex();
1859             break;
1860         case gl::ShaderType::Compute:
1861             updateCachedComputeExecutableIndex();
1862             break;
1863         default:
1864             ASSERT(false);
1865             break;
1866     }
1867 }
1868 
updateCachedVertexExecutableIndex()1869 void ProgramExecutableD3D::updateCachedVertexExecutableIndex()
1870 {
1871     mCachedVertexExecutableIndex.reset();
1872     for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
1873     {
1874         if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
1875         {
1876             mCachedVertexExecutableIndex = executableIndex;
1877             break;
1878         }
1879     }
1880 }
1881 
updateCachedPixelExecutableIndex()1882 void ProgramExecutableD3D::updateCachedPixelExecutableIndex()
1883 {
1884     mCachedPixelExecutableIndex.reset();
1885     for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
1886     {
1887         if (mPixelExecutables[executableIndex]->matchesSignature(
1888                 mPixelShaderOutputLayoutCache, mImage2DBindLayoutCache[gl::ShaderType::Fragment]))
1889         {
1890             mCachedPixelExecutableIndex = executableIndex;
1891             break;
1892         }
1893     }
1894 }
1895 
updateCachedComputeExecutableIndex()1896 void ProgramExecutableD3D::updateCachedComputeExecutableIndex()
1897 {
1898     mCachedComputeExecutableIndex.reset();
1899     for (size_t executableIndex = 0; executableIndex < mComputeExecutables.size();
1900          executableIndex++)
1901     {
1902         if (mComputeExecutables[executableIndex]->matchesSignature(
1903                 mImage2DBindLayoutCache[gl::ShaderType::Compute]))
1904         {
1905             mCachedComputeExecutableIndex = executableIndex;
1906             break;
1907         }
1908     }
1909 }
1910 
updateUniformBufferCache(const gl::Caps & caps)1911 void ProgramExecutableD3D::updateUniformBufferCache(const gl::Caps &caps)
1912 {
1913     if (mExecutable->getUniformBlocks().empty())
1914     {
1915         return;
1916     }
1917 
1918     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1919     {
1920         mShaderUBOCaches[shaderType].clear();
1921         mShaderUBOCachesUseSB[shaderType].clear();
1922     }
1923 
1924     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
1925          uniformBlockIndex++)
1926     {
1927         const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
1928         GLuint blockBinding = mExecutable->getUniformBlockBinding(uniformBlockIndex);
1929 
1930         // Unnecessary to apply an unreferenced standard or shared UBO
1931         for (gl::ShaderType shaderType : gl::AllShaderTypes())
1932         {
1933             if (!uniformBlock.activeInShader(shaderType))
1934             {
1935                 continue;
1936             }
1937 
1938             bool useStructuredBuffer   = uniformBlock.mUseStructuredBuffers[shaderType];
1939             unsigned int registerIndex = uniformBlock.mShaderRegisterIndexes[shaderType];
1940             if (useStructuredBuffer)
1941             {
1942                 D3DUBOCacheUseSB cacheUseSB;
1943                 cacheUseSB.registerIndex       = registerIndex;
1944                 cacheUseSB.binding             = blockBinding;
1945                 cacheUseSB.byteWidth           = uniformBlock.mByteWidths[shaderType];
1946                 cacheUseSB.structureByteStride = uniformBlock.mStructureByteStrides[shaderType];
1947                 mShaderUBOCachesUseSB[shaderType].push_back(cacheUseSB);
1948             }
1949             else
1950             {
1951                 ASSERT(registerIndex <
1952                        static_cast<unsigned int>(caps.maxShaderUniformBlocks[shaderType]));
1953                 D3DUBOCache cache;
1954                 cache.registerIndex = registerIndex;
1955                 cache.binding       = blockBinding;
1956                 mShaderUBOCaches[shaderType].push_back(cache);
1957             }
1958         }
1959     }
1960 
1961     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1962     {
1963         GLuint uniformBlockCount = static_cast<GLuint>(mShaderUBOCaches[shaderType].size() +
1964                                                        mShaderUBOCachesUseSB[shaderType].size());
1965         ASSERT(uniformBlockCount <=
1966                static_cast<unsigned int>(caps.maxShaderUniformBlocks[shaderType]));
1967     }
1968 }
1969 
defineUniformsAndAssignRegisters(RendererD3D * renderer,const gl::ShaderMap<gl::SharedCompiledShaderState> & shaders)1970 void ProgramExecutableD3D::defineUniformsAndAssignRegisters(
1971     RendererD3D *renderer,
1972     const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders)
1973 {
1974     D3DUniformMap uniformMap;
1975 
1976     gl::ShaderBitSet attachedShaders;
1977     for (gl::ShaderType shaderType : gl::AllShaderTypes())
1978     {
1979         const gl::SharedCompiledShaderState &shader = shaders[shaderType];
1980         if (shader)
1981         {
1982             for (const sh::ShaderVariable &uniform : shader->uniforms)
1983             {
1984                 if (uniform.active)
1985                 {
1986                     defineUniformBase(shader->shaderType, uniform, &uniformMap);
1987                 }
1988             }
1989 
1990             attachedShaders.set(shader->shaderType);
1991         }
1992     }
1993 
1994     // Initialize the D3DUniform list to mirror the indexing of the GL layer.
1995     for (GLuint index = 0; index < static_cast<GLuint>(mExecutable->getUniforms().size()); index++)
1996     {
1997         const gl::LinkedUniform &glUniform = mExecutable->getUniforms()[index];
1998         if (!glUniform.isInDefaultBlock())
1999             continue;
2000 
2001         std::string name = mExecutable->getUniformNames()[index];
2002         if (glUniform.isArray())
2003         {
2004             // In the program state, array uniform names include [0] as in the program resource
2005             // spec. Here we don't include it.
2006             // TODO([email protected]): consider using the same uniform naming here as in the GL
2007             // layer.
2008             ASSERT(angle::EndsWith(name, "[0]"));
2009             name.resize(name.length() - 3);
2010         }
2011         auto mapEntry = uniformMap.find(name);
2012         ASSERT(mapEntry != uniformMap.end());
2013         mD3DUniforms.push_back(mapEntry->second);
2014     }
2015 
2016     assignAllSamplerRegisters(shaders);
2017     assignAllAtomicCounterRegisters();
2018     // Samplers and readonly images share shader input resource slot, adjust low value of
2019     // readonly image range.
2020     for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
2021     {
2022         mUsedReadonlyImageRange[shaderType] =
2023             gl::RangeUI(mUsedShaderSamplerRanges[shaderType].high(),
2024                         mUsedShaderSamplerRanges[shaderType].high());
2025         // Atomic counter buffers and non-readonly images share input resource slots
2026         mUsedImageRange[shaderType] = gl::RangeUI(mUsedAtomicCounterRange[shaderType].high(),
2027                                                   mUsedAtomicCounterRange[shaderType].high());
2028     }
2029     assignAllImageRegisters();
2030     initializeUniformStorage(renderer, attachedShaders);
2031 }
2032 
defineUniformBase(gl::ShaderType shaderType,const sh::ShaderVariable & uniform,D3DUniformMap * uniformMap)2033 void ProgramExecutableD3D::defineUniformBase(gl::ShaderType shaderType,
2034                                              const sh::ShaderVariable &uniform,
2035                                              D3DUniformMap *uniformMap)
2036 {
2037     sh::StubBlockEncoder stubEncoder;
2038 
2039     // Samplers get their registers assigned in assignAllSamplerRegisters, and images get their
2040     // registers assigned in assignAllImageRegisters.
2041     if (gl::IsSamplerType(uniform.type))
2042     {
2043         UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::Texture, &stubEncoder,
2044                                           uniformMap);
2045         sh::TraverseShaderVariable(uniform, false, &visitor);
2046         return;
2047     }
2048 
2049     if (gl::IsImageType(uniform.type))
2050     {
2051         if (uniform.readonly)
2052         {
2053             UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::Texture, &stubEncoder,
2054                                               uniformMap);
2055             sh::TraverseShaderVariable(uniform, false, &visitor);
2056         }
2057         else
2058         {
2059             UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::UnorderedAccessView,
2060                                               &stubEncoder, uniformMap);
2061             sh::TraverseShaderVariable(uniform, false, &visitor);
2062         }
2063         mImageBindingMap[uniform.name] = uniform.binding;
2064         return;
2065     }
2066 
2067     if (uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn())
2068     {
2069         UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::None, &stubEncoder,
2070                                           uniformMap);
2071         sh::TraverseShaderVariable(uniform, false, &visitor);
2072         return;
2073     }
2074     else if (gl::IsAtomicCounterType(uniform.type))
2075     {
2076         UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::UnorderedAccessView,
2077                                           &stubEncoder, uniformMap);
2078         sh::TraverseShaderVariable(uniform, false, &visitor);
2079         mAtomicBindingMap[uniform.name] = uniform.binding;
2080         return;
2081     }
2082 
2083     const SharedCompiledShaderStateD3D &shaderD3D = mAttachedShaders[shaderType];
2084     unsigned int startRegister                    = shaderD3D->getUniformRegister(uniform.name);
2085     ShShaderOutput outputType                     = shaderD3D->compilerOutputType;
2086     sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
2087     encoder.skipRegisters(startRegister);
2088 
2089     UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::None, &encoder, uniformMap);
2090     sh::TraverseShaderVariable(uniform, false, &visitor);
2091 }
2092 
assignAllSamplerRegisters(const gl::ShaderMap<gl::SharedCompiledShaderState> & shaders)2093 void ProgramExecutableD3D::assignAllSamplerRegisters(
2094     const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders)
2095 {
2096     for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2097     {
2098         if (mD3DUniforms[uniformIndex]->isSampler())
2099         {
2100             assignSamplerRegisters(shaders, uniformIndex);
2101         }
2102     }
2103 }
2104 
assignSamplerRegisters(const gl::ShaderMap<gl::SharedCompiledShaderState> & shaders,size_t uniformIndex)2105 void ProgramExecutableD3D::assignSamplerRegisters(
2106     const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders,
2107     size_t uniformIndex)
2108 {
2109     D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2110     ASSERT(d3dUniform->isSampler());
2111     // If the uniform is an array of arrays, then we have separate entries for each inner array in
2112     // mD3DUniforms. However, the sampler register info is stored in the shader only for the
2113     // outermost array.
2114     std::vector<unsigned int> subscripts;
2115     const std::string baseName  = gl::ParseResourceName(d3dUniform->name, &subscripts);
2116     unsigned int registerOffset = mExecutable->getUniforms()[uniformIndex].pod.parentArrayIndex *
2117                                   d3dUniform->getArraySizeProduct();
2118 
2119     bool hasUniform = false;
2120     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2121     {
2122         if (!shaders[shaderType])
2123         {
2124             continue;
2125         }
2126 
2127         const SharedCompiledShaderStateD3D &shaderD3D = mAttachedShaders[shaderType];
2128         if (shaderD3D->hasUniform(baseName))
2129         {
2130             d3dUniform->mShaderRegisterIndexes[shaderType] =
2131                 shaderD3D->getUniformRegister(baseName) + registerOffset;
2132             ASSERT(d3dUniform->mShaderRegisterIndexes[shaderType] != GL_INVALID_VALUE);
2133 
2134             AssignSamplers(d3dUniform->mShaderRegisterIndexes[shaderType], d3dUniform->typeInfo,
2135                            d3dUniform->getArraySizeProduct(), mShaderSamplers[shaderType],
2136                            &mUsedShaderSamplerRanges[shaderType]);
2137             hasUniform = true;
2138         }
2139     }
2140 
2141     ASSERT(hasUniform);
2142 }
2143 
2144 // static
AssignSamplers(unsigned int startSamplerIndex,const gl::UniformTypeInfo & typeInfo,unsigned int samplerCount,std::vector<D3DSampler> & outSamplers,gl::RangeUI * outUsedRange)2145 void ProgramExecutableD3D::AssignSamplers(unsigned int startSamplerIndex,
2146                                           const gl::UniformTypeInfo &typeInfo,
2147                                           unsigned int samplerCount,
2148                                           std::vector<D3DSampler> &outSamplers,
2149                                           gl::RangeUI *outUsedRange)
2150 {
2151     unsigned int samplerIndex = startSamplerIndex;
2152 
2153     do
2154     {
2155         ASSERT(samplerIndex < outSamplers.size());
2156         D3DSampler *sampler         = &outSamplers[samplerIndex];
2157         sampler->active             = true;
2158         sampler->textureType        = gl::FromGLenum<gl::TextureType>(typeInfo.textureType);
2159         sampler->logicalTextureUnit = 0;
2160         outUsedRange->extend(samplerIndex);
2161         samplerIndex++;
2162     } while (samplerIndex < startSamplerIndex + samplerCount);
2163 }
2164 
assignAllImageRegisters()2165 void ProgramExecutableD3D::assignAllImageRegisters()
2166 {
2167     for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2168     {
2169         if (mD3DUniforms[uniformIndex]->isImage() && !mD3DUniforms[uniformIndex]->isImage2D())
2170         {
2171             assignImageRegisters(uniformIndex);
2172         }
2173     }
2174 }
2175 
assignAllAtomicCounterRegisters()2176 void ProgramExecutableD3D::assignAllAtomicCounterRegisters()
2177 {
2178     if (mAtomicBindingMap.empty())
2179     {
2180         return;
2181     }
2182     const SharedCompiledShaderStateD3D &computeShader = mAttachedShaders[gl::ShaderType::Compute];
2183     if (computeShader)
2184     {
2185         auto &registerIndices = mComputeAtomicCounterBufferRegisterIndices;
2186         for (auto &atomicBinding : mAtomicBindingMap)
2187         {
2188             ASSERT(computeShader->hasUniform(atomicBinding.first));
2189             unsigned int currentRegister = computeShader->getUniformRegister(atomicBinding.first);
2190             ASSERT(currentRegister != GL_INVALID_INDEX);
2191             const int kBinding = atomicBinding.second;
2192 
2193             registerIndices[kBinding] = currentRegister;
2194 
2195             mUsedAtomicCounterRange[gl::ShaderType::Compute].extend(currentRegister);
2196         }
2197     }
2198     else
2199     {
2200         // Implement atomic counters for non-compute shaders
2201         // http://anglebug.com/42260658
2202         UNIMPLEMENTED();
2203     }
2204 }
2205 
assignImageRegisters(size_t uniformIndex)2206 void ProgramExecutableD3D::assignImageRegisters(size_t uniformIndex)
2207 {
2208     D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2209     ASSERT(d3dUniform->isImage());
2210     // If the uniform is an array of arrays, then we have separate entries for each inner array in
2211     // mD3DUniforms. However, the image register info is stored in the shader only for the
2212     // outermost array.
2213     std::vector<unsigned int> subscripts;
2214     const std::string baseName  = gl::ParseResourceName(d3dUniform->name, &subscripts);
2215     unsigned int registerOffset = mExecutable->getUniforms()[uniformIndex].pod.parentArrayIndex *
2216                                   d3dUniform->getArraySizeProduct();
2217 
2218     const SharedCompiledShaderStateD3D &computeShader = mAttachedShaders[gl::ShaderType::Compute];
2219     if (computeShader)
2220     {
2221         ASSERT(computeShader->hasUniform(baseName));
2222         d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] =
2223             computeShader->getUniformRegister(baseName) + registerOffset;
2224         ASSERT(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] != GL_INVALID_INDEX);
2225         auto bindingIter = mImageBindingMap.find(baseName);
2226         ASSERT(bindingIter != mImageBindingMap.end());
2227         if (d3dUniform->regType == HLSLRegisterType::Texture)
2228         {
2229             AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2230                          bindingIter->second, d3dUniform->getArraySizeProduct(),
2231                          mReadonlyImages[gl::ShaderType::Compute],
2232                          &mUsedReadonlyImageRange[gl::ShaderType::Compute]);
2233         }
2234         else if (d3dUniform->regType == HLSLRegisterType::UnorderedAccessView)
2235         {
2236             AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2237                          bindingIter->second, d3dUniform->getArraySizeProduct(),
2238                          mImages[gl::ShaderType::Compute],
2239                          &mUsedImageRange[gl::ShaderType::Compute]);
2240         }
2241         else
2242         {
2243             UNREACHABLE();
2244         }
2245     }
2246     else
2247     {
2248         // TODO([email protected]): Implement image variables in vertex shader and pixel shader.
2249         UNIMPLEMENTED();
2250     }
2251 }
2252 
2253 // static
AssignImages(unsigned int startImageIndex,int startLogicalImageUnit,unsigned int imageCount,std::vector<D3DImage> & outImages,gl::RangeUI * outUsedRange)2254 void ProgramExecutableD3D::AssignImages(unsigned int startImageIndex,
2255                                         int startLogicalImageUnit,
2256                                         unsigned int imageCount,
2257                                         std::vector<D3DImage> &outImages,
2258                                         gl::RangeUI *outUsedRange)
2259 {
2260     unsigned int imageIndex = startImageIndex;
2261 
2262     // If declare without a binding qualifier, any uniform image variable (include all elements of
2263     // unbound image array) shoud be bound to unit zero.
2264     if (startLogicalImageUnit == -1)
2265     {
2266         ASSERT(imageIndex < outImages.size());
2267         D3DImage *image         = &outImages[imageIndex];
2268         image->active           = true;
2269         image->logicalImageUnit = 0;
2270         outUsedRange->extend(imageIndex);
2271         return;
2272     }
2273 
2274     unsigned int logcalImageUnit = startLogicalImageUnit;
2275     do
2276     {
2277         ASSERT(imageIndex < outImages.size());
2278         D3DImage *image         = &outImages[imageIndex];
2279         image->active           = true;
2280         image->logicalImageUnit = logcalImageUnit;
2281         outUsedRange->extend(imageIndex);
2282         imageIndex++;
2283         logcalImageUnit++;
2284     } while (imageIndex < startImageIndex + imageCount);
2285 }
2286 
assignImage2DRegisters(gl::ShaderType shaderType,unsigned int startImageIndex,int startLogicalImageUnit,bool readonly)2287 void ProgramExecutableD3D::assignImage2DRegisters(gl::ShaderType shaderType,
2288                                                   unsigned int startImageIndex,
2289                                                   int startLogicalImageUnit,
2290                                                   bool readonly)
2291 {
2292     if (readonly)
2293     {
2294         AssignImages(startImageIndex, startLogicalImageUnit, 1, mReadonlyImages[shaderType],
2295                      &mUsedReadonlyImageRange[shaderType]);
2296     }
2297     else
2298     {
2299         AssignImages(startImageIndex, startLogicalImageUnit, 1, mImages[shaderType],
2300                      &mUsedImageRange[shaderType]);
2301     }
2302 }
2303 
gatherTransformFeedbackVaryings(RendererD3D * renderer,const gl::VaryingPacking & varyingPacking,const std::vector<std::string> & tfVaryingNames,const BuiltinInfo & builtins)2304 void ProgramExecutableD3D::gatherTransformFeedbackVaryings(
2305     RendererD3D *renderer,
2306     const gl::VaryingPacking &varyingPacking,
2307     const std::vector<std::string> &tfVaryingNames,
2308     const BuiltinInfo &builtins)
2309 {
2310     const std::string &varyingSemantic =
2311         GetVaryingSemantic(renderer->getMajorShaderModel(), usesPointSize());
2312 
2313     // Gather the linked varyings that are used for transform feedback, they should all exist.
2314     mStreamOutVaryings.clear();
2315 
2316     for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
2317          ++outputSlot)
2318     {
2319         const auto &tfVaryingName = tfVaryingNames[outputSlot];
2320         if (tfVaryingName == "gl_Position")
2321         {
2322             if (builtins.glPosition.enabled)
2323             {
2324                 mStreamOutVaryings.emplace_back(builtins.glPosition.semantic,
2325                                                 builtins.glPosition.indexOrSize, 4, outputSlot);
2326             }
2327         }
2328         else if (tfVaryingName == "gl_FragCoord")
2329         {
2330             if (builtins.glFragCoord.enabled)
2331             {
2332                 mStreamOutVaryings.emplace_back(builtins.glFragCoord.semantic,
2333                                                 builtins.glFragCoord.indexOrSize, 4, outputSlot);
2334             }
2335         }
2336         else if (tfVaryingName == "gl_PointSize")
2337         {
2338             if (builtins.glPointSize.enabled)
2339             {
2340                 mStreamOutVaryings.emplace_back("PSIZE", 0, 1, outputSlot);
2341             }
2342         }
2343         else
2344         {
2345             const auto &registerInfos = varyingPacking.getRegisterList();
2346             for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
2347             {
2348                 const auto &registerInfo = registerInfos[registerIndex];
2349                 const auto &varying      = registerInfo.packedVarying->varying();
2350                 GLenum transposedType    = gl::TransposeMatrixType(varying.type);
2351                 int componentCount       = gl::VariableColumnCount(transposedType);
2352                 ASSERT(!varying.isBuiltIn() && !varying.isStruct());
2353 
2354                 // There can be more than one register assigned to a particular varying, and each
2355                 // register needs its own stream out entry.
2356                 if (registerInfo.tfVaryingName() == tfVaryingName)
2357                 {
2358                     mStreamOutVaryings.emplace_back(varyingSemantic, registerIndex, componentCount,
2359                                                     outputSlot);
2360                 }
2361             }
2362         }
2363     }
2364 }
2365 
getD3DUniformFromLocation(const gl::VariableLocation & locationInfo)2366 D3DUniform *ProgramExecutableD3D::getD3DUniformFromLocation(
2367     const gl::VariableLocation &locationInfo)
2368 {
2369     return mD3DUniforms[locationInfo.index];
2370 }
2371 
getD3DUniformFromLocation(const gl::VariableLocation & locationInfo) const2372 const D3DUniform *ProgramExecutableD3D::getD3DUniformFromLocation(
2373     const gl::VariableLocation &locationInfo) const
2374 {
2375     return mD3DUniforms[locationInfo.index];
2376 }
2377 
issueSerial()2378 unsigned int ProgramExecutableD3D::issueSerial()
2379 {
2380     return mCurrentSerial++;
2381 }
2382 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)2383 void ProgramExecutableD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
2384 {
2385     setUniformInternal(location, count, v, GL_FLOAT);
2386 }
2387 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)2388 void ProgramExecutableD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2389 {
2390     setUniformInternal(location, count, v, GL_FLOAT_VEC2);
2391 }
2392 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)2393 void ProgramExecutableD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2394 {
2395     setUniformInternal(location, count, v, GL_FLOAT_VEC3);
2396 }
2397 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)2398 void ProgramExecutableD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2399 {
2400     setUniformInternal(location, count, v, GL_FLOAT_VEC4);
2401 }
2402 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2403 void ProgramExecutableD3D::setUniformMatrix2fv(GLint location,
2404                                                GLsizei count,
2405                                                GLboolean transpose,
2406                                                const GLfloat *value)
2407 {
2408     setUniformMatrixfvInternal<2, 2>(location, count, transpose, value);
2409 }
2410 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2411 void ProgramExecutableD3D::setUniformMatrix3fv(GLint location,
2412                                                GLsizei count,
2413                                                GLboolean transpose,
2414                                                const GLfloat *value)
2415 {
2416     setUniformMatrixfvInternal<3, 3>(location, count, transpose, value);
2417 }
2418 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2419 void ProgramExecutableD3D::setUniformMatrix4fv(GLint location,
2420                                                GLsizei count,
2421                                                GLboolean transpose,
2422                                                const GLfloat *value)
2423 {
2424     setUniformMatrixfvInternal<4, 4>(location, count, transpose, value);
2425 }
2426 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2427 void ProgramExecutableD3D::setUniformMatrix2x3fv(GLint location,
2428                                                  GLsizei count,
2429                                                  GLboolean transpose,
2430                                                  const GLfloat *value)
2431 {
2432     setUniformMatrixfvInternal<2, 3>(location, count, transpose, value);
2433 }
2434 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2435 void ProgramExecutableD3D::setUniformMatrix3x2fv(GLint location,
2436                                                  GLsizei count,
2437                                                  GLboolean transpose,
2438                                                  const GLfloat *value)
2439 {
2440     setUniformMatrixfvInternal<3, 2>(location, count, transpose, value);
2441 }
2442 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2443 void ProgramExecutableD3D::setUniformMatrix2x4fv(GLint location,
2444                                                  GLsizei count,
2445                                                  GLboolean transpose,
2446                                                  const GLfloat *value)
2447 {
2448     setUniformMatrixfvInternal<2, 4>(location, count, transpose, value);
2449 }
2450 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2451 void ProgramExecutableD3D::setUniformMatrix4x2fv(GLint location,
2452                                                  GLsizei count,
2453                                                  GLboolean transpose,
2454                                                  const GLfloat *value)
2455 {
2456     setUniformMatrixfvInternal<4, 2>(location, count, transpose, value);
2457 }
2458 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2459 void ProgramExecutableD3D::setUniformMatrix3x4fv(GLint location,
2460                                                  GLsizei count,
2461                                                  GLboolean transpose,
2462                                                  const GLfloat *value)
2463 {
2464     setUniformMatrixfvInternal<3, 4>(location, count, transpose, value);
2465 }
2466 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2467 void ProgramExecutableD3D::setUniformMatrix4x3fv(GLint location,
2468                                                  GLsizei count,
2469                                                  GLboolean transpose,
2470                                                  const GLfloat *value)
2471 {
2472     setUniformMatrixfvInternal<4, 3>(location, count, transpose, value);
2473 }
2474 
setUniform1iv(GLint location,GLsizei count,const GLint * v)2475 void ProgramExecutableD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
2476 {
2477     setUniformInternal(location, count, v, GL_INT);
2478 }
2479 
setUniform2iv(GLint location,GLsizei count,const GLint * v)2480 void ProgramExecutableD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
2481 {
2482     setUniformInternal(location, count, v, GL_INT_VEC2);
2483 }
2484 
setUniform3iv(GLint location,GLsizei count,const GLint * v)2485 void ProgramExecutableD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
2486 {
2487     setUniformInternal(location, count, v, GL_INT_VEC3);
2488 }
2489 
setUniform4iv(GLint location,GLsizei count,const GLint * v)2490 void ProgramExecutableD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
2491 {
2492     setUniformInternal(location, count, v, GL_INT_VEC4);
2493 }
2494 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)2495 void ProgramExecutableD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
2496 {
2497     setUniformInternal(location, count, v, GL_UNSIGNED_INT);
2498 }
2499 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)2500 void ProgramExecutableD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
2501 {
2502     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
2503 }
2504 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)2505 void ProgramExecutableD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2506 {
2507     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
2508 }
2509 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)2510 void ProgramExecutableD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2511 {
2512     setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
2513 }
2514 
2515 // Assume count is already clamped.
2516 template <typename T>
setUniformImpl(D3DUniform * targetUniform,const gl::VariableLocation & locationInfo,GLsizei count,const T * v,uint8_t * targetState,GLenum uniformType)2517 void ProgramExecutableD3D::setUniformImpl(D3DUniform *targetUniform,
2518                                           const gl::VariableLocation &locationInfo,
2519                                           GLsizei count,
2520                                           const T *v,
2521                                           uint8_t *targetState,
2522                                           GLenum uniformType)
2523 {
2524     const int components                  = targetUniform->typeInfo.componentCount;
2525     const unsigned int arrayElementOffset = locationInfo.arrayIndex;
2526     const int blockSize                   = 4;
2527 
2528     if (targetUniform->typeInfo.type == uniformType)
2529     {
2530         T *dest         = reinterpret_cast<T *>(targetState) + arrayElementOffset * blockSize;
2531         const T *source = v;
2532 
2533         // If the component is equal to the block size, we can optimize to a single memcpy.
2534         // Otherwise, we have to do partial block writes.
2535         if (components == blockSize)
2536         {
2537             memcpy(dest, source, components * count * sizeof(T));
2538         }
2539         else
2540         {
2541             for (GLint i = 0; i < count; i++, dest += blockSize, source += components)
2542             {
2543                 memcpy(dest, source, components * sizeof(T));
2544             }
2545         }
2546     }
2547     else
2548     {
2549         ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
2550         GLint *boolParams = reinterpret_cast<GLint *>(targetState) + arrayElementOffset * 4;
2551 
2552         for (GLint i = 0; i < count; i++)
2553         {
2554             GLint *dest     = boolParams + (i * 4);
2555             const T *source = v + (i * components);
2556 
2557             for (int c = 0; c < components; c++)
2558             {
2559                 dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
2560             }
2561         }
2562     }
2563 }
2564 
2565 template <typename T>
setUniformInternal(GLint location,GLsizei count,const T * v,GLenum uniformType)2566 void ProgramExecutableD3D::setUniformInternal(GLint location,
2567                                               GLsizei count,
2568                                               const T *v,
2569                                               GLenum uniformType)
2570 {
2571     const gl::VariableLocation &locationInfo = mExecutable->getUniformLocations()[location];
2572     D3DUniform *targetUniform                = mD3DUniforms[locationInfo.index];
2573 
2574     if (targetUniform->typeInfo.isSampler)
2575     {
2576         ASSERT(uniformType == GL_INT);
2577         size_t size = count * sizeof(T);
2578         GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
2579         if (memcmp(dest, v, size) != 0)
2580         {
2581             memcpy(dest, v, size);
2582             mDirtySamplerMapping = true;
2583         }
2584         return;
2585     }
2586 
2587     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2588     {
2589         uint8_t *targetState = targetUniform->mShaderData[shaderType];
2590         if (targetState)
2591         {
2592             setUniformImpl(targetUniform, locationInfo, count, v, targetState, uniformType);
2593             mShaderUniformsDirty.set(shaderType);
2594         }
2595     }
2596 }
2597 
2598 template <int cols, int rows>
setUniformMatrixfvInternal(GLint location,GLsizei countIn,GLboolean transpose,const GLfloat * value)2599 void ProgramExecutableD3D::setUniformMatrixfvInternal(GLint location,
2600                                                       GLsizei countIn,
2601                                                       GLboolean transpose,
2602                                                       const GLfloat *value)
2603 {
2604     const gl::VariableLocation &uniformLocation = mExecutable->getUniformLocations()[location];
2605     D3DUniform *targetUniform                   = getD3DUniformFromLocation(uniformLocation);
2606     unsigned int arrayElementOffset             = uniformLocation.arrayIndex;
2607     unsigned int elementCount                   = targetUniform->getArraySizeProduct();
2608 
2609     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2610     {
2611         if (targetUniform->mShaderData[shaderType])
2612         {
2613             SetFloatUniformMatrixHLSL<cols, rows>::Run(arrayElementOffset, elementCount, countIn,
2614                                                        transpose, value,
2615                                                        targetUniform->mShaderData[shaderType]);
2616             mShaderUniformsDirty.set(shaderType);
2617         }
2618     }
2619 }
2620 
2621 template <typename DestT>
getUniformInternal(GLint location,DestT * dataOut) const2622 void ProgramExecutableD3D::getUniformInternal(GLint location, DestT *dataOut) const
2623 {
2624     const gl::VariableLocation &locationInfo = mExecutable->getUniformLocations()[location];
2625     const gl::LinkedUniform &uniform         = mExecutable->getUniforms()[locationInfo.index];
2626 
2627     const D3DUniform *targetUniform = getD3DUniformFromLocation(locationInfo);
2628     const uint8_t *srcPointer       = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
2629 
2630     if (gl::IsMatrixType(uniform.getType()))
2631     {
2632         GetMatrixUniform(uniform.getType(), dataOut, reinterpret_cast<const DestT *>(srcPointer),
2633                          true);
2634     }
2635     else
2636     {
2637         memcpy(dataOut, srcPointer, uniform.getElementSize());
2638     }
2639 }
2640 
getUniformfv(const gl::Context * context,GLint location,GLfloat * params) const2641 void ProgramExecutableD3D::getUniformfv(const gl::Context *context,
2642                                         GLint location,
2643                                         GLfloat *params) const
2644 {
2645     getUniformInternal(location, params);
2646 }
2647 
getUniformiv(const gl::Context * context,GLint location,GLint * params) const2648 void ProgramExecutableD3D::getUniformiv(const gl::Context *context,
2649                                         GLint location,
2650                                         GLint *params) const
2651 {
2652     getUniformInternal(location, params);
2653 }
2654 
getUniformuiv(const gl::Context * context,GLint location,GLuint * params) const2655 void ProgramExecutableD3D::getUniformuiv(const gl::Context *context,
2656                                          GLint location,
2657                                          GLuint *params) const
2658 {
2659     getUniformInternal(location, params);
2660 }
2661 
2662 }  // namespace rx
2663