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