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