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/1729
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) && !usesInstancedPointSpriteEmulation(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
usesInstancedPointSpriteEmulation(RendererD3D * renderer) const1330 bool ProgramExecutableD3D::usesInstancedPointSpriteEmulation(RendererD3D *renderer) const
1331 {
1332 return renderer->getFeatures().useInstancedPointSpriteEmulation.enabled;
1333 }
1334
getVertexExecutableForCachedInputLayout(d3d::Context * context,RendererD3D * renderer,ShaderExecutableD3D ** outExectuable,gl::InfoLog * infoLog)1335 angle::Result ProgramExecutableD3D::getVertexExecutableForCachedInputLayout(
1336 d3d::Context *context,
1337 RendererD3D *renderer,
1338 ShaderExecutableD3D **outExectuable,
1339 gl::InfoLog *infoLog)
1340 {
1341 if (mCachedVertexExecutableIndex.valid())
1342 {
1343 *outExectuable =
1344 mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
1345 return angle::Result::Continue;
1346 }
1347
1348 // Generate new dynamic layout with attribute conversions
1349 std::string vertexHLSL = DynamicHLSL::GenerateVertexShaderForInputLayout(
1350 renderer, mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout,
1351 mExecutable->getProgramInputs(), mShaderStorageBlocks[gl::ShaderType::Vertex],
1352 mPixelShaderKey.size());
1353 std::string finalVertexHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature(
1354 *this, gl::ShaderType::Vertex, mAttachedShaders[gl::ShaderType::Vertex], vertexHLSL,
1355 mImage2DUniforms[gl::ShaderType::Vertex], mImage2DBindLayoutCache[gl::ShaderType::Vertex],
1356 static_cast<unsigned int>(mPixelShaderKey.size()));
1357
1358 // Generate new vertex executable
1359 ShaderExecutableD3D *vertexExecutable = nullptr;
1360
1361 gl::InfoLog tempInfoLog;
1362 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1363
1364 ANGLE_TRY(renderer->compileToExecutable(
1365 context, *currentInfoLog, finalVertexHLSL, gl::ShaderType::Vertex, mStreamOutVaryings,
1366 mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS,
1367 mShaderWorkarounds[gl::ShaderType::Vertex], &vertexExecutable));
1368
1369 if (vertexExecutable)
1370 {
1371 mVertexExecutables.push_back(std::unique_ptr<D3DVertexExecutable>(
1372 new D3DVertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
1373 mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
1374 }
1375 else if (!infoLog)
1376 {
1377 ERR() << "Error compiling dynamic vertex executable:" << std::endl
1378 << tempInfoLog.str() << std::endl;
1379 }
1380
1381 *outExectuable = vertexExecutable;
1382 return angle::Result::Continue;
1383 }
1384
getGeometryExecutableForPrimitiveType(d3d::Context * context,RendererD3D * renderer,const gl::Caps & caps,gl::ProvokingVertexConvention provokingVertex,gl::PrimitiveMode drawMode,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1385 angle::Result ProgramExecutableD3D::getGeometryExecutableForPrimitiveType(
1386 d3d::Context *context,
1387 RendererD3D *renderer,
1388 const gl::Caps &caps,
1389 gl::ProvokingVertexConvention provokingVertex,
1390 gl::PrimitiveMode drawMode,
1391 ShaderExecutableD3D **outExecutable,
1392 gl::InfoLog *infoLog)
1393 {
1394 if (outExecutable)
1395 {
1396 *outExecutable = nullptr;
1397 }
1398
1399 // Return a null shader if the current rendering doesn't use a geometry shader
1400 if (!usesGeometryShader(renderer, provokingVertex, drawMode))
1401 {
1402 return angle::Result::Continue;
1403 }
1404
1405 gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
1406
1407 if (mGeometryExecutables[geometryShaderType])
1408 {
1409 if (outExecutable)
1410 {
1411 *outExecutable = mGeometryExecutables[geometryShaderType].get();
1412 }
1413 return angle::Result::Continue;
1414 }
1415
1416 std::string geometryHLSL = DynamicHLSL::GenerateGeometryShaderHLSL(
1417 renderer, caps, geometryShaderType, renderer->presentPathFastEnabled(),
1418 mHasMultiviewEnabled, renderer->canSelectViewInVertexShader(),
1419 usesGeometryShaderForPointSpriteEmulation(renderer), mGeometryShaderPreamble);
1420
1421 gl::InfoLog tempInfoLog;
1422 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1423
1424 ShaderExecutableD3D *geometryExecutable = nullptr;
1425 angle::Result result = renderer->compileToExecutable(
1426 context, *currentInfoLog, geometryHLSL, gl::ShaderType::Geometry, mStreamOutVaryings,
1427 mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS,
1428 CompilerWorkaroundsD3D(), &geometryExecutable);
1429
1430 if (!infoLog && result == angle::Result::Stop)
1431 {
1432 ERR() << "Error compiling dynamic geometry executable:" << std::endl
1433 << tempInfoLog.str() << std::endl;
1434 }
1435
1436 if (geometryExecutable != nullptr)
1437 {
1438 mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
1439 }
1440
1441 if (outExecutable)
1442 {
1443 *outExecutable = mGeometryExecutables[geometryShaderType].get();
1444 }
1445 return result;
1446 }
1447
getPixelExecutableForCachedOutputLayout(d3d::Context * context,RendererD3D * renderer,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1448 angle::Result ProgramExecutableD3D::getPixelExecutableForCachedOutputLayout(
1449 d3d::Context *context,
1450 RendererD3D *renderer,
1451 ShaderExecutableD3D **outExecutable,
1452 gl::InfoLog *infoLog)
1453 {
1454 if (mCachedPixelExecutableIndex.valid())
1455 {
1456 *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
1457 return angle::Result::Continue;
1458 }
1459
1460 std::string pixelHLSL = DynamicHLSL::GeneratePixelShaderForOutputSignature(
1461 renderer, mShaderHLSL[gl::ShaderType::Fragment], mPixelShaderKey, mFragDepthUsage,
1462 mUsesSampleMask, mPixelShaderOutputLayoutCache,
1463 mShaderStorageBlocks[gl::ShaderType::Fragment], mPixelShaderKey.size());
1464
1465 std::string finalPixelHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature(
1466 *this, gl::ShaderType::Fragment, mAttachedShaders[gl::ShaderType::Fragment], pixelHLSL,
1467 mImage2DUniforms[gl::ShaderType::Fragment],
1468 mImage2DBindLayoutCache[gl::ShaderType::Fragment],
1469 static_cast<unsigned int>(mPixelShaderKey.size()));
1470
1471 // Generate new pixel executable
1472 ShaderExecutableD3D *pixelExecutable = nullptr;
1473
1474 gl::InfoLog tempInfoLog;
1475 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1476
1477 ANGLE_TRY(renderer->compileToExecutable(
1478 context, *currentInfoLog, finalPixelHLSL, gl::ShaderType::Fragment, mStreamOutVaryings,
1479 mExecutable->getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS,
1480 mShaderWorkarounds[gl::ShaderType::Fragment], &pixelExecutable));
1481
1482 if (pixelExecutable)
1483 {
1484 mPixelExecutables.push_back(std::unique_ptr<D3DPixelExecutable>(new D3DPixelExecutable(
1485 mPixelShaderOutputLayoutCache, mImage2DBindLayoutCache[gl::ShaderType::Fragment],
1486 pixelExecutable)));
1487 mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
1488 }
1489 else if (!infoLog)
1490 {
1491 ERR() << "Error compiling dynamic pixel executable:" << std::endl
1492 << tempInfoLog.str() << std::endl;
1493 }
1494
1495 *outExecutable = pixelExecutable;
1496 return angle::Result::Continue;
1497 }
1498
getComputeExecutableForImage2DBindLayout(d3d::Context * context,RendererD3D * renderer,ShaderExecutableD3D ** outExecutable,gl::InfoLog * infoLog)1499 angle::Result ProgramExecutableD3D::getComputeExecutableForImage2DBindLayout(
1500 d3d::Context *context,
1501 RendererD3D *renderer,
1502 ShaderExecutableD3D **outExecutable,
1503 gl::InfoLog *infoLog)
1504 {
1505 ANGLE_TRACE_EVENT0("gpu.angle",
1506 "ProgramExecutableD3D::getComputeExecutableForImage2DBindLayout");
1507 if (mCachedComputeExecutableIndex.valid())
1508 {
1509 *outExecutable =
1510 mComputeExecutables[mCachedComputeExecutableIndex.value()]->shaderExecutable();
1511 return angle::Result::Continue;
1512 }
1513
1514 std::string finalComputeHLSL = DynamicHLSL::GenerateShaderForImage2DBindSignature(
1515 *this, gl::ShaderType::Compute, mAttachedShaders[gl::ShaderType::Compute],
1516 mShaderHLSL[gl::ShaderType::Compute], mImage2DUniforms[gl::ShaderType::Compute],
1517 mImage2DBindLayoutCache[gl::ShaderType::Compute], 0u);
1518
1519 // Generate new compute executable
1520 ShaderExecutableD3D *computeExecutable = nullptr;
1521
1522 gl::InfoLog tempInfoLog;
1523 gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
1524
1525 ANGLE_TRY(renderer->compileToExecutable(context, *currentInfoLog, finalComputeHLSL,
1526 gl::ShaderType::Compute, std::vector<D3DVarying>(),
1527 false, CompilerWorkaroundsD3D(), &computeExecutable));
1528
1529 if (computeExecutable)
1530 {
1531 mComputeExecutables.push_back(std::unique_ptr<D3DComputeExecutable>(
1532 new D3DComputeExecutable(mImage2DBindLayoutCache[gl::ShaderType::Compute],
1533 std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
1534 mCachedComputeExecutableIndex = mComputeExecutables.size() - 1;
1535 }
1536 else if (!infoLog)
1537 {
1538 ERR() << "Error compiling dynamic compute executable:" << std::endl
1539 << tempInfoLog.str() << std::endl;
1540 }
1541 *outExecutable = computeExecutable;
1542
1543 return angle::Result::Continue;
1544 }
1545
hasNamedUniform(const std::string & name)1546 bool ProgramExecutableD3D::hasNamedUniform(const std::string &name)
1547 {
1548 for (D3DUniform *d3dUniform : mD3DUniforms)
1549 {
1550 if (d3dUniform->name == name)
1551 {
1552 return true;
1553 }
1554 }
1555
1556 return false;
1557 }
1558
initAttribLocationsToD3DSemantic(const gl::SharedCompiledShaderState & vertexShader)1559 void ProgramExecutableD3D::initAttribLocationsToD3DSemantic(
1560 const gl::SharedCompiledShaderState &vertexShader)
1561 {
1562 if (!vertexShader)
1563 {
1564 return;
1565 }
1566
1567 // Init semantic index
1568 int semanticIndex = 0;
1569 for (const sh::ShaderVariable &attribute : vertexShader->activeAttributes)
1570 {
1571 int regCount = gl::VariableRegisterCount(attribute.type);
1572 GLuint location = mExecutable->getAttributeLocation(attribute.name);
1573 ASSERT(location != std::numeric_limits<GLuint>::max());
1574
1575 for (int reg = 0; reg < regCount; ++reg)
1576 {
1577 mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
1578 }
1579 }
1580 }
1581
initializeUniformBlocks()1582 void ProgramExecutableD3D::initializeUniformBlocks()
1583 {
1584 if (mExecutable->getUniformBlocks().empty())
1585 {
1586 return;
1587 }
1588
1589 ASSERT(mD3DUniformBlocks.empty());
1590
1591 // Assign registers and update sizes.
1592 for (const gl::InterfaceBlock &uniformBlock : mExecutable->getUniformBlocks())
1593 {
1594 unsigned int uniformBlockElement =
1595 uniformBlock.pod.isArray ? uniformBlock.pod.arrayElement : 0;
1596
1597 D3DUniformBlock d3dUniformBlock;
1598
1599 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1600 {
1601 if (uniformBlock.isActive(shaderType))
1602 {
1603 ASSERT(mAttachedShaders[shaderType]);
1604 unsigned int baseRegister =
1605 mAttachedShaders[shaderType]->getUniformBlockRegister(uniformBlock.name);
1606 d3dUniformBlock.mShaderRegisterIndexes[shaderType] =
1607 baseRegister + uniformBlockElement;
1608 bool useStructuredBuffer =
1609 mAttachedShaders[shaderType]->shouldUniformBlockUseStructuredBuffer(
1610 uniformBlock.name);
1611 if (useStructuredBuffer)
1612 {
1613 d3dUniformBlock.mUseStructuredBuffers[shaderType] = true;
1614 d3dUniformBlock.mByteWidths[shaderType] = uniformBlock.pod.dataSize;
1615 d3dUniformBlock.mStructureByteStrides[shaderType] =
1616 uniformBlock.pod.firstFieldArraySize == 0u
1617 ? uniformBlock.pod.dataSize
1618 : uniformBlock.pod.dataSize / uniformBlock.pod.firstFieldArraySize;
1619 }
1620 }
1621 }
1622
1623 mD3DUniformBlocks.push_back(d3dUniformBlock);
1624 }
1625 }
1626
initializeShaderStorageBlocks(const gl::ShaderMap<gl::SharedCompiledShaderState> & shaders)1627 void ProgramExecutableD3D::initializeShaderStorageBlocks(
1628 const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders)
1629 {
1630 if (mExecutable->getShaderStorageBlocks().empty())
1631 {
1632 return;
1633 }
1634
1635 ASSERT(mD3DShaderStorageBlocks.empty());
1636
1637 // Assign registers and update sizes.
1638 for (const gl::InterfaceBlock &shaderStorageBlock : mExecutable->getShaderStorageBlocks())
1639 {
1640 unsigned int shaderStorageBlockElement =
1641 shaderStorageBlock.pod.isArray ? shaderStorageBlock.pod.arrayElement : 0;
1642 D3DInterfaceBlock d3dShaderStorageBlock;
1643
1644 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1645 {
1646 if (shaderStorageBlock.isActive(shaderType))
1647 {
1648 ASSERT(mAttachedShaders[shaderType]);
1649 unsigned int baseRegister =
1650 mAttachedShaders[shaderType]->getShaderStorageBlockRegister(
1651 shaderStorageBlock.name);
1652
1653 d3dShaderStorageBlock.mShaderRegisterIndexes[shaderType] =
1654 baseRegister + shaderStorageBlockElement;
1655 }
1656 }
1657 mD3DShaderStorageBlocks.push_back(d3dShaderStorageBlock);
1658 }
1659
1660 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1661 {
1662 const gl::SharedCompiledShaderState &shader = shaders[shaderType];
1663 if (!shader)
1664 {
1665 continue;
1666 }
1667 for (const sh::InterfaceBlock &ssbo : shader->shaderStorageBlocks)
1668 {
1669 if (!ssbo.active)
1670 {
1671 continue;
1672 }
1673 ShaderStorageBlock block;
1674 block.name = !ssbo.instanceName.empty() ? ssbo.instanceName : ssbo.name;
1675 block.arraySize = ssbo.isArray() ? ssbo.arraySize : 0;
1676 block.registerIndex =
1677 mAttachedShaders[shaderType]->getShaderStorageBlockRegister(ssbo.name);
1678 mShaderStorageBlocks[shaderType].push_back(block);
1679 }
1680 }
1681 }
1682
initializeUniformStorage(RendererD3D * renderer,const gl::ShaderBitSet & availableShaderStages)1683 void ProgramExecutableD3D::initializeUniformStorage(RendererD3D *renderer,
1684 const gl::ShaderBitSet &availableShaderStages)
1685 {
1686 // Compute total default block size
1687 gl::ShaderMap<unsigned int> shaderRegisters = {};
1688 for (const D3DUniform *d3dUniform : mD3DUniforms)
1689 {
1690 if (d3dUniform->isSampler())
1691 {
1692 continue;
1693 }
1694
1695 for (gl::ShaderType shaderType : availableShaderStages)
1696 {
1697 if (d3dUniform->isReferencedByShader(shaderType))
1698 {
1699 shaderRegisters[shaderType] = std::max(
1700 shaderRegisters[shaderType],
1701 d3dUniform->mShaderRegisterIndexes[shaderType] + d3dUniform->registerCount);
1702 }
1703 }
1704 }
1705
1706 // We only reset uniform storages for the shader stages available in the program (attached
1707 // shaders in ProgramExecutableD3D::link() and linkedShaderStages in
1708 // ProgramExecutableD3D::load()).
1709 for (gl::ShaderType shaderType : availableShaderStages)
1710 {
1711 mShaderUniformStorages[shaderType].reset(
1712 renderer->createUniformStorage(shaderRegisters[shaderType] * 16u));
1713 }
1714
1715 // Iterate the uniforms again to assign data pointers to default block uniforms.
1716 for (D3DUniform *d3dUniform : mD3DUniforms)
1717 {
1718 if (d3dUniform->isSampler())
1719 {
1720 d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
1721 continue;
1722 }
1723
1724 for (gl::ShaderType shaderType : availableShaderStages)
1725 {
1726 if (d3dUniform->isReferencedByShader(shaderType))
1727 {
1728 d3dUniform->mShaderData[shaderType] =
1729 mShaderUniformStorages[shaderType]->getDataPointer(
1730 d3dUniform->mShaderRegisterIndexes[shaderType],
1731 d3dUniform->registerElement);
1732 }
1733 }
1734 }
1735 }
1736
updateCachedInputLayoutFromShader(RendererD3D * renderer,const gl::SharedCompiledShaderState & vertexShader)1737 void ProgramExecutableD3D::updateCachedInputLayoutFromShader(
1738 RendererD3D *renderer,
1739 const gl::SharedCompiledShaderState &vertexShader)
1740 {
1741 GetDefaultInputLayoutFromShader(vertexShader, &mCachedInputLayout);
1742 D3DVertexExecutable::getSignature(renderer, mCachedInputLayout, &mCachedVertexSignature);
1743 updateCachedVertexExecutableIndex();
1744 }
1745
updateCachedOutputLayoutFromShader()1746 void ProgramExecutableD3D::updateCachedOutputLayoutFromShader()
1747 {
1748 GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
1749 updateCachedPixelExecutableIndex();
1750 }
1751
updateCachedImage2DBindLayoutFromShader(gl::ShaderType shaderType)1752 void ProgramExecutableD3D::updateCachedImage2DBindLayoutFromShader(gl::ShaderType shaderType)
1753 {
1754 GetDefaultImage2DBindLayoutFromShader(mImage2DUniforms[shaderType],
1755 &mImage2DBindLayoutCache[shaderType]);
1756 switch (shaderType)
1757 {
1758 case gl::ShaderType::Compute:
1759 updateCachedComputeExecutableIndex();
1760 break;
1761 case gl::ShaderType::Fragment:
1762 updateCachedPixelExecutableIndex();
1763 break;
1764 case gl::ShaderType::Vertex:
1765 updateCachedVertexExecutableIndex();
1766 break;
1767 default:
1768 ASSERT(false);
1769 break;
1770 }
1771 }
1772
updateCachedInputLayout(RendererD3D * renderer,UniqueSerial associatedSerial,const gl::State & state)1773 void ProgramExecutableD3D::updateCachedInputLayout(RendererD3D *renderer,
1774 UniqueSerial associatedSerial,
1775 const gl::State &state)
1776 {
1777 if (mCurrentVertexArrayStateSerial == associatedSerial)
1778 {
1779 return;
1780 }
1781
1782 mCurrentVertexArrayStateSerial = associatedSerial;
1783 mCachedInputLayout.clear();
1784
1785 const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
1786 const gl::AttributesMask &attributesMask = mExecutable->getActiveAttribLocationsMask();
1787
1788 for (size_t locationIndex : attributesMask)
1789 {
1790 int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
1791
1792 if (d3dSemantic != -1)
1793 {
1794 if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
1795 {
1796 mCachedInputLayout.resize(d3dSemantic + 1, angle::FormatID::NONE);
1797 }
1798 mCachedInputLayout[d3dSemantic] =
1799 GetVertexFormatID(vertexAttributes[locationIndex],
1800 state.getVertexAttribCurrentValue(locationIndex).Type);
1801 }
1802 }
1803
1804 D3DVertexExecutable::getSignature(renderer, mCachedInputLayout, &mCachedVertexSignature);
1805
1806 updateCachedVertexExecutableIndex();
1807 }
1808
updateCachedOutputLayout(const gl::Context * context,const gl::Framebuffer * framebuffer)1809 void ProgramExecutableD3D::updateCachedOutputLayout(const gl::Context *context,
1810 const gl::Framebuffer *framebuffer)
1811 {
1812 mPixelShaderOutputLayoutCache.clear();
1813
1814 FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
1815 const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
1816
1817 for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
1818 {
1819 const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
1820
1821 if (colorbuffer)
1822 {
1823 auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
1824 : colorbuffer->getBinding();
1825 size_t maxIndex = binding != GL_NONE ? GetMaxOutputIndex(mPixelShaderKey,
1826 binding - GL_COLOR_ATTACHMENT0)
1827 : 0;
1828 mPixelShaderOutputLayoutCache.insert(mPixelShaderOutputLayoutCache.end(), maxIndex + 1,
1829 binding);
1830 }
1831 else
1832 {
1833 mPixelShaderOutputLayoutCache.push_back(GL_NONE);
1834 }
1835 }
1836
1837 updateCachedPixelExecutableIndex();
1838 }
1839
updateCachedImage2DBindLayout(const gl::Context * context,const gl::ShaderType shaderType)1840 void ProgramExecutableD3D::updateCachedImage2DBindLayout(const gl::Context *context,
1841 const gl::ShaderType shaderType)
1842 {
1843 const auto &glState = context->getState();
1844 for (auto &image2DBindLayout : mImage2DBindLayoutCache[shaderType])
1845 {
1846 const gl::ImageUnit &imageUnit = glState.getImageUnit(image2DBindLayout.first);
1847 if (imageUnit.texture.get())
1848 {
1849 image2DBindLayout.second = imageUnit.texture->getType();
1850 }
1851 else
1852 {
1853 image2DBindLayout.second = gl::TextureType::_2D;
1854 }
1855 }
1856
1857 switch (shaderType)
1858 {
1859 case gl::ShaderType::Vertex:
1860 updateCachedVertexExecutableIndex();
1861 break;
1862 case gl::ShaderType::Fragment:
1863 updateCachedPixelExecutableIndex();
1864 break;
1865 case gl::ShaderType::Compute:
1866 updateCachedComputeExecutableIndex();
1867 break;
1868 default:
1869 ASSERT(false);
1870 break;
1871 }
1872 }
1873
updateCachedVertexExecutableIndex()1874 void ProgramExecutableD3D::updateCachedVertexExecutableIndex()
1875 {
1876 mCachedVertexExecutableIndex.reset();
1877 for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
1878 {
1879 if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
1880 {
1881 mCachedVertexExecutableIndex = executableIndex;
1882 break;
1883 }
1884 }
1885 }
1886
updateCachedPixelExecutableIndex()1887 void ProgramExecutableD3D::updateCachedPixelExecutableIndex()
1888 {
1889 mCachedPixelExecutableIndex.reset();
1890 for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
1891 {
1892 if (mPixelExecutables[executableIndex]->matchesSignature(
1893 mPixelShaderOutputLayoutCache, mImage2DBindLayoutCache[gl::ShaderType::Fragment]))
1894 {
1895 mCachedPixelExecutableIndex = executableIndex;
1896 break;
1897 }
1898 }
1899 }
1900
updateCachedComputeExecutableIndex()1901 void ProgramExecutableD3D::updateCachedComputeExecutableIndex()
1902 {
1903 mCachedComputeExecutableIndex.reset();
1904 for (size_t executableIndex = 0; executableIndex < mComputeExecutables.size();
1905 executableIndex++)
1906 {
1907 if (mComputeExecutables[executableIndex]->matchesSignature(
1908 mImage2DBindLayoutCache[gl::ShaderType::Compute]))
1909 {
1910 mCachedComputeExecutableIndex = executableIndex;
1911 break;
1912 }
1913 }
1914 }
1915
updateUniformBufferCache(const gl::Caps & caps)1916 void ProgramExecutableD3D::updateUniformBufferCache(const gl::Caps &caps)
1917 {
1918 if (mExecutable->getUniformBlocks().empty())
1919 {
1920 return;
1921 }
1922
1923 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1924 {
1925 mShaderUBOCaches[shaderType].clear();
1926 mShaderUBOCachesUseSB[shaderType].clear();
1927 }
1928
1929 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
1930 uniformBlockIndex++)
1931 {
1932 const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
1933 GLuint blockBinding = mExecutable->getUniformBlockBinding(uniformBlockIndex);
1934
1935 // Unnecessary to apply an unreferenced standard or shared UBO
1936 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1937 {
1938 if (!uniformBlock.activeInShader(shaderType))
1939 {
1940 continue;
1941 }
1942
1943 bool useStructuredBuffer = uniformBlock.mUseStructuredBuffers[shaderType];
1944 unsigned int registerIndex = uniformBlock.mShaderRegisterIndexes[shaderType];
1945 if (useStructuredBuffer)
1946 {
1947 D3DUBOCacheUseSB cacheUseSB;
1948 cacheUseSB.registerIndex = registerIndex;
1949 cacheUseSB.binding = blockBinding;
1950 cacheUseSB.byteWidth = uniformBlock.mByteWidths[shaderType];
1951 cacheUseSB.structureByteStride = uniformBlock.mStructureByteStrides[shaderType];
1952 mShaderUBOCachesUseSB[shaderType].push_back(cacheUseSB);
1953 }
1954 else
1955 {
1956 ASSERT(registerIndex <
1957 static_cast<unsigned int>(caps.maxShaderUniformBlocks[shaderType]));
1958 D3DUBOCache cache;
1959 cache.registerIndex = registerIndex;
1960 cache.binding = blockBinding;
1961 mShaderUBOCaches[shaderType].push_back(cache);
1962 }
1963 }
1964 }
1965
1966 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1967 {
1968 GLuint uniformBlockCount = static_cast<GLuint>(mShaderUBOCaches[shaderType].size() +
1969 mShaderUBOCachesUseSB[shaderType].size());
1970 ASSERT(uniformBlockCount <=
1971 static_cast<unsigned int>(caps.maxShaderUniformBlocks[shaderType]));
1972 }
1973 }
1974
defineUniformsAndAssignRegisters(RendererD3D * renderer,const gl::ShaderMap<gl::SharedCompiledShaderState> & shaders)1975 void ProgramExecutableD3D::defineUniformsAndAssignRegisters(
1976 RendererD3D *renderer,
1977 const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders)
1978 {
1979 D3DUniformMap uniformMap;
1980
1981 gl::ShaderBitSet attachedShaders;
1982 for (gl::ShaderType shaderType : gl::AllShaderTypes())
1983 {
1984 const gl::SharedCompiledShaderState &shader = shaders[shaderType];
1985 if (shader)
1986 {
1987 for (const sh::ShaderVariable &uniform : shader->uniforms)
1988 {
1989 if (uniform.active)
1990 {
1991 defineUniformBase(shader->shaderType, uniform, &uniformMap);
1992 }
1993 }
1994
1995 attachedShaders.set(shader->shaderType);
1996 }
1997 }
1998
1999 // Initialize the D3DUniform list to mirror the indexing of the GL layer.
2000 for (GLuint index = 0; index < static_cast<GLuint>(mExecutable->getUniforms().size()); index++)
2001 {
2002 const gl::LinkedUniform &glUniform = mExecutable->getUniforms()[index];
2003 if (!glUniform.isInDefaultBlock())
2004 continue;
2005
2006 std::string name = mExecutable->getUniformNames()[index];
2007 if (glUniform.isArray())
2008 {
2009 // In the program state, array uniform names include [0] as in the program resource
2010 // spec. Here we don't include it.
2011 // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL
2012 // layer.
2013 ASSERT(angle::EndsWith(name, "[0]"));
2014 name.resize(name.length() - 3);
2015 }
2016 auto mapEntry = uniformMap.find(name);
2017 ASSERT(mapEntry != uniformMap.end());
2018 mD3DUniforms.push_back(mapEntry->second);
2019 }
2020
2021 assignAllSamplerRegisters(shaders);
2022 assignAllAtomicCounterRegisters();
2023 // Samplers and readonly images share shader input resource slot, adjust low value of
2024 // readonly image range.
2025 for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
2026 {
2027 mUsedReadonlyImageRange[shaderType] =
2028 gl::RangeUI(mUsedShaderSamplerRanges[shaderType].high(),
2029 mUsedShaderSamplerRanges[shaderType].high());
2030 // Atomic counter buffers and non-readonly images share input resource slots
2031 mUsedImageRange[shaderType] = gl::RangeUI(mUsedAtomicCounterRange[shaderType].high(),
2032 mUsedAtomicCounterRange[shaderType].high());
2033 }
2034 assignAllImageRegisters();
2035 initializeUniformStorage(renderer, attachedShaders);
2036 }
2037
defineUniformBase(gl::ShaderType shaderType,const sh::ShaderVariable & uniform,D3DUniformMap * uniformMap)2038 void ProgramExecutableD3D::defineUniformBase(gl::ShaderType shaderType,
2039 const sh::ShaderVariable &uniform,
2040 D3DUniformMap *uniformMap)
2041 {
2042 sh::StubBlockEncoder stubEncoder;
2043
2044 // Samplers get their registers assigned in assignAllSamplerRegisters, and images get their
2045 // registers assigned in assignAllImageRegisters.
2046 if (gl::IsSamplerType(uniform.type))
2047 {
2048 UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::Texture, &stubEncoder,
2049 uniformMap);
2050 sh::TraverseShaderVariable(uniform, false, &visitor);
2051 return;
2052 }
2053
2054 if (gl::IsImageType(uniform.type))
2055 {
2056 if (uniform.readonly)
2057 {
2058 UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::Texture, &stubEncoder,
2059 uniformMap);
2060 sh::TraverseShaderVariable(uniform, false, &visitor);
2061 }
2062 else
2063 {
2064 UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::UnorderedAccessView,
2065 &stubEncoder, uniformMap);
2066 sh::TraverseShaderVariable(uniform, false, &visitor);
2067 }
2068 mImageBindingMap[uniform.name] = uniform.binding;
2069 return;
2070 }
2071
2072 if (uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn())
2073 {
2074 UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::None, &stubEncoder,
2075 uniformMap);
2076 sh::TraverseShaderVariable(uniform, false, &visitor);
2077 return;
2078 }
2079 else if (gl::IsAtomicCounterType(uniform.type))
2080 {
2081 UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::UnorderedAccessView,
2082 &stubEncoder, uniformMap);
2083 sh::TraverseShaderVariable(uniform, false, &visitor);
2084 mAtomicBindingMap[uniform.name] = uniform.binding;
2085 return;
2086 }
2087
2088 const SharedCompiledShaderStateD3D &shaderD3D = mAttachedShaders[shaderType];
2089 unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
2090 ShShaderOutput outputType = shaderD3D->compilerOutputType;
2091 sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
2092 encoder.skipRegisters(startRegister);
2093
2094 UniformEncodingVisitorD3D visitor(shaderType, HLSLRegisterType::None, &encoder, uniformMap);
2095 sh::TraverseShaderVariable(uniform, false, &visitor);
2096 }
2097
assignAllSamplerRegisters(const gl::ShaderMap<gl::SharedCompiledShaderState> & shaders)2098 void ProgramExecutableD3D::assignAllSamplerRegisters(
2099 const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders)
2100 {
2101 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2102 {
2103 if (mD3DUniforms[uniformIndex]->isSampler())
2104 {
2105 assignSamplerRegisters(shaders, uniformIndex);
2106 }
2107 }
2108 }
2109
assignSamplerRegisters(const gl::ShaderMap<gl::SharedCompiledShaderState> & shaders,size_t uniformIndex)2110 void ProgramExecutableD3D::assignSamplerRegisters(
2111 const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders,
2112 size_t uniformIndex)
2113 {
2114 D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2115 ASSERT(d3dUniform->isSampler());
2116 // If the uniform is an array of arrays, then we have separate entries for each inner array in
2117 // mD3DUniforms. However, the sampler register info is stored in the shader only for the
2118 // outermost array.
2119 std::vector<unsigned int> subscripts;
2120 const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2121 unsigned int registerOffset = mExecutable->getUniforms()[uniformIndex].pod.parentArrayIndex *
2122 d3dUniform->getArraySizeProduct();
2123
2124 bool hasUniform = false;
2125 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2126 {
2127 if (!shaders[shaderType])
2128 {
2129 continue;
2130 }
2131
2132 const SharedCompiledShaderStateD3D &shaderD3D = mAttachedShaders[shaderType];
2133 if (shaderD3D->hasUniform(baseName))
2134 {
2135 d3dUniform->mShaderRegisterIndexes[shaderType] =
2136 shaderD3D->getUniformRegister(baseName) + registerOffset;
2137 ASSERT(d3dUniform->mShaderRegisterIndexes[shaderType] != GL_INVALID_VALUE);
2138
2139 AssignSamplers(d3dUniform->mShaderRegisterIndexes[shaderType], d3dUniform->typeInfo,
2140 d3dUniform->getArraySizeProduct(), mShaderSamplers[shaderType],
2141 &mUsedShaderSamplerRanges[shaderType]);
2142 hasUniform = true;
2143 }
2144 }
2145
2146 ASSERT(hasUniform);
2147 }
2148
2149 // static
AssignSamplers(unsigned int startSamplerIndex,const gl::UniformTypeInfo & typeInfo,unsigned int samplerCount,std::vector<D3DSampler> & outSamplers,gl::RangeUI * outUsedRange)2150 void ProgramExecutableD3D::AssignSamplers(unsigned int startSamplerIndex,
2151 const gl::UniformTypeInfo &typeInfo,
2152 unsigned int samplerCount,
2153 std::vector<D3DSampler> &outSamplers,
2154 gl::RangeUI *outUsedRange)
2155 {
2156 unsigned int samplerIndex = startSamplerIndex;
2157
2158 do
2159 {
2160 ASSERT(samplerIndex < outSamplers.size());
2161 D3DSampler *sampler = &outSamplers[samplerIndex];
2162 sampler->active = true;
2163 sampler->textureType = gl::FromGLenum<gl::TextureType>(typeInfo.textureType);
2164 sampler->logicalTextureUnit = 0;
2165 outUsedRange->extend(samplerIndex);
2166 samplerIndex++;
2167 } while (samplerIndex < startSamplerIndex + samplerCount);
2168 }
2169
assignAllImageRegisters()2170 void ProgramExecutableD3D::assignAllImageRegisters()
2171 {
2172 for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
2173 {
2174 if (mD3DUniforms[uniformIndex]->isImage() && !mD3DUniforms[uniformIndex]->isImage2D())
2175 {
2176 assignImageRegisters(uniformIndex);
2177 }
2178 }
2179 }
2180
assignAllAtomicCounterRegisters()2181 void ProgramExecutableD3D::assignAllAtomicCounterRegisters()
2182 {
2183 if (mAtomicBindingMap.empty())
2184 {
2185 return;
2186 }
2187 const SharedCompiledShaderStateD3D &computeShader = mAttachedShaders[gl::ShaderType::Compute];
2188 if (computeShader)
2189 {
2190 auto ®isterIndices = mComputeAtomicCounterBufferRegisterIndices;
2191 for (auto &atomicBinding : mAtomicBindingMap)
2192 {
2193 ASSERT(computeShader->hasUniform(atomicBinding.first));
2194 unsigned int currentRegister = computeShader->getUniformRegister(atomicBinding.first);
2195 ASSERT(currentRegister != GL_INVALID_INDEX);
2196 const int kBinding = atomicBinding.second;
2197
2198 registerIndices[kBinding] = currentRegister;
2199
2200 mUsedAtomicCounterRange[gl::ShaderType::Compute].extend(currentRegister);
2201 }
2202 }
2203 else
2204 {
2205 // Implement atomic counters for non-compute shaders
2206 // http://anglebug.com/1729
2207 UNIMPLEMENTED();
2208 }
2209 }
2210
assignImageRegisters(size_t uniformIndex)2211 void ProgramExecutableD3D::assignImageRegisters(size_t uniformIndex)
2212 {
2213 D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
2214 ASSERT(d3dUniform->isImage());
2215 // If the uniform is an array of arrays, then we have separate entries for each inner array in
2216 // mD3DUniforms. However, the image register info is stored in the shader only for the
2217 // outermost array.
2218 std::vector<unsigned int> subscripts;
2219 const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
2220 unsigned int registerOffset = mExecutable->getUniforms()[uniformIndex].pod.parentArrayIndex *
2221 d3dUniform->getArraySizeProduct();
2222
2223 const SharedCompiledShaderStateD3D &computeShader = mAttachedShaders[gl::ShaderType::Compute];
2224 if (computeShader)
2225 {
2226 ASSERT(computeShader->hasUniform(baseName));
2227 d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] =
2228 computeShader->getUniformRegister(baseName) + registerOffset;
2229 ASSERT(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] != GL_INVALID_INDEX);
2230 auto bindingIter = mImageBindingMap.find(baseName);
2231 ASSERT(bindingIter != mImageBindingMap.end());
2232 if (d3dUniform->regType == HLSLRegisterType::Texture)
2233 {
2234 AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2235 bindingIter->second, d3dUniform->getArraySizeProduct(),
2236 mReadonlyImages[gl::ShaderType::Compute],
2237 &mUsedReadonlyImageRange[gl::ShaderType::Compute]);
2238 }
2239 else if (d3dUniform->regType == HLSLRegisterType::UnorderedAccessView)
2240 {
2241 AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
2242 bindingIter->second, d3dUniform->getArraySizeProduct(),
2243 mImages[gl::ShaderType::Compute],
2244 &mUsedImageRange[gl::ShaderType::Compute]);
2245 }
2246 else
2247 {
2248 UNREACHABLE();
2249 }
2250 }
2251 else
2252 {
2253 // TODO(xinghua.cao@intel.com): Implement image variables in vertex shader and pixel shader.
2254 UNIMPLEMENTED();
2255 }
2256 }
2257
2258 // static
AssignImages(unsigned int startImageIndex,int startLogicalImageUnit,unsigned int imageCount,std::vector<D3DImage> & outImages,gl::RangeUI * outUsedRange)2259 void ProgramExecutableD3D::AssignImages(unsigned int startImageIndex,
2260 int startLogicalImageUnit,
2261 unsigned int imageCount,
2262 std::vector<D3DImage> &outImages,
2263 gl::RangeUI *outUsedRange)
2264 {
2265 unsigned int imageIndex = startImageIndex;
2266
2267 // If declare without a binding qualifier, any uniform image variable (include all elements of
2268 // unbound image array) shoud be bound to unit zero.
2269 if (startLogicalImageUnit == -1)
2270 {
2271 ASSERT(imageIndex < outImages.size());
2272 D3DImage *image = &outImages[imageIndex];
2273 image->active = true;
2274 image->logicalImageUnit = 0;
2275 outUsedRange->extend(imageIndex);
2276 return;
2277 }
2278
2279 unsigned int logcalImageUnit = startLogicalImageUnit;
2280 do
2281 {
2282 ASSERT(imageIndex < outImages.size());
2283 D3DImage *image = &outImages[imageIndex];
2284 image->active = true;
2285 image->logicalImageUnit = logcalImageUnit;
2286 outUsedRange->extend(imageIndex);
2287 imageIndex++;
2288 logcalImageUnit++;
2289 } while (imageIndex < startImageIndex + imageCount);
2290 }
2291
assignImage2DRegisters(gl::ShaderType shaderType,unsigned int startImageIndex,int startLogicalImageUnit,bool readonly)2292 void ProgramExecutableD3D::assignImage2DRegisters(gl::ShaderType shaderType,
2293 unsigned int startImageIndex,
2294 int startLogicalImageUnit,
2295 bool readonly)
2296 {
2297 if (readonly)
2298 {
2299 AssignImages(startImageIndex, startLogicalImageUnit, 1, mReadonlyImages[shaderType],
2300 &mUsedReadonlyImageRange[shaderType]);
2301 }
2302 else
2303 {
2304 AssignImages(startImageIndex, startLogicalImageUnit, 1, mImages[shaderType],
2305 &mUsedImageRange[shaderType]);
2306 }
2307 }
2308
gatherTransformFeedbackVaryings(RendererD3D * renderer,const gl::VaryingPacking & varyingPacking,const std::vector<std::string> & tfVaryingNames,const BuiltinInfo & builtins)2309 void ProgramExecutableD3D::gatherTransformFeedbackVaryings(
2310 RendererD3D *renderer,
2311 const gl::VaryingPacking &varyingPacking,
2312 const std::vector<std::string> &tfVaryingNames,
2313 const BuiltinInfo &builtins)
2314 {
2315 const std::string &varyingSemantic =
2316 GetVaryingSemantic(renderer->getMajorShaderModel(), usesPointSize());
2317
2318 // Gather the linked varyings that are used for transform feedback, they should all exist.
2319 mStreamOutVaryings.clear();
2320
2321 for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
2322 ++outputSlot)
2323 {
2324 const auto &tfVaryingName = tfVaryingNames[outputSlot];
2325 if (tfVaryingName == "gl_Position")
2326 {
2327 if (builtins.glPosition.enabled)
2328 {
2329 mStreamOutVaryings.emplace_back(builtins.glPosition.semantic,
2330 builtins.glPosition.indexOrSize, 4, outputSlot);
2331 }
2332 }
2333 else if (tfVaryingName == "gl_FragCoord")
2334 {
2335 if (builtins.glFragCoord.enabled)
2336 {
2337 mStreamOutVaryings.emplace_back(builtins.glFragCoord.semantic,
2338 builtins.glFragCoord.indexOrSize, 4, outputSlot);
2339 }
2340 }
2341 else if (tfVaryingName == "gl_PointSize")
2342 {
2343 if (builtins.glPointSize.enabled)
2344 {
2345 mStreamOutVaryings.emplace_back("PSIZE", 0, 1, outputSlot);
2346 }
2347 }
2348 else
2349 {
2350 const auto ®isterInfos = varyingPacking.getRegisterList();
2351 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
2352 {
2353 const auto ®isterInfo = registerInfos[registerIndex];
2354 const auto &varying = registerInfo.packedVarying->varying();
2355 GLenum transposedType = gl::TransposeMatrixType(varying.type);
2356 int componentCount = gl::VariableColumnCount(transposedType);
2357 ASSERT(!varying.isBuiltIn() && !varying.isStruct());
2358
2359 // There can be more than one register assigned to a particular varying, and each
2360 // register needs its own stream out entry.
2361 if (registerInfo.tfVaryingName() == tfVaryingName)
2362 {
2363 mStreamOutVaryings.emplace_back(varyingSemantic, registerIndex, componentCount,
2364 outputSlot);
2365 }
2366 }
2367 }
2368 }
2369 }
2370
getD3DUniformFromLocation(const gl::VariableLocation & locationInfo)2371 D3DUniform *ProgramExecutableD3D::getD3DUniformFromLocation(
2372 const gl::VariableLocation &locationInfo)
2373 {
2374 return mD3DUniforms[locationInfo.index];
2375 }
2376
getD3DUniformFromLocation(const gl::VariableLocation & locationInfo) const2377 const D3DUniform *ProgramExecutableD3D::getD3DUniformFromLocation(
2378 const gl::VariableLocation &locationInfo) const
2379 {
2380 return mD3DUniforms[locationInfo.index];
2381 }
2382
issueSerial()2383 unsigned int ProgramExecutableD3D::issueSerial()
2384 {
2385 return mCurrentSerial++;
2386 }
2387
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)2388 void ProgramExecutableD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
2389 {
2390 setUniformInternal(location, count, v, GL_FLOAT);
2391 }
2392
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)2393 void ProgramExecutableD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2394 {
2395 setUniformInternal(location, count, v, GL_FLOAT_VEC2);
2396 }
2397
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)2398 void ProgramExecutableD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2399 {
2400 setUniformInternal(location, count, v, GL_FLOAT_VEC3);
2401 }
2402
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)2403 void ProgramExecutableD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2404 {
2405 setUniformInternal(location, count, v, GL_FLOAT_VEC4);
2406 }
2407
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2408 void ProgramExecutableD3D::setUniformMatrix2fv(GLint location,
2409 GLsizei count,
2410 GLboolean transpose,
2411 const GLfloat *value)
2412 {
2413 setUniformMatrixfvInternal<2, 2>(location, count, transpose, value);
2414 }
2415
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2416 void ProgramExecutableD3D::setUniformMatrix3fv(GLint location,
2417 GLsizei count,
2418 GLboolean transpose,
2419 const GLfloat *value)
2420 {
2421 setUniformMatrixfvInternal<3, 3>(location, count, transpose, value);
2422 }
2423
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2424 void ProgramExecutableD3D::setUniformMatrix4fv(GLint location,
2425 GLsizei count,
2426 GLboolean transpose,
2427 const GLfloat *value)
2428 {
2429 setUniformMatrixfvInternal<4, 4>(location, count, transpose, value);
2430 }
2431
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2432 void ProgramExecutableD3D::setUniformMatrix2x3fv(GLint location,
2433 GLsizei count,
2434 GLboolean transpose,
2435 const GLfloat *value)
2436 {
2437 setUniformMatrixfvInternal<2, 3>(location, count, transpose, value);
2438 }
2439
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2440 void ProgramExecutableD3D::setUniformMatrix3x2fv(GLint location,
2441 GLsizei count,
2442 GLboolean transpose,
2443 const GLfloat *value)
2444 {
2445 setUniformMatrixfvInternal<3, 2>(location, count, transpose, value);
2446 }
2447
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2448 void ProgramExecutableD3D::setUniformMatrix2x4fv(GLint location,
2449 GLsizei count,
2450 GLboolean transpose,
2451 const GLfloat *value)
2452 {
2453 setUniformMatrixfvInternal<2, 4>(location, count, transpose, value);
2454 }
2455
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2456 void ProgramExecutableD3D::setUniformMatrix4x2fv(GLint location,
2457 GLsizei count,
2458 GLboolean transpose,
2459 const GLfloat *value)
2460 {
2461 setUniformMatrixfvInternal<4, 2>(location, count, transpose, value);
2462 }
2463
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2464 void ProgramExecutableD3D::setUniformMatrix3x4fv(GLint location,
2465 GLsizei count,
2466 GLboolean transpose,
2467 const GLfloat *value)
2468 {
2469 setUniformMatrixfvInternal<3, 4>(location, count, transpose, value);
2470 }
2471
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2472 void ProgramExecutableD3D::setUniformMatrix4x3fv(GLint location,
2473 GLsizei count,
2474 GLboolean transpose,
2475 const GLfloat *value)
2476 {
2477 setUniformMatrixfvInternal<4, 3>(location, count, transpose, value);
2478 }
2479
setUniform1iv(GLint location,GLsizei count,const GLint * v)2480 void ProgramExecutableD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
2481 {
2482 setUniformInternal(location, count, v, GL_INT);
2483 }
2484
setUniform2iv(GLint location,GLsizei count,const GLint * v)2485 void ProgramExecutableD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
2486 {
2487 setUniformInternal(location, count, v, GL_INT_VEC2);
2488 }
2489
setUniform3iv(GLint location,GLsizei count,const GLint * v)2490 void ProgramExecutableD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
2491 {
2492 setUniformInternal(location, count, v, GL_INT_VEC3);
2493 }
2494
setUniform4iv(GLint location,GLsizei count,const GLint * v)2495 void ProgramExecutableD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
2496 {
2497 setUniformInternal(location, count, v, GL_INT_VEC4);
2498 }
2499
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)2500 void ProgramExecutableD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
2501 {
2502 setUniformInternal(location, count, v, GL_UNSIGNED_INT);
2503 }
2504
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)2505 void ProgramExecutableD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
2506 {
2507 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
2508 }
2509
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)2510 void ProgramExecutableD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2511 {
2512 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
2513 }
2514
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)2515 void ProgramExecutableD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2516 {
2517 setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
2518 }
2519
2520 // Assume count is already clamped.
2521 template <typename T>
setUniformImpl(D3DUniform * targetUniform,const gl::VariableLocation & locationInfo,GLsizei count,const T * v,uint8_t * targetState,GLenum uniformType)2522 void ProgramExecutableD3D::setUniformImpl(D3DUniform *targetUniform,
2523 const gl::VariableLocation &locationInfo,
2524 GLsizei count,
2525 const T *v,
2526 uint8_t *targetState,
2527 GLenum uniformType)
2528 {
2529 const int components = targetUniform->typeInfo.componentCount;
2530 const unsigned int arrayElementOffset = locationInfo.arrayIndex;
2531 const int blockSize = 4;
2532
2533 if (targetUniform->typeInfo.type == uniformType)
2534 {
2535 T *dest = reinterpret_cast<T *>(targetState) + arrayElementOffset * blockSize;
2536 const T *source = v;
2537
2538 // If the component is equal to the block size, we can optimize to a single memcpy.
2539 // Otherwise, we have to do partial block writes.
2540 if (components == blockSize)
2541 {
2542 memcpy(dest, source, components * count * sizeof(T));
2543 }
2544 else
2545 {
2546 for (GLint i = 0; i < count; i++, dest += blockSize, source += components)
2547 {
2548 memcpy(dest, source, components * sizeof(T));
2549 }
2550 }
2551 }
2552 else
2553 {
2554 ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
2555 GLint *boolParams = reinterpret_cast<GLint *>(targetState) + arrayElementOffset * 4;
2556
2557 for (GLint i = 0; i < count; i++)
2558 {
2559 GLint *dest = boolParams + (i * 4);
2560 const T *source = v + (i * components);
2561
2562 for (int c = 0; c < components; c++)
2563 {
2564 dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
2565 }
2566 }
2567 }
2568 }
2569
2570 template <typename T>
setUniformInternal(GLint location,GLsizei count,const T * v,GLenum uniformType)2571 void ProgramExecutableD3D::setUniformInternal(GLint location,
2572 GLsizei count,
2573 const T *v,
2574 GLenum uniformType)
2575 {
2576 const gl::VariableLocation &locationInfo = mExecutable->getUniformLocations()[location];
2577 D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
2578
2579 if (targetUniform->typeInfo.isSampler)
2580 {
2581 ASSERT(uniformType == GL_INT);
2582 size_t size = count * sizeof(T);
2583 GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
2584 if (memcmp(dest, v, size) != 0)
2585 {
2586 memcpy(dest, v, size);
2587 mDirtySamplerMapping = true;
2588 }
2589 return;
2590 }
2591
2592 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2593 {
2594 uint8_t *targetState = targetUniform->mShaderData[shaderType];
2595 if (targetState)
2596 {
2597 setUniformImpl(targetUniform, locationInfo, count, v, targetState, uniformType);
2598 mShaderUniformsDirty.set(shaderType);
2599 }
2600 }
2601 }
2602
2603 template <int cols, int rows>
setUniformMatrixfvInternal(GLint location,GLsizei countIn,GLboolean transpose,const GLfloat * value)2604 void ProgramExecutableD3D::setUniformMatrixfvInternal(GLint location,
2605 GLsizei countIn,
2606 GLboolean transpose,
2607 const GLfloat *value)
2608 {
2609 const gl::VariableLocation &uniformLocation = mExecutable->getUniformLocations()[location];
2610 D3DUniform *targetUniform = getD3DUniformFromLocation(uniformLocation);
2611 unsigned int arrayElementOffset = uniformLocation.arrayIndex;
2612 unsigned int elementCount = targetUniform->getArraySizeProduct();
2613
2614 for (gl::ShaderType shaderType : gl::AllShaderTypes())
2615 {
2616 if (targetUniform->mShaderData[shaderType])
2617 {
2618 SetFloatUniformMatrixHLSL<cols, rows>::Run(arrayElementOffset, elementCount, countIn,
2619 transpose, value,
2620 targetUniform->mShaderData[shaderType]);
2621 mShaderUniformsDirty.set(shaderType);
2622 }
2623 }
2624 }
2625
2626 template <typename DestT>
getUniformInternal(GLint location,DestT * dataOut) const2627 void ProgramExecutableD3D::getUniformInternal(GLint location, DestT *dataOut) const
2628 {
2629 const gl::VariableLocation &locationInfo = mExecutable->getUniformLocations()[location];
2630 const gl::LinkedUniform &uniform = mExecutable->getUniforms()[locationInfo.index];
2631
2632 const D3DUniform *targetUniform = getD3DUniformFromLocation(locationInfo);
2633 const uint8_t *srcPointer = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
2634
2635 if (gl::IsMatrixType(uniform.getType()))
2636 {
2637 GetMatrixUniform(uniform.getType(), dataOut, reinterpret_cast<const DestT *>(srcPointer),
2638 true);
2639 }
2640 else
2641 {
2642 memcpy(dataOut, srcPointer, uniform.getElementSize());
2643 }
2644 }
2645
getUniformfv(const gl::Context * context,GLint location,GLfloat * params) const2646 void ProgramExecutableD3D::getUniformfv(const gl::Context *context,
2647 GLint location,
2648 GLfloat *params) const
2649 {
2650 getUniformInternal(location, params);
2651 }
2652
getUniformiv(const gl::Context * context,GLint location,GLint * params) const2653 void ProgramExecutableD3D::getUniformiv(const gl::Context *context,
2654 GLint location,
2655 GLint *params) const
2656 {
2657 getUniformInternal(location, params);
2658 }
2659
getUniformuiv(const gl::Context * context,GLint location,GLuint * params) const2660 void ProgramExecutableD3D::getUniformuiv(const gl::Context *context,
2661 GLint location,
2662 GLuint *params) const
2663 {
2664 getUniformInternal(location, params);
2665 }
2666
2667 } // namespace rx
2668