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