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