DynamicHLSL.cpp (59967B)
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 // DynamicHLSL.cpp: Implementation for link and run-time HLSL generation 7 // 8 9 #include "libANGLE/renderer/d3d/DynamicHLSL.h" 10 11 #include "common/string_utils.h" 12 #include "common/utilities.h" 13 #include "compiler/translator/blocklayoutHLSL.h" 14 #include "libANGLE/Context.h" 15 #include "libANGLE/Program.h" 16 #include "libANGLE/Shader.h" 17 #include "libANGLE/VaryingPacking.h" 18 #include "libANGLE/formatutils.h" 19 #include "libANGLE/renderer/d3d/ProgramD3D.h" 20 #include "libANGLE/renderer/d3d/RendererD3D.h" 21 #include "libANGLE/renderer/d3d/ShaderD3D.h" 22 23 using namespace gl; 24 25 namespace rx 26 { 27 28 namespace 29 { 30 31 // kShaderStorageDeclarationString must be the same as outputHLSL. 32 constexpr const char kShaderStorageDeclarationString[] = 33 "// @@ SHADER STORAGE DECLARATION STRING @@"; 34 35 const char *HLSLComponentTypeString(GLenum componentType) 36 { 37 switch (componentType) 38 { 39 case GL_UNSIGNED_INT: 40 return "uint"; 41 case GL_INT: 42 return "int"; 43 case GL_UNSIGNED_NORMALIZED: 44 case GL_SIGNED_NORMALIZED: 45 case GL_FLOAT: 46 return "float"; 47 default: 48 UNREACHABLE(); 49 return "not-component-type"; 50 } 51 } 52 53 void HLSLComponentTypeString(std::ostringstream &ostream, GLenum componentType, int componentCount) 54 { 55 ostream << HLSLComponentTypeString(componentType); 56 if (componentCount > 1) 57 { 58 ostream << componentCount; 59 } 60 } 61 62 const char *HLSLMatrixTypeString(GLenum type) 63 { 64 switch (type) 65 { 66 case GL_FLOAT_MAT2: 67 return "float2x2"; 68 case GL_FLOAT_MAT3: 69 return "float3x3"; 70 case GL_FLOAT_MAT4: 71 return "float4x4"; 72 case GL_FLOAT_MAT2x3: 73 return "float2x3"; 74 case GL_FLOAT_MAT3x2: 75 return "float3x2"; 76 case GL_FLOAT_MAT2x4: 77 return "float2x4"; 78 case GL_FLOAT_MAT4x2: 79 return "float4x2"; 80 case GL_FLOAT_MAT3x4: 81 return "float3x4"; 82 case GL_FLOAT_MAT4x3: 83 return "float4x3"; 84 default: 85 UNREACHABLE(); 86 return "not-matrix-type"; 87 } 88 } 89 90 void HLSLTypeString(std::ostringstream &ostream, GLenum type) 91 { 92 if (gl::IsMatrixType(type)) 93 { 94 ostream << HLSLMatrixTypeString(type); 95 return; 96 } 97 98 HLSLComponentTypeString(ostream, gl::VariableComponentType(type), 99 gl::VariableComponentCount(type)); 100 } 101 102 const PixelShaderOutputVariable *FindOutputAtLocation( 103 const std::vector<PixelShaderOutputVariable> &outputVariables, 104 unsigned int location, 105 size_t index = 0) 106 { 107 for (auto &outputVar : outputVariables) 108 { 109 if (outputVar.outputLocation == location && outputVar.outputIndex == index) 110 { 111 return &outputVar; 112 } 113 } 114 115 return nullptr; 116 } 117 118 void WriteArrayString(std::ostringstream &strstr, unsigned int i) 119 { 120 static_assert(GL_INVALID_INDEX == UINT_MAX, 121 "GL_INVALID_INDEX must be equal to the max unsigned int."); 122 if (i == UINT_MAX) 123 { 124 return; 125 } 126 127 strstr << "["; 128 strstr << i; 129 strstr << "]"; 130 } 131 132 bool ReplaceShaderStorageDeclaration(const std::vector<ShaderStorageBlock> &shaderStorageBlocks, 133 std::string *hlsl, 134 size_t baseUAVRegister, 135 gl::ShaderType shaderType) 136 { 137 std::string ssboHeader; 138 std::ostringstream out(ssboHeader); 139 for (const ShaderStorageBlock &ssbo : shaderStorageBlocks) 140 { 141 size_t uavRegister = baseUAVRegister + ssbo.registerIndex; 142 std::string name = ssbo.name; 143 if (ssbo.arraySize > 0) 144 { 145 for (unsigned int arrayIndex = 0; arrayIndex < ssbo.arraySize; arrayIndex++) 146 { 147 out << "RWByteAddressBuffer " 148 << "dx_" << name << "_" << arrayIndex << ": register(u" 149 << uavRegister + arrayIndex << ");\n"; 150 } 151 } 152 else 153 { 154 out << "RWByteAddressBuffer " 155 << "_" << name << ": register(u" << uavRegister << ");\n"; 156 } 157 } 158 if (out.str().empty()) 159 { 160 return true; 161 } 162 return angle::ReplaceSubstring(hlsl, kShaderStorageDeclarationString, out.str()); 163 } 164 165 constexpr const char *VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; 166 constexpr const char *VERTEX_OUTPUT_STUB_STRING = "@@ VERTEX OUTPUT @@"; 167 constexpr const char *PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; 168 constexpr const char *PIXEL_MAIN_PARAMETERS_STUB_STRING = "@@ PIXEL MAIN PARAMETERS @@"; 169 constexpr const char *MAIN_PROLOGUE_STUB_STRING = "@@ MAIN PROLOGUE @@"; 170 } // anonymous namespace 171 172 // BuiltinInfo implementation 173 174 BuiltinInfo::BuiltinInfo() = default; 175 BuiltinInfo::~BuiltinInfo() = default; 176 177 // DynamicHLSL implementation 178 179 DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer) {} 180 181 std::string DynamicHLSL::generateVertexShaderForInputLayout( 182 const std::string &sourceShader, 183 const InputLayout &inputLayout, 184 const std::vector<sh::ShaderVariable> &shaderAttributes, 185 const std::vector<rx::ShaderStorageBlock> &shaderStorageBlocks, 186 size_t baseUAVRegister) const 187 { 188 std::ostringstream structStream; 189 std::ostringstream initStream; 190 191 structStream << "struct VS_INPUT\n" 192 << "{\n"; 193 194 int semanticIndex = 0; 195 unsigned int inputIndex = 0; 196 197 // If gl_PointSize is used in the shader then pointsprites rendering is expected. 198 // If the renderer does not support Geometry shaders then Instanced PointSprite emulation 199 // must be used. 200 bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos; 201 bool useInstancedPointSpriteEmulation = 202 usesPointSize && mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled; 203 204 // Instanced PointSprite emulation requires additional entries in the 205 // VS_INPUT structure to support the vertices that make up the quad vertices. 206 // These values must be in sync with the cooresponding values added during inputlayout creation 207 // in InputLayoutCache::applyVertexBuffers(). 208 // 209 // The additional entries must appear first in the VS_INPUT layout because 210 // Windows Phone 8 era devices require per vertex data to physically come 211 // before per instance data in the shader. 212 if (useInstancedPointSpriteEmulation) 213 { 214 structStream << " float3 spriteVertexPos : SPRITEPOSITION0;\n" 215 << " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; 216 } 217 218 for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex) 219 { 220 const sh::ShaderVariable &shaderAttribute = shaderAttributes[attributeIndex]; 221 if (!shaderAttribute.name.empty()) 222 { 223 ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); 224 angle::FormatID vertexFormatID = 225 inputIndex < inputLayout.size() ? inputLayout[inputIndex] : angle::FormatID::NONE; 226 227 // HLSL code for input structure 228 if (IsMatrixType(shaderAttribute.type)) 229 { 230 // Matrix types are always transposed 231 structStream << " " 232 << HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); 233 } 234 else 235 { 236 if (shaderAttribute.name == "gl_InstanceID" || 237 shaderAttribute.name == "gl_VertexID") 238 { 239 // The input types of the instance ID and vertex ID in HLSL (uint) differs from 240 // the ones in ESSL (int). 241 structStream << " uint"; 242 } 243 else 244 { 245 GLenum componentType = mRenderer->getVertexComponentType(vertexFormatID); 246 247 structStream << " "; 248 HLSLComponentTypeString(structStream, componentType, 249 VariableComponentCount(shaderAttribute.type)); 250 } 251 } 252 253 structStream << " " << DecorateVariable(shaderAttribute.name) << " : "; 254 255 if (shaderAttribute.name == "gl_InstanceID") 256 { 257 structStream << "SV_InstanceID"; 258 } 259 else if (shaderAttribute.name == "gl_VertexID") 260 { 261 structStream << "SV_VertexID"; 262 } 263 else 264 { 265 structStream << "TEXCOORD" << semanticIndex; 266 semanticIndex += VariableRegisterCount(shaderAttribute.type); 267 } 268 269 structStream << ";\n"; 270 271 // HLSL code for initialization 272 initStream << " " << DecorateVariable(shaderAttribute.name) << " = "; 273 274 // Mismatched vertex attribute to vertex input may result in an undefined 275 // data reinterpretation (eg for pure integer->float, float->pure integer) 276 // TODO: issue warning with gl debug info extension, when supported 277 if (IsMatrixType(shaderAttribute.type) || 278 (mRenderer->getVertexConversionType(vertexFormatID) & VERTEX_CONVERT_GPU) != 0) 279 { 280 GenerateAttributeConversionHLSL(vertexFormatID, shaderAttribute, initStream); 281 } 282 else 283 { 284 initStream << "input." << DecorateVariable(shaderAttribute.name); 285 } 286 287 if (shaderAttribute.name == "gl_VertexID") 288 { 289 // dx_VertexID contains the firstVertex offset 290 initStream << " + dx_VertexID"; 291 } 292 293 initStream << ";\n"; 294 295 inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type)); 296 } 297 } 298 299 structStream << "};\n" 300 "\n" 301 "void initAttributes(VS_INPUT input)\n" 302 "{\n" 303 << initStream.str() << "}\n"; 304 305 std::string vertexHLSL(sourceShader); 306 307 bool success = 308 angle::ReplaceSubstring(&vertexHLSL, VERTEX_ATTRIBUTE_STUB_STRING, structStream.str()); 309 ASSERT(success); 310 311 success = ReplaceShaderStorageDeclaration(shaderStorageBlocks, &vertexHLSL, baseUAVRegister, 312 gl::ShaderType::Vertex); 313 ASSERT(success); 314 315 return vertexHLSL; 316 } 317 318 std::string DynamicHLSL::generatePixelShaderForOutputSignature( 319 const std::string &sourceShader, 320 const std::vector<PixelShaderOutputVariable> &outputVariables, 321 bool usesFragDepth, 322 const std::vector<GLenum> &outputLayout, 323 const std::vector<ShaderStorageBlock> &shaderStorageBlocks, 324 size_t baseUAVRegister) const 325 { 326 const int shaderModel = mRenderer->getMajorShaderModel(); 327 std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR"; 328 std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; 329 330 std::ostringstream declarationStream; 331 std::ostringstream copyStream; 332 333 declarationStream << "struct PS_OUTPUT\n" 334 "{\n"; 335 336 size_t numOutputs = outputLayout.size(); 337 338 // Workaround for HLSL 3.x: We can't do a depth/stencil only render, the runtime will complain. 339 if (numOutputs == 0 && (shaderModel == 3 || !mRenderer->getShaderModelSuffix().empty())) 340 { 341 numOutputs = 1u; 342 } 343 const PixelShaderOutputVariable defaultOutput(GL_FLOAT_VEC4, "unused", "float4(0, 0, 0, 1)", 0, 344 0); 345 size_t outputIndex = 0; 346 347 for (size_t layoutIndex = 0; layoutIndex < numOutputs; ++layoutIndex) 348 { 349 GLenum binding = outputLayout.empty() ? GL_COLOR_ATTACHMENT0 : outputLayout[layoutIndex]; 350 351 if (binding != GL_NONE) 352 { 353 unsigned int location = (binding - GL_COLOR_ATTACHMENT0); 354 outputIndex = 355 layoutIndex > 0 && binding == outputLayout[layoutIndex - 1] ? outputIndex + 1 : 0; 356 357 const PixelShaderOutputVariable *outputVariable = 358 outputLayout.empty() ? &defaultOutput 359 : FindOutputAtLocation(outputVariables, location, outputIndex); 360 361 // OpenGL ES 3.0 spec $4.2.1 362 // If [...] not all user-defined output variables are written, the values of fragment 363 // colors corresponding to unwritten variables are similarly undefined. 364 if (outputVariable) 365 { 366 declarationStream << " "; 367 HLSLTypeString(declarationStream, outputVariable->type); 368 declarationStream << " " << outputVariable->name << " : " << targetSemantic 369 << static_cast<int>(layoutIndex) << ";\n"; 370 371 copyStream << " output." << outputVariable->name << " = " 372 << outputVariable->source << ";\n"; 373 } 374 } 375 } 376 377 if (usesFragDepth) 378 { 379 declarationStream << " float gl_Depth : " << depthSemantic << ";\n"; 380 copyStream << " output.gl_Depth = gl_Depth; \n"; 381 } 382 383 declarationStream << "};\n" 384 "\n" 385 "PS_OUTPUT generateOutput()\n" 386 "{\n" 387 " PS_OUTPUT output;\n" 388 << copyStream.str() 389 << " return output;\n" 390 "}\n"; 391 392 std::string pixelHLSL(sourceShader); 393 394 bool success = 395 angle::ReplaceSubstring(&pixelHLSL, PIXEL_OUTPUT_STUB_STRING, declarationStream.str()); 396 ASSERT(success); 397 398 success = ReplaceShaderStorageDeclaration(shaderStorageBlocks, &pixelHLSL, baseUAVRegister, 399 gl::ShaderType::Fragment); 400 ASSERT(success); 401 402 return pixelHLSL; 403 } 404 405 std::string DynamicHLSL::generateShaderForImage2DBindSignature( 406 ProgramD3D &programD3D, 407 const gl::ProgramState &programData, 408 gl::ShaderType shaderType, 409 const std::string &shaderHLSL, 410 std::vector<sh::ShaderVariable> &image2DUniforms, 411 const gl::ImageUnitTextureTypeMap &image2DBindLayout, 412 unsigned int baseUAVRegister) const 413 { 414 if (image2DUniforms.empty()) 415 { 416 return shaderHLSL; 417 } 418 419 return GenerateShaderForImage2DBindSignature(programD3D, programData, shaderType, shaderHLSL, 420 image2DUniforms, image2DBindLayout, 421 baseUAVRegister); 422 } 423 424 void DynamicHLSL::generateVaryingLinkHLSL(const VaryingPacking &varyingPacking, 425 const BuiltinInfo &builtins, 426 bool programUsesPointSize, 427 std::ostringstream &hlslStream) const 428 { 429 ASSERT(builtins.dxPosition.enabled); 430 hlslStream << "{\n" 431 << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n"; 432 433 if (builtins.glPosition.enabled) 434 { 435 hlslStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n"; 436 } 437 438 if (builtins.glFragCoord.enabled) 439 { 440 hlslStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n"; 441 } 442 443 if (builtins.glPointCoord.enabled) 444 { 445 hlslStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n"; 446 } 447 448 if (builtins.glPointSize.enabled) 449 { 450 hlslStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n"; 451 } 452 453 if (builtins.glViewIDOVR.enabled) 454 { 455 hlslStream << " nointerpolation uint gl_ViewID_OVR : " << builtins.glViewIDOVR.str() 456 << ";\n"; 457 } 458 459 std::string varyingSemantic = 460 GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize); 461 462 const auto ®isterInfos = varyingPacking.getRegisterList(); 463 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex) 464 { 465 const PackedVaryingRegister ®isterInfo = registerInfos[registerIndex]; 466 const auto &varying = registerInfo.packedVarying->varying(); 467 ASSERT(!varying.isStruct()); 468 469 // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many 470 // registers being used. 471 // For example, if there are N registers, and we have N vec3 varyings and 1 float 472 // varying, then D3D will pack them into N registers. 473 // If the float varying has the 'nointerpolation' modifier on it then we would need 474 // N + 1 registers, and D3D compilation will fail. 475 476 switch (registerInfo.packedVarying->interpolation) 477 { 478 case sh::INTERPOLATION_SMOOTH: 479 hlslStream << " "; 480 break; 481 case sh::INTERPOLATION_FLAT: 482 hlslStream << " nointerpolation "; 483 break; 484 case sh::INTERPOLATION_CENTROID: 485 hlslStream << " centroid "; 486 break; 487 case sh::INTERPOLATION_SAMPLE: 488 hlslStream << " sample "; 489 break; 490 default: 491 UNREACHABLE(); 492 } 493 494 GLenum transposedType = gl::TransposeMatrixType(varying.type); 495 GLenum componentType = gl::VariableComponentType(transposedType); 496 int columnCount = gl::VariableColumnCount(transposedType); 497 HLSLComponentTypeString(hlslStream, componentType, columnCount); 498 hlslStream << " v" << registerIndex << " : " << varyingSemantic << registerIndex << ";\n"; 499 } 500 501 // Note that the following outputs need to be declared after the others. They are not included 502 // in pixel shader inputs even when they are in vertex/geometry shader outputs, and the pixel 503 // shader input struct must be a prefix of the vertex/geometry shader output struct. 504 505 if (builtins.glViewportIndex.enabled) 506 { 507 hlslStream << " nointerpolation uint gl_ViewportIndex : " 508 << builtins.glViewportIndex.str() << ";\n"; 509 } 510 511 if (builtins.glLayer.enabled) 512 { 513 hlslStream << " nointerpolation uint gl_Layer : " << builtins.glLayer.str() << ";\n"; 514 } 515 516 hlslStream << "};\n"; 517 } 518 519 void DynamicHLSL::generateShaderLinkHLSL(const gl::Context *context, 520 const gl::Caps &caps, 521 const gl::ProgramState &programData, 522 const ProgramD3DMetadata &programMetadata, 523 const VaryingPacking &varyingPacking, 524 const BuiltinVaryingsD3D &builtinsD3D, 525 gl::ShaderMap<std::string> *shaderHLSL) const 526 { 527 ASSERT(shaderHLSL); 528 ASSERT((*shaderHLSL)[gl::ShaderType::Vertex].empty() && 529 (*shaderHLSL)[gl::ShaderType::Fragment].empty()); 530 531 gl::Shader *vertexShaderGL = programData.getAttachedShader(ShaderType::Vertex); 532 gl::Shader *fragmentShaderGL = programData.getAttachedShader(ShaderType::Fragment); 533 const int shaderModel = mRenderer->getMajorShaderModel(); 534 535 const ShaderD3D *fragmentShader = nullptr; 536 if (fragmentShaderGL) 537 { 538 fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL); 539 } 540 541 // usesViewScale() isn't supported in the D3D9 renderer 542 ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale()); 543 544 bool useInstancedPointSpriteEmulation = 545 programMetadata.usesPointSize() && 546 mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled; 547 548 // Validation done in the compiler 549 ASSERT(!fragmentShader || !fragmentShader->usesFragColor() || !fragmentShader->usesFragData()); 550 551 std::ostringstream vertexStream; 552 vertexStream << "struct VS_OUTPUT\n"; 553 const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex]; 554 generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(), 555 vertexStream); 556 557 // Instanced PointSprite emulation requires additional entries originally generated in the 558 // GeometryShader HLSL. These include pointsize clamp values. 559 if (useInstancedPointSpriteEmulation) 560 { 561 vertexStream << "static float minPointSize = " << static_cast<int>(caps.minAliasedPointSize) 562 << ".0f;\n" 563 << "static float maxPointSize = " << static_cast<int>(caps.maxAliasedPointSize) 564 << ".0f;\n"; 565 } 566 567 std::ostringstream vertexGenerateOutput; 568 vertexGenerateOutput << "VS_OUTPUT generateOutput(VS_INPUT input)\n" 569 << "{\n" 570 << " VS_OUTPUT output;\n"; 571 572 if (vertexBuiltins.glPosition.enabled) 573 { 574 vertexGenerateOutput << " output.gl_Position = gl_Position;\n"; 575 } 576 577 if (vertexBuiltins.glViewIDOVR.enabled) 578 { 579 vertexGenerateOutput << " output.gl_ViewID_OVR = ViewID_OVR;\n"; 580 } 581 if (programMetadata.hasANGLEMultiviewEnabled() && programMetadata.canSelectViewInVertexShader()) 582 { 583 ASSERT(vertexBuiltins.glViewportIndex.enabled && vertexBuiltins.glLayer.enabled); 584 vertexGenerateOutput << " if (multiviewSelectViewportIndex)\n" 585 << " {\n" 586 << " output.gl_ViewportIndex = ViewID_OVR;\n" 587 << " } else {\n" 588 << " output.gl_ViewportIndex = 0;\n" 589 << " output.gl_Layer = ViewID_OVR;\n" 590 << " }\n"; 591 } 592 593 // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust. 594 if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") 595 { 596 vertexGenerateOutput << " output.dx_Position.x = gl_Position.x;\n"; 597 598 if (programMetadata.usesViewScale()) 599 { 600 // This code assumes that dx_ViewScale.y = -1.0f when rendering to texture, and +1.0f 601 // when rendering to the default framebuffer. No other values are valid. 602 vertexGenerateOutput << " output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n"; 603 } 604 else 605 { 606 vertexGenerateOutput 607 << " output.dx_Position.y = clipControlOrigin * gl_Position.y;\n"; 608 } 609 610 vertexGenerateOutput 611 << " if (clipControlZeroToOne)\n" 612 << " {\n" 613 << " output.dx_Position.z = gl_Position.z;\n" 614 << " } else {\n" 615 << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" 616 << " }\n"; 617 618 vertexGenerateOutput << " output.dx_Position.w = gl_Position.w;\n"; 619 } 620 else 621 { 622 vertexGenerateOutput << " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + " 623 "dx_ViewAdjust.x * gl_Position.w;\n"; 624 625 // If usesViewScale() is true and we're using the D3D11 renderer via Feature Level 9_*, 626 // then we need to multiply the gl_Position.y by the viewScale. 627 // usesViewScale() isn't supported when using the D3D9 renderer. 628 if (programMetadata.usesViewScale() && 629 (shaderModel >= 4 && mRenderer->getShaderModelSuffix() != "")) 630 { 631 vertexGenerateOutput << " output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * " 632 "dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"; 633 } 634 else 635 { 636 vertexGenerateOutput << " output.dx_Position.y = clipControlOrigin * (gl_Position.y " 637 "* dx_ViewAdjust.w + " 638 "dx_ViewAdjust.y * gl_Position.w);\n"; 639 } 640 641 vertexGenerateOutput 642 << " if (clipControlZeroToOne)\n" 643 << " {\n" 644 << " output.dx_Position.z = gl_Position.z;\n" 645 << " } else {\n" 646 << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" 647 << " }\n"; 648 649 vertexGenerateOutput << " output.dx_Position.w = gl_Position.w;\n"; 650 } 651 652 // We don't need to output gl_PointSize if we use are emulating point sprites via instancing. 653 if (vertexBuiltins.glPointSize.enabled) 654 { 655 vertexGenerateOutput << " output.gl_PointSize = gl_PointSize;\n"; 656 } 657 658 if (vertexBuiltins.glFragCoord.enabled) 659 { 660 vertexGenerateOutput << " output.gl_FragCoord = gl_Position;\n"; 661 } 662 663 const auto ®isterInfos = varyingPacking.getRegisterList(); 664 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex) 665 { 666 const PackedVaryingRegister ®isterInfo = registerInfos[registerIndex]; 667 const auto &packedVarying = *registerInfo.packedVarying; 668 const auto &varying = *packedVarying.frontVarying.varying; 669 ASSERT(!varying.isStruct()); 670 671 vertexGenerateOutput << " output.v" << registerIndex << " = "; 672 673 if (packedVarying.isStructField()) 674 { 675 vertexGenerateOutput << DecorateVariable(packedVarying.frontVarying.parentStructName) 676 << "."; 677 } 678 679 vertexGenerateOutput << DecorateVariable(varying.name); 680 681 if (varying.isArray()) 682 { 683 WriteArrayString(vertexGenerateOutput, registerInfo.varyingArrayIndex); 684 } 685 686 if (VariableRowCount(varying.type) > 1) 687 { 688 WriteArrayString(vertexGenerateOutput, registerInfo.varyingRowIndex); 689 } 690 691 vertexGenerateOutput << ";\n"; 692 } 693 694 // Instanced PointSprite emulation requires additional entries to calculate 695 // the final output vertex positions of the quad that represents each sprite. 696 if (useInstancedPointSpriteEmulation) 697 { 698 vertexGenerateOutput 699 << "\n" 700 << " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n"; 701 702 vertexGenerateOutput 703 << " output.dx_Position.x += (input.spriteVertexPos.x * gl_PointSize / " 704 "(dx_ViewCoords.x*2)) * output.dx_Position.w;"; 705 706 if (programMetadata.usesViewScale()) 707 { 708 // Multiply by ViewScale to invert the rendering when appropriate 709 vertexGenerateOutput 710 << " output.dx_Position.y += (-dx_ViewScale.y * " 711 "input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2)) * " 712 "output.dx_Position.w;"; 713 } 714 else 715 { 716 vertexGenerateOutput 717 << " output.dx_Position.y += (input.spriteVertexPos.y * gl_PointSize / " 718 "(dx_ViewCoords.y*2)) * output.dx_Position.w;"; 719 } 720 721 vertexGenerateOutput 722 << " output.dx_Position.z += input.spriteVertexPos.z * output.dx_Position.w;\n"; 723 724 if (programMetadata.usesPointCoord()) 725 { 726 vertexGenerateOutput << "\n" 727 << " output.gl_PointCoord = input.spriteTexCoord;\n"; 728 } 729 } 730 731 // Renderers that enable instanced pointsprite emulation require the vertex shader output member 732 // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same 733 // default value used in the generated pixel shader. 734 if (programMetadata.usesInsertedPointCoordValue()) 735 { 736 ASSERT(!useInstancedPointSpriteEmulation); 737 vertexGenerateOutput << "\n" 738 << " output.gl_PointCoord = float2(0.5, 0.5);\n"; 739 } 740 741 vertexGenerateOutput << "\n" 742 << " return output;\n" 743 << "}"; 744 745 if (vertexShaderGL) 746 { 747 std::string vertexSource = vertexShaderGL->getTranslatedSource(context); 748 angle::ReplaceSubstring(&vertexSource, std::string(MAIN_PROLOGUE_STUB_STRING), 749 " initAttributes(input);\n"); 750 angle::ReplaceSubstring(&vertexSource, std::string(VERTEX_OUTPUT_STUB_STRING), 751 vertexGenerateOutput.str()); 752 vertexStream << vertexSource; 753 } 754 755 const auto &pixelBuiltins = builtinsD3D[gl::ShaderType::Fragment]; 756 757 std::ostringstream pixelStream; 758 pixelStream << "struct PS_INPUT\n"; 759 generateVaryingLinkHLSL(varyingPacking, pixelBuiltins, builtinsD3D.usesPointSize(), 760 pixelStream); 761 pixelStream << "\n"; 762 763 std::ostringstream pixelPrologue; 764 if (fragmentShader && fragmentShader->usesViewID()) 765 { 766 ASSERT(pixelBuiltins.glViewIDOVR.enabled); 767 pixelPrologue << " ViewID_OVR = input.gl_ViewID_OVR;\n"; 768 } 769 770 if (pixelBuiltins.glFragCoord.enabled) 771 { 772 pixelPrologue << " float rhw = 1.0 / input.gl_FragCoord.w;\n"; 773 774 // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader. 775 // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using 776 // dx_ViewCoords. 777 // DComp usually gives us an offset at (0, 0), but this is not always the case. It is 778 // valid for DComp to give us an offset into the texture atlas. In that scenario, we 779 // need to offset gl_FragCoord using dx_FragCoordOffset to point to the correct location 780 // of the pixel. 781 if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") 782 { 783 pixelPrologue << " gl_FragCoord.x = input.dx_Position.x - dx_FragCoordOffset.x;\n" 784 << " gl_FragCoord.y = input.dx_Position.y - dx_FragCoordOffset.y;\n"; 785 } 786 else if (shaderModel == 3) 787 { 788 pixelPrologue 789 << " gl_FragCoord.x = input.dx_Position.x + 0.5 - dx_FragCoordOffset.x;\n" 790 << " gl_FragCoord.y = input.dx_Position.y + 0.5 - dx_FragCoordOffset.y;\n"; 791 } 792 else 793 { 794 // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See 795 // Renderer::setViewport() 796 pixelPrologue 797 << " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + " 798 "dx_ViewCoords.z - dx_FragCoordOffset.x;\n" 799 << " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + " 800 "dx_ViewCoords.w - dx_FragCoordOffset.y;\n"; 801 } 802 803 if (programMetadata.usesViewScale()) 804 { 805 // For Feature Level 9_3 and below, we need to correct gl_FragCoord.y to account 806 // for dx_ViewScale. On Feature Level 10_0+, gl_FragCoord.y is calculated above using 807 // dx_ViewCoords and is always correct irrespective of dx_ViewScale's value. 808 // NOTE: usesViewScale() can only be true on D3D11 (i.e. Shader Model 4.0+). 809 if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") 810 { 811 // Some assumptions: 812 // - dx_ViewScale.y = -1.0f when rendering to texture 813 // - dx_ViewScale.y = +1.0f when rendering to the default framebuffer 814 // - gl_FragCoord.y has been set correctly above. 815 // 816 // When rendering to the backbuffer, the code inverts gl_FragCoord's y coordinate. 817 // This involves subtracting the y coordinate from the height of the area being 818 // rendered to. 819 // 820 // First we calculate the height of the area being rendered to: 821 // render_area_height = (2.0f / (1.0f - input.gl_FragCoord.y * rhw)) * 822 // gl_FragCoord.y 823 // 824 // Note that when we're rendering to default FB, we want our output to be 825 // equivalent to: 826 // "gl_FragCoord.y = render_area_height - gl_FragCoord.y" 827 // 828 // When we're rendering to a texture, we want our output to be equivalent to: 829 // "gl_FragCoord.y = gl_FragCoord.y;" 830 // 831 // If we set scale_factor = ((1.0f + dx_ViewScale.y) / 2.0f), then notice that 832 // - When rendering to default FB: scale_factor = 1.0f 833 // - When rendering to texture: scale_factor = 0.0f 834 // 835 // Therefore, we can get our desired output by setting: 836 // "gl_FragCoord.y = scale_factor * render_area_height - dx_ViewScale.y * 837 // gl_FragCoord.y" 838 // 839 // Simplifying, this becomes: 840 pixelPrologue 841 << " gl_FragCoord.y = (1.0f + dx_ViewScale.y) * gl_FragCoord.y /" 842 "(1.0f - input.gl_FragCoord.y * rhw) - dx_ViewScale.y * gl_FragCoord.y;\n"; 843 } 844 } 845 846 pixelPrologue << " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + " 847 "dx_DepthFront.y;\n" 848 << " gl_FragCoord.w = rhw;\n"; 849 } 850 851 if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3) 852 { 853 pixelPrologue << " gl_PointCoord.x = input.gl_PointCoord.x;\n" 854 << " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; 855 } 856 857 if (fragmentShader && fragmentShader->usesFrontFacing()) 858 { 859 if (shaderModel <= 3) 860 { 861 pixelPrologue << " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; 862 } 863 else 864 { 865 pixelPrologue << " gl_FrontFacing = isFrontFace;\n"; 866 } 867 } 868 869 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex) 870 { 871 const PackedVaryingRegister ®isterInfo = registerInfos[registerIndex]; 872 const auto &packedVarying = *registerInfo.packedVarying; 873 874 // Don't reference VS-only transform feedback varyings in the PS. 875 if (packedVarying.vertexOnly()) 876 { 877 continue; 878 } 879 880 const auto &varying = *packedVarying.backVarying.varying; 881 ASSERT(!varying.isBuiltIn() && !varying.isStruct()); 882 883 // Note that we're relying on that the active flag is set according to usage in the fragment 884 // shader. 885 if (!varying.active) 886 { 887 continue; 888 } 889 890 pixelPrologue << " "; 891 892 if (packedVarying.isStructField()) 893 { 894 pixelPrologue << DecorateVariable(packedVarying.backVarying.parentStructName) << "."; 895 } 896 897 pixelPrologue << DecorateVariable(varying.name); 898 899 if (varying.isArray()) 900 { 901 WriteArrayString(pixelPrologue, registerInfo.varyingArrayIndex); 902 } 903 904 GLenum transposedType = TransposeMatrixType(varying.type); 905 if (VariableRowCount(transposedType) > 1) 906 { 907 WriteArrayString(pixelPrologue, registerInfo.varyingRowIndex); 908 } 909 910 pixelPrologue << " = input.v" << registerIndex; 911 912 switch (VariableColumnCount(transposedType)) 913 { 914 case 1: 915 pixelPrologue << ".x"; 916 break; 917 case 2: 918 pixelPrologue << ".xy"; 919 break; 920 case 3: 921 pixelPrologue << ".xyz"; 922 break; 923 case 4: 924 break; 925 default: 926 UNREACHABLE(); 927 } 928 pixelPrologue << ";\n"; 929 } 930 931 if (fragmentShaderGL) 932 { 933 std::string pixelSource = fragmentShaderGL->getTranslatedSource(context); 934 935 if (fragmentShader->usesFrontFacing()) 936 { 937 if (shaderModel >= 4) 938 { 939 angle::ReplaceSubstring(&pixelSource, 940 std::string(PIXEL_MAIN_PARAMETERS_STUB_STRING), 941 "PS_INPUT input, bool isFrontFace : SV_IsFrontFace"); 942 } 943 else 944 { 945 angle::ReplaceSubstring(&pixelSource, 946 std::string(PIXEL_MAIN_PARAMETERS_STUB_STRING), 947 "PS_INPUT input, float vFace : VFACE"); 948 } 949 } 950 else 951 { 952 angle::ReplaceSubstring(&pixelSource, std::string(PIXEL_MAIN_PARAMETERS_STUB_STRING), 953 "PS_INPUT input"); 954 } 955 956 angle::ReplaceSubstring(&pixelSource, std::string(MAIN_PROLOGUE_STUB_STRING), 957 pixelPrologue.str()); 958 pixelStream << pixelSource; 959 } 960 961 (*shaderHLSL)[gl::ShaderType::Vertex] = vertexStream.str(); 962 (*shaderHLSL)[gl::ShaderType::Fragment] = pixelStream.str(); 963 } 964 965 std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking, 966 const BuiltinVaryingsD3D &builtinsD3D, 967 const bool hasANGLEMultiviewEnabled, 968 const bool selectViewInVS) const 969 { 970 ASSERT(mRenderer->getMajorShaderModel() >= 4); 971 972 std::ostringstream preambleStream; 973 974 const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex]; 975 976 preambleStream << "struct GS_INPUT\n"; 977 generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(), 978 preambleStream); 979 preambleStream << "\n" 980 << "struct GS_OUTPUT\n"; 981 generateVaryingLinkHLSL(varyingPacking, builtinsD3D[gl::ShaderType::Geometry], 982 builtinsD3D.usesPointSize(), preambleStream); 983 preambleStream 984 << "\n" 985 << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n" 986 << "{\n" 987 << " output.gl_Position = input.gl_Position;\n"; 988 989 if (vertexBuiltins.glPointSize.enabled) 990 { 991 preambleStream << " output.gl_PointSize = input.gl_PointSize;\n"; 992 } 993 994 if (hasANGLEMultiviewEnabled) 995 { 996 preambleStream << " output.gl_ViewID_OVR = input.gl_ViewID_OVR;\n"; 997 if (selectViewInVS) 998 { 999 ASSERT(builtinsD3D[gl::ShaderType::Geometry].glViewportIndex.enabled && 1000 builtinsD3D[gl::ShaderType::Geometry].glLayer.enabled); 1001 1002 // If the view is already selected in the VS, then we just pass the gl_ViewportIndex and 1003 // gl_Layer to the output. 1004 preambleStream << " output.gl_ViewportIndex = input.gl_ViewportIndex;\n" 1005 << " output.gl_Layer = input.gl_Layer;\n"; 1006 } 1007 } 1008 1009 const auto ®isterInfos = varyingPacking.getRegisterList(); 1010 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex) 1011 { 1012 const PackedVaryingRegister &varyingRegister = registerInfos[registerIndex]; 1013 preambleStream << " output.v" << registerIndex << " = "; 1014 if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT) 1015 { 1016 preambleStream << "flat"; 1017 } 1018 preambleStream << "input.v" << registerIndex << "; \n"; 1019 } 1020 1021 if (vertexBuiltins.glFragCoord.enabled) 1022 { 1023 preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n"; 1024 } 1025 1026 // Only write the dx_Position if we aren't using point sprites 1027 preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n" 1028 << " output.dx_Position = input.dx_Position;\n" 1029 << "#endif // ANGLE_POINT_SPRITE_SHADER\n" 1030 << "}\n"; 1031 1032 if (hasANGLEMultiviewEnabled && !selectViewInVS) 1033 { 1034 ASSERT(builtinsD3D[gl::ShaderType::Geometry].glViewportIndex.enabled && 1035 builtinsD3D[gl::ShaderType::Geometry].glLayer.enabled); 1036 1037 // According to the HLSL reference, using SV_RenderTargetArrayIndex is only valid if the 1038 // render target is an array resource. Because of this we do not write to gl_Layer if we are 1039 // taking the side-by-side code path. We still select the viewport index in the layered code 1040 // path as that is always valid. See: 1041 // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647(v=vs.85).aspx 1042 preambleStream << "\n" 1043 << "void selectView(inout GS_OUTPUT output, GS_INPUT input)\n" 1044 << "{\n" 1045 << " if (multiviewSelectViewportIndex)\n" 1046 << " {\n" 1047 << " output.gl_ViewportIndex = input.gl_ViewID_OVR;\n" 1048 << " } else {\n" 1049 << " output.gl_ViewportIndex = 0;\n" 1050 << " output.gl_Layer = input.gl_ViewID_OVR;\n" 1051 << " }\n" 1052 << "}\n"; 1053 } 1054 1055 return preambleStream.str(); 1056 } 1057 1058 std::string DynamicHLSL::generateGeometryShaderHLSL(const gl::Caps &caps, 1059 gl::PrimitiveMode primitiveType, 1060 const gl::ProgramState &programData, 1061 const bool useViewScale, 1062 const bool hasANGLEMultiviewEnabled, 1063 const bool selectViewInVS, 1064 const bool pointSpriteEmulation, 1065 const std::string &preambleString) const 1066 { 1067 ASSERT(mRenderer->getMajorShaderModel() >= 4); 1068 1069 std::stringstream shaderStream; 1070 1071 const bool pointSprites = (primitiveType == gl::PrimitiveMode::Points) && pointSpriteEmulation; 1072 const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos; 1073 1074 const char *inputPT = nullptr; 1075 const char *outputPT = nullptr; 1076 int inputSize = 0; 1077 int maxVertexOutput = 0; 1078 1079 switch (primitiveType) 1080 { 1081 case gl::PrimitiveMode::Points: 1082 inputPT = "point"; 1083 inputSize = 1; 1084 1085 if (pointSprites) 1086 { 1087 outputPT = "Triangle"; 1088 maxVertexOutput = 4; 1089 } 1090 else 1091 { 1092 outputPT = "Point"; 1093 maxVertexOutput = 1; 1094 } 1095 1096 break; 1097 1098 case gl::PrimitiveMode::Lines: 1099 case gl::PrimitiveMode::LineStrip: 1100 case gl::PrimitiveMode::LineLoop: 1101 inputPT = "line"; 1102 outputPT = "Line"; 1103 inputSize = 2; 1104 maxVertexOutput = 2; 1105 break; 1106 1107 case gl::PrimitiveMode::Triangles: 1108 case gl::PrimitiveMode::TriangleStrip: 1109 case gl::PrimitiveMode::TriangleFan: 1110 inputPT = "triangle"; 1111 outputPT = "Triangle"; 1112 inputSize = 3; 1113 maxVertexOutput = 3; 1114 break; 1115 1116 default: 1117 UNREACHABLE(); 1118 break; 1119 } 1120 1121 if (pointSprites || hasANGLEMultiviewEnabled) 1122 { 1123 shaderStream << "cbuffer DriverConstants : register(b0)\n" 1124 "{\n"; 1125 1126 if (pointSprites) 1127 { 1128 shaderStream << " float4 dx_ViewCoords : packoffset(c1);\n"; 1129 if (useViewScale) 1130 { 1131 shaderStream << " float2 dx_ViewScale : packoffset(c3.z);\n"; 1132 } 1133 } 1134 1135 if (hasANGLEMultiviewEnabled) 1136 { 1137 // We have to add a value which we can use to keep track of which multi-view code path 1138 // is to be selected in the GS. 1139 shaderStream << " float multiviewSelectViewportIndex : packoffset(c4.x);\n"; 1140 } 1141 1142 shaderStream << "};\n\n"; 1143 } 1144 1145 if (pointSprites) 1146 { 1147 shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n" 1148 "\n" 1149 "static float2 pointSpriteCorners[] = \n" 1150 "{\n" 1151 " float2( 0.5f, -0.5f),\n" 1152 " float2( 0.5f, 0.5f),\n" 1153 " float2(-0.5f, -0.5f),\n" 1154 " float2(-0.5f, 0.5f)\n" 1155 "};\n" 1156 "\n" 1157 "static float2 pointSpriteTexcoords[] = \n" 1158 "{\n" 1159 " float2(1.0f, 1.0f),\n" 1160 " float2(1.0f, 0.0f),\n" 1161 " float2(0.0f, 1.0f),\n" 1162 " float2(0.0f, 0.0f)\n" 1163 "};\n" 1164 "\n" 1165 "static float minPointSize = " 1166 << static_cast<int>(caps.minAliasedPointSize) 1167 << ".0f;\n" 1168 "static float maxPointSize = " 1169 << static_cast<int>(caps.maxAliasedPointSize) << ".0f;\n" 1170 << "\n"; 1171 } 1172 1173 shaderStream << preambleString << "\n" 1174 << "[maxvertexcount(" << maxVertexOutput << ")]\n" 1175 << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], "; 1176 1177 if (primitiveType == gl::PrimitiveMode::TriangleStrip) 1178 { 1179 shaderStream << "uint primitiveID : SV_PrimitiveID, "; 1180 } 1181 1182 shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n" 1183 << "{\n" 1184 << " GS_OUTPUT output = (GS_OUTPUT)0;\n"; 1185 1186 if (primitiveType == gl::PrimitiveMode::TriangleStrip) 1187 { 1188 shaderStream << " uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n"; 1189 } 1190 else 1191 { 1192 shaderStream << " uint lastVertexIndex = " << (inputSize - 1) << ";\n"; 1193 } 1194 1195 for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex) 1196 { 1197 shaderStream << " copyVertex(output, input[" << vertexIndex 1198 << "], input[lastVertexIndex]);\n"; 1199 if (hasANGLEMultiviewEnabled && !selectViewInVS) 1200 { 1201 shaderStream << " selectView(output, input[" << vertexIndex << "]);\n"; 1202 } 1203 if (!pointSprites) 1204 { 1205 ASSERT(inputSize == maxVertexOutput); 1206 shaderStream << " outStream.Append(output);\n"; 1207 } 1208 } 1209 1210 if (pointSprites) 1211 { 1212 shaderStream << "\n" 1213 " float4 dx_Position = input[0].dx_Position;\n" 1214 " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, " 1215 "maxPointSize);\n" 1216 " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / " 1217 "dx_ViewCoords.y) * dx_Position.w;\n"; 1218 1219 for (int corner = 0; corner < 4; corner++) 1220 { 1221 if (useViewScale) 1222 { 1223 shaderStream << " \n" 1224 " output.dx_Position = dx_Position + float4(1.0f, " 1225 "-dx_ViewScale.y, 1.0f, 1.0f)" 1226 " * float4(pointSpriteCorners[" 1227 << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; 1228 } 1229 else 1230 { 1231 shaderStream << "\n" 1232 " output.dx_Position = dx_Position + float4(pointSpriteCorners[" 1233 << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; 1234 } 1235 1236 if (usesPointCoord) 1237 { 1238 shaderStream << " output.gl_PointCoord = pointSpriteTexcoords[" << corner 1239 << "];\n"; 1240 } 1241 1242 shaderStream << " outStream.Append(output);\n"; 1243 } 1244 } 1245 1246 shaderStream << " \n" 1247 " outStream.RestartStrip();\n" 1248 "}\n"; 1249 1250 return shaderStream.str(); 1251 } 1252 1253 // static 1254 void DynamicHLSL::GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID, 1255 const sh::ShaderVariable &shaderAttrib, 1256 std::ostringstream &outStream) 1257 { 1258 // Matrix 1259 if (IsMatrixType(shaderAttrib.type)) 1260 { 1261 outStream << "transpose(input." << DecorateVariable(shaderAttrib.name) << ")"; 1262 return; 1263 } 1264 1265 GLenum shaderComponentType = VariableComponentType(shaderAttrib.type); 1266 int shaderComponentCount = VariableComponentCount(shaderAttrib.type); 1267 const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(vertexFormatID); 1268 1269 // Perform integer to float conversion (if necessary) 1270 if (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT) 1271 { 1272 // TODO: normalization for 32-bit integer formats 1273 ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger); 1274 outStream << "float" << shaderComponentCount << "(input." 1275 << DecorateVariable(shaderAttrib.name) << ")"; 1276 return; 1277 } 1278 1279 // No conversion necessary 1280 outStream << "input." << DecorateVariable(shaderAttrib.name); 1281 } 1282 1283 void DynamicHLSL::getPixelShaderOutputKey(const gl::State &data, 1284 const gl::ProgramState &programData, 1285 const ProgramD3DMetadata &metadata, 1286 std::vector<PixelShaderOutputVariable> *outPixelShaderKey) 1287 { 1288 // Two cases when writing to gl_FragColor and using ESSL 1.0: 1289 // - with a 3.0 context, the output color is copied to channel 0 1290 // - with a 2.0 context, the output color is broadcast to all channels 1291 bool broadcast = metadata.usesBroadcast(data); 1292 const unsigned int numRenderTargets = 1293 (broadcast || metadata.usesMultipleFragmentOuts() 1294 ? static_cast<unsigned int>(data.getCaps().maxDrawBuffers) 1295 : 1); 1296 1297 if (!metadata.usesCustomOutVars()) 1298 { 1299 for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; 1300 renderTargetIndex++) 1301 { 1302 PixelShaderOutputVariable outputKeyVariable; 1303 outputKeyVariable.type = GL_FLOAT_VEC4; 1304 outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); 1305 outputKeyVariable.source = 1306 broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; 1307 outputKeyVariable.outputLocation = renderTargetIndex; 1308 1309 outPixelShaderKey->push_back(outputKeyVariable); 1310 } 1311 1312 if (metadata.usesSecondaryColor()) 1313 { 1314 for (unsigned int secondaryIndex = 0; 1315 secondaryIndex < data.getCaps().maxDualSourceDrawBuffers; secondaryIndex++) 1316 { 1317 PixelShaderOutputVariable outputKeyVariable; 1318 outputKeyVariable.type = GL_FLOAT_VEC4; 1319 outputKeyVariable.name = "gl_SecondaryColor" + Str(secondaryIndex); 1320 outputKeyVariable.source = "gl_SecondaryColor[" + Str(secondaryIndex) + "]"; 1321 outputKeyVariable.outputLocation = secondaryIndex; 1322 outputKeyVariable.outputIndex = 1; 1323 1324 outPixelShaderKey->push_back(outputKeyVariable); 1325 } 1326 } 1327 } 1328 else 1329 { 1330 const ShaderD3D *fragmentShader = metadata.getFragmentShader(); 1331 1332 if (!fragmentShader) 1333 { 1334 return; 1335 } 1336 1337 const auto &shaderOutputVars = fragmentShader->getState().getActiveOutputVariables(); 1338 1339 for (size_t outputLocationIndex = 0u; 1340 outputLocationIndex < programData.getOutputLocations().size(); ++outputLocationIndex) 1341 { 1342 const VariableLocation &outputLocation = 1343 programData.getOutputLocations().at(outputLocationIndex); 1344 if (!outputLocation.used()) 1345 { 1346 continue; 1347 } 1348 const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; 1349 const std::string &variableName = "out_" + outputVariable.name; 1350 1351 // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6. 1352 const std::string &elementString = 1353 (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : ""); 1354 1355 ASSERT(outputVariable.active); 1356 1357 PixelShaderOutputVariable outputKeyVariable; 1358 outputKeyVariable.type = outputVariable.type; 1359 outputKeyVariable.name = variableName + elementString; 1360 outputKeyVariable.source = 1361 variableName + 1362 (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : ""); 1363 outputKeyVariable.outputLocation = outputLocationIndex; 1364 1365 outPixelShaderKey->push_back(outputKeyVariable); 1366 } 1367 1368 // Now generate any secondary outputs... 1369 for (size_t outputLocationIndex = 0u; 1370 outputLocationIndex < programData.getSecondaryOutputLocations().size(); 1371 ++outputLocationIndex) 1372 { 1373 const VariableLocation &outputLocation = 1374 programData.getSecondaryOutputLocations().at(outputLocationIndex); 1375 if (!outputLocation.used()) 1376 { 1377 continue; 1378 } 1379 const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; 1380 const std::string &variableName = "out_" + outputVariable.name; 1381 1382 // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6. 1383 const std::string &elementString = 1384 (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : ""); 1385 1386 ASSERT(outputVariable.active); 1387 1388 PixelShaderOutputVariable outputKeyVariable; 1389 outputKeyVariable.type = outputVariable.type; 1390 outputKeyVariable.name = variableName + elementString; 1391 outputKeyVariable.source = 1392 variableName + 1393 (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : ""); 1394 outputKeyVariable.outputLocation = outputLocationIndex; 1395 outputKeyVariable.outputIndex = 1; 1396 1397 outPixelShaderKey->push_back(outputKeyVariable); 1398 } 1399 } 1400 } 1401 1402 // BuiltinVarying Implementation. 1403 BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false) {} 1404 1405 std::string BuiltinVarying::str() const 1406 { 1407 return (systemValue ? semantic : (semantic + Str(index))); 1408 } 1409 1410 void BuiltinVarying::enableSystem(const std::string &systemValueSemantic) 1411 { 1412 enabled = true; 1413 semantic = systemValueSemantic; 1414 systemValue = true; 1415 } 1416 1417 void BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal) 1418 { 1419 enabled = true; 1420 semantic = semanticVal; 1421 index = indexVal; 1422 } 1423 1424 // BuiltinVaryingsD3D Implementation. 1425 BuiltinVaryingsD3D::BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata, 1426 const VaryingPacking &packing) 1427 { 1428 updateBuiltins(gl::ShaderType::Vertex, metadata, packing); 1429 updateBuiltins(gl::ShaderType::Fragment, metadata, packing); 1430 int shaderModel = metadata.getRendererMajorShaderModel(); 1431 if (shaderModel >= 4) 1432 { 1433 updateBuiltins(gl::ShaderType::Geometry, metadata, packing); 1434 } 1435 // In shader model >= 4, some builtins need to be the same in vertex and pixel shaders - input 1436 // struct needs to be a prefix of output struct. 1437 ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPosition.enabled == 1438 mBuiltinInfo[gl::ShaderType::Fragment].glPosition.enabled); 1439 ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glFragCoord.enabled == 1440 mBuiltinInfo[gl::ShaderType::Fragment].glFragCoord.enabled); 1441 ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPointCoord.enabled == 1442 mBuiltinInfo[gl::ShaderType::Fragment].glPointCoord.enabled); 1443 ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPointSize.enabled == 1444 mBuiltinInfo[gl::ShaderType::Fragment].glPointSize.enabled); 1445 ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glViewIDOVR.enabled == 1446 mBuiltinInfo[gl::ShaderType::Fragment].glViewIDOVR.enabled); 1447 } 1448 1449 BuiltinVaryingsD3D::~BuiltinVaryingsD3D() = default; 1450 1451 void BuiltinVaryingsD3D::updateBuiltins(gl::ShaderType shaderType, 1452 const ProgramD3DMetadata &metadata, 1453 const VaryingPacking &packing) 1454 { 1455 const std::string &userSemantic = GetVaryingSemantic(metadata.getRendererMajorShaderModel(), 1456 metadata.usesSystemValuePointSize()); 1457 1458 // Note that when enabling builtins only for specific shader stages in shader model >= 4, the 1459 // code needs to ensure that the input struct of the shader stage is a prefix of the output 1460 // struct of the previous stage. 1461 1462 unsigned int reservedSemanticIndex = packing.getMaxSemanticIndex(); 1463 1464 BuiltinInfo *builtins = &mBuiltinInfo[shaderType]; 1465 1466 if (metadata.getRendererMajorShaderModel() >= 4) 1467 { 1468 builtins->dxPosition.enableSystem("SV_Position"); 1469 } 1470 else if (shaderType == gl::ShaderType::Fragment) 1471 { 1472 builtins->dxPosition.enableSystem("VPOS"); 1473 } 1474 else 1475 { 1476 builtins->dxPosition.enableSystem("POSITION"); 1477 } 1478 1479 if (metadata.usesTransformFeedbackGLPosition()) 1480 { 1481 builtins->glPosition.enable(userSemantic, reservedSemanticIndex++); 1482 } 1483 1484 if (metadata.usesFragCoord()) 1485 { 1486 builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++); 1487 } 1488 1489 if (shaderType == gl::ShaderType::Vertex ? metadata.addsPointCoordToVertexShader() 1490 : metadata.usesPointCoord()) 1491 { 1492 // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) 1493 // In D3D11 we manually compute gl_PointCoord in the GS. 1494 if (metadata.getRendererMajorShaderModel() >= 4) 1495 { 1496 builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++); 1497 } 1498 else 1499 { 1500 builtins->glPointCoord.enable("TEXCOORD", 0); 1501 } 1502 } 1503 1504 if (metadata.hasANGLEMultiviewEnabled()) 1505 { 1506 // Although it is possible to compute gl_ViewID_OVR from the value of 1507 // SV_ViewportArrayIndex or SV_RenderTargetArrayIndex and the multi-view state in the 1508 // driver constant buffer, it is easier and cleaner to always pass it as a varying. 1509 builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++); 1510 1511 if (shaderType == gl::ShaderType::Vertex) 1512 { 1513 if (metadata.canSelectViewInVertexShader()) 1514 { 1515 builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex"); 1516 builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex"); 1517 } 1518 } 1519 1520 if (shaderType == gl::ShaderType::Geometry) 1521 { 1522 // gl_Layer and gl_ViewportIndex are necessary so that we can write to either based on 1523 // the multiview state in the driver constant buffer. 1524 builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex"); 1525 builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex"); 1526 } 1527 } 1528 1529 // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders 1530 if (metadata.usesSystemValuePointSize() && 1531 (shaderType != gl::ShaderType::Fragment || metadata.getRendererMajorShaderModel() >= 4)) 1532 { 1533 builtins->glPointSize.enableSystem("PSIZE"); 1534 } 1535 } 1536 1537 } // namespace rx