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