DriverUniform.cpp (17128B)
1 // 2 // Copyright 2020 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 // DriverUniform.cpp: Add code to support driver uniforms 7 // 8 9 #include "compiler/translator/tree_util/DriverUniform.h" 10 11 #include "compiler/translator/Compiler.h" 12 #include "compiler/translator/IntermNode.h" 13 #include "compiler/translator/StaticType.h" 14 #include "compiler/translator/SymbolTable.h" 15 #include "compiler/translator/tree_util/FindMain.h" 16 #include "compiler/translator/tree_util/IntermNode_util.h" 17 #include "compiler/translator/tree_util/IntermTraverse.h" 18 #include "compiler/translator/util.h" 19 20 namespace sh 21 { 22 23 namespace 24 { 25 constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams"); 26 27 constexpr const char kAcbBufferOffsets[] = "acbBufferOffsets"; 28 constexpr const char kDepthRange[] = "depthRange"; 29 constexpr const char kRenderArea[] = "renderArea"; 30 constexpr const char kFlipXY[] = "flipXY"; 31 constexpr const char kDither[] = "dither"; 32 constexpr const char kMisc[] = "misc"; 33 34 // Extended uniforms 35 constexpr const char kXfbBufferOffsets[] = "xfbBufferOffsets"; 36 constexpr const char kXfbVerticesPerInstance[] = "xfbVerticesPerInstance"; 37 constexpr const char kUnused[] = "unused"; 38 constexpr const char kUnused2[] = "unused2"; 39 } // anonymous namespace 40 41 // Class DriverUniform 42 bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable) 43 { 44 constexpr size_t kNumComputeDriverUniforms = 1; 45 constexpr std::array<const char *, kNumComputeDriverUniforms> kComputeDriverUniformNames = { 46 {kAcbBufferOffsets}}; 47 48 ASSERT(!mDriverUniforms); 49 // This field list mirrors the structure of ComputeDriverUniforms in ContextVk.cpp. 50 TFieldList *driverFieldList = new TFieldList; 51 52 const std::array<TType *, kNumComputeDriverUniforms> kDriverUniformTypes = {{ 53 new TType(EbtUInt, EbpHigh, EvqGlobal, 4), 54 }}; 55 56 for (size_t uniformIndex = 0; uniformIndex < kNumComputeDriverUniforms; ++uniformIndex) 57 { 58 TField *driverUniformField = 59 new TField(kDriverUniformTypes[uniformIndex], 60 ImmutableString(kComputeDriverUniformNames[uniformIndex]), TSourceLoc(), 61 SymbolType::AngleInternal); 62 driverFieldList->push_back(driverUniformField); 63 } 64 65 // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". 66 TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); 67 layoutQualifier.blockStorage = EbsStd140; 68 layoutQualifier.pushConstant = true; 69 70 mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, 71 layoutQualifier, TMemoryQualifier::Create(), 0, 72 ImmutableString(vk::kDriverUniformsBlockName), 73 ImmutableString(vk::kDriverUniformsVarName)); 74 return mDriverUniforms != nullptr; 75 } 76 77 TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable) 78 { 79 constexpr size_t kNumGraphicsDriverUniforms = 6; 80 constexpr std::array<const char *, kNumGraphicsDriverUniforms> kGraphicsDriverUniformNames = {{ 81 kAcbBufferOffsets, 82 kDepthRange, 83 kRenderArea, 84 kFlipXY, 85 kDither, 86 kMisc, 87 }}; 88 89 // This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp. 90 TFieldList *driverFieldList = new TFieldList; 91 92 const std::array<TType *, kNumGraphicsDriverUniforms> kDriverUniformTypes = {{ 93 // acbBufferOffsets: Packed ubyte8 94 new TType(EbtUInt, EbpHigh, EvqGlobal, 2), 95 // depthRange: Near and far depth 96 new TType(EbtFloat, EbpHigh, EvqGlobal, 2), 97 // renderArea: Packed ushort2 98 new TType(EbtUInt, EbpHigh, EvqGlobal), 99 // flipXY: Packed snorm4 100 new TType(EbtUInt, EbpHigh, EvqGlobal), 101 // dither: ushort 102 new TType(EbtUInt, EbpHigh, EvqGlobal), 103 // misc: Various bits of state 104 new TType(EbtUInt, EbpHigh, EvqGlobal), 105 }}; 106 107 for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex) 108 { 109 TField *driverUniformField = 110 new TField(kDriverUniformTypes[uniformIndex], 111 ImmutableString(kGraphicsDriverUniformNames[uniformIndex]), TSourceLoc(), 112 SymbolType::AngleInternal); 113 driverFieldList->push_back(driverUniformField); 114 } 115 116 return driverFieldList; 117 } 118 119 const TType *DriverUniform::createEmulatedDepthRangeType(TSymbolTable *symbolTable) 120 { 121 // If already defined, return it immediately. 122 if (mEmulatedDepthRangeType != nullptr) 123 { 124 return mEmulatedDepthRangeType; 125 } 126 127 // Create the depth range type. 128 TFieldList *depthRangeParamsFields = new TFieldList(); 129 TType *floatType = new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1); 130 depthRangeParamsFields->push_back( 131 new TField(floatType, ImmutableString("near"), TSourceLoc(), SymbolType::AngleInternal)); 132 depthRangeParamsFields->push_back( 133 new TField(floatType, ImmutableString("far"), TSourceLoc(), SymbolType::AngleInternal)); 134 depthRangeParamsFields->push_back( 135 new TField(floatType, ImmutableString("diff"), TSourceLoc(), SymbolType::AngleInternal)); 136 137 TStructure *emulatedDepthRangeParams = new TStructure( 138 symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal); 139 140 mEmulatedDepthRangeType = new TType(emulatedDepthRangeParams, false); 141 142 return mEmulatedDepthRangeType; 143 } 144 145 // The Add*DriverUniformsToShader operation adds an internal uniform block to a shader. The driver 146 // block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms 147 // variable. 148 // 149 // There are Graphics and Compute variations as they require different uniforms. 150 bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable) 151 { 152 ASSERT(!mDriverUniforms); 153 154 // Declare the depth range struct type. 155 const TType *emulatedDepthRangeType = createEmulatedDepthRangeType(symbolTable); 156 const TType *emulatedDepthRangeDeclType = new TType(emulatedDepthRangeType->getStruct(), true); 157 158 const TVariable *depthRangeVar = 159 new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty, 160 TExtension::UNDEFINED, emulatedDepthRangeDeclType); 161 162 DeclareGlobalVariable(root, depthRangeVar); 163 164 TFieldList *driverFieldList = createUniformFields(symbolTable); 165 if (mMode == DriverUniformMode::InterfaceBlock) 166 { 167 // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". 168 TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); 169 layoutQualifier.blockStorage = EbsStd140; 170 layoutQualifier.pushConstant = true; 171 172 mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, 173 layoutQualifier, TMemoryQualifier::Create(), 0, 174 ImmutableString(vk::kDriverUniformsBlockName), 175 ImmutableString(vk::kDriverUniformsVarName)); 176 } 177 else 178 { 179 // Declare a structure "ANGLEUniformBlock" with instance name "ANGLE_angleUniforms". 180 // This code path is taken only by the direct-to-Metal backend, and the assumptions 181 // about the naming conventions of ANGLE-internal variables run too deeply to rename 182 // this one. 183 auto varName = ImmutableString("ANGLE_angleUniforms"); 184 auto result = DeclareStructure(root, symbolTable, driverFieldList, EvqUniform, 185 TMemoryQualifier::Create(), 0, 186 ImmutableString(vk::kDriverUniformsBlockName), &varName); 187 mDriverUniforms = result.second; 188 } 189 190 return mDriverUniforms != nullptr; 191 } 192 193 TIntermTyped *DriverUniform::createDriverUniformRef(const char *fieldName) const 194 { 195 size_t fieldIndex = 0; 196 if (mMode == DriverUniformMode::InterfaceBlock) 197 { 198 fieldIndex = 199 FindFieldIndex(mDriverUniforms->getType().getInterfaceBlock()->fields(), fieldName); 200 } 201 else 202 { 203 fieldIndex = FindFieldIndex(mDriverUniforms->getType().getStruct()->fields(), fieldName); 204 } 205 206 TIntermSymbol *angleUniformsRef = new TIntermSymbol(mDriverUniforms); 207 TConstantUnion *uniformIndex = new TConstantUnion; 208 uniformIndex->setIConst(static_cast<int>(fieldIndex)); 209 TIntermConstantUnion *indexRef = 210 new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic<EbtInt, EbpLow>()); 211 if (mMode == DriverUniformMode::InterfaceBlock) 212 { 213 return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef); 214 } 215 return new TIntermBinary(EOpIndexDirectStruct, angleUniformsRef, indexRef); 216 } 217 218 TIntermTyped *DriverUniform::getAcbBufferOffsets() const 219 { 220 return createDriverUniformRef(kAcbBufferOffsets); 221 } 222 223 TIntermTyped *DriverUniform::getDepthRange() const 224 { 225 ASSERT(mEmulatedDepthRangeType != nullptr); 226 227 TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange); 228 TIntermTyped *nearRef = new TIntermSwizzle(depthRangeRef, {0}); 229 TIntermTyped *farRef = new TIntermSwizzle(depthRangeRef->deepCopy(), {1}); 230 TIntermTyped *diff = new TIntermBinary(EOpSub, farRef, nearRef); 231 232 TIntermSequence args = { 233 nearRef->deepCopy(), 234 farRef->deepCopy(), 235 diff, 236 }; 237 238 return TIntermAggregate::CreateConstructor(*mEmulatedDepthRangeType, &args); 239 } 240 241 TIntermTyped *DriverUniform::getViewportZScale() const 242 { 243 ASSERT(mEmulatedDepthRangeType != nullptr); 244 245 TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange); 246 TIntermTyped *nearRef = new TIntermSwizzle(depthRangeRef, {0}); 247 TIntermTyped *farRef = new TIntermSwizzle(depthRangeRef->deepCopy(), {1}); 248 249 TIntermTyped *isNegative = new TIntermBinary(EOpLessThan, farRef, nearRef); 250 251 return new TIntermTernary(isNegative, CreateFloatNode(-1, EbpMedium), 252 CreateFloatNode(1, EbpMedium)); 253 } 254 255 TIntermTyped *DriverUniform::getHalfRenderArea() const 256 { 257 TIntermTyped *renderAreaRef = createDriverUniformRef(kRenderArea); 258 TIntermTyped *width = new TIntermBinary(EOpBitwiseAnd, renderAreaRef, CreateUIntNode(0xFFFF)); 259 TIntermTyped *height = 260 new TIntermBinary(EOpBitShiftRight, renderAreaRef->deepCopy(), CreateUIntNode(16)); 261 262 TIntermSequence widthArgs = { 263 width, 264 }; 265 TIntermTyped *widthAsFloat = 266 TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpHigh>(), &widthArgs); 267 268 TIntermSequence heightArgs = { 269 height, 270 }; 271 TIntermTyped *heightAsFloat = TIntermAggregate::CreateConstructor( 272 *StaticType::GetBasic<EbtFloat, EbpHigh>(), &heightArgs); 273 274 TIntermSequence args = { 275 widthAsFloat, 276 heightAsFloat, 277 }; 278 279 TIntermTyped *renderArea = 280 TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpHigh, 2>(), &args); 281 return new TIntermBinary(EOpVectorTimesScalar, renderArea, CreateFloatNode(0.5, EbpMedium)); 282 } 283 284 TIntermTyped *DriverUniform::getFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const 285 { 286 TIntermTyped *flipXY = createDriverUniformRef(kFlipXY); 287 TIntermTyped *values = CreateBuiltInUnaryFunctionCallNode( 288 "unpackSnorm4x8", flipXY, *symbolTable, 289 GetESSLOrGLSLVersion(symbolTable->getShaderSpec(), 310, 400)); 290 291 if (stage == DriverUniformFlip::Fragment) 292 { 293 return new TIntermSwizzle(values, {0, 1}); 294 } 295 296 return new TIntermSwizzle(values, {2, 3}); 297 } 298 299 TIntermTyped *DriverUniform::getNegFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const 300 { 301 TIntermTyped *flipXY = getFlipXY(symbolTable, stage); 302 303 constexpr std::array<float, 2> kMultiplier = {1, -1}; 304 return new TIntermBinary(EOpMul, flipXY, CreateVecNode(kMultiplier.data(), 2, EbpLow)); 305 } 306 307 TIntermTyped *DriverUniform::getDither() const 308 { 309 return createDriverUniformRef(kDither); 310 } 311 312 TIntermTyped *DriverUniform::getSwapXY() const 313 { 314 TIntermTyped *miscRef = createDriverUniformRef(kMisc); 315 TIntermTyped *swapXY = new TIntermBinary(EOpBitwiseAnd, miscRef, 316 CreateUIntNode(vk::kDriverUniformsMiscSwapXYMask)); 317 318 TIntermSequence args = { 319 swapXY, 320 }; 321 return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(), 322 &args); 323 } 324 325 TIntermTyped *DriverUniform::getAdvancedBlendEquation() const 326 { 327 TIntermTyped *miscRef = createDriverUniformRef(kMisc); 328 TIntermTyped *equation = 329 new TIntermBinary(EOpBitShiftRight, miscRef, 330 CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationOffset)); 331 equation = new TIntermBinary(EOpBitwiseAnd, equation, 332 CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationMask)); 333 334 return equation; 335 } 336 337 TIntermTyped *DriverUniform::getNumSamples() const 338 { 339 TIntermTyped *miscRef = createDriverUniformRef(kMisc); 340 TIntermTyped *sampleCount = new TIntermBinary( 341 EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscSampleCountOffset)); 342 sampleCount = new TIntermBinary(EOpBitwiseAnd, sampleCount, 343 CreateUIntNode(vk::kDriverUniformsMiscSampleCountMask)); 344 345 return sampleCount; 346 } 347 348 TIntermTyped *DriverUniform::getClipDistancesEnabled() const 349 { 350 TIntermTyped *miscRef = createDriverUniformRef(kMisc); 351 TIntermTyped *enabledMask = new TIntermBinary( 352 EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesOffset)); 353 enabledMask = new TIntermBinary(EOpBitwiseAnd, enabledMask, 354 CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesMask)); 355 356 return enabledMask; 357 } 358 359 TIntermTyped *DriverUniform::getTransformDepth() const 360 { 361 TIntermTyped *miscRef = createDriverUniformRef(kMisc); 362 TIntermTyped *transformDepth = new TIntermBinary( 363 EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscTransformDepthOffset)); 364 transformDepth = new TIntermBinary(EOpBitwiseAnd, transformDepth, 365 CreateUIntNode(vk::kDriverUniformsMiscTransformDepthMask)); 366 367 TIntermSequence args = { 368 transformDepth, 369 }; 370 return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtBool, EbpUndefined>(), 371 &args); 372 } 373 374 // 375 // Class DriverUniformExtended 376 // 377 TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable) 378 { 379 TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable); 380 381 constexpr size_t kNumGraphicsDriverUniformsExt = 4; 382 constexpr std::array<const char *, kNumGraphicsDriverUniformsExt> 383 kGraphicsDriverUniformNamesExt = { 384 {kXfbBufferOffsets, kXfbVerticesPerInstance, kUnused, kUnused2}}; 385 386 const std::array<TType *, kNumGraphicsDriverUniformsExt> kDriverUniformTypesExt = {{ 387 // xfbBufferOffsets: uvec4 388 new TType(EbtInt, EbpHigh, EvqGlobal, 4), 389 // xfbVerticesPerInstance: uint 390 new TType(EbtInt, EbpHigh, EvqGlobal), 391 // unused: uvec3 392 new TType(EbtUInt, EbpHigh, EvqGlobal), 393 new TType(EbtUInt, EbpHigh, EvqGlobal, 2), 394 }}; 395 396 for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex) 397 { 398 TField *driverUniformField = 399 new TField(kDriverUniformTypesExt[uniformIndex], 400 ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(), 401 SymbolType::AngleInternal); 402 driverFieldList->push_back(driverUniformField); 403 } 404 405 return driverFieldList; 406 } 407 408 TIntermTyped *DriverUniformExtended::getXfbBufferOffsets() const 409 { 410 return createDriverUniformRef(kXfbBufferOffsets); 411 } 412 413 TIntermTyped *DriverUniformExtended::getXfbVerticesPerInstance() const 414 { 415 return createDriverUniformRef(kXfbVerticesPerInstance); 416 } 417 418 TIntermTyped *MakeSwapXMultiplier(TIntermTyped *swapped) 419 { 420 // float(!swapped) 421 TIntermSequence args = { 422 new TIntermUnary(EOpLogicalNot, swapped, nullptr), 423 }; 424 return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpLow>(), &args); 425 } 426 427 TIntermTyped *MakeSwapYMultiplier(TIntermTyped *swapped) 428 { 429 // float(swapped) 430 TIntermSequence args = { 431 swapped, 432 }; 433 return TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtFloat, EbpLow>(), &args); 434 } 435 } // namespace sh