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