From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../translator/tree_util/DriverUniform.cpp | 435 +++++++++++++++++++++ 1 file changed, 435 insertions(+) create mode 100644 gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp (limited to 'gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp') diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp new file mode 100644 index 0000000000..9cf4dddcd0 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/tree_util/DriverUniform.cpp @@ -0,0 +1,435 @@ +// +// Copyright 2020 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DriverUniform.cpp: Add code to support driver uniforms +// + +#include "compiler/translator/tree_util/DriverUniform.h" + +#include "compiler/translator/Compiler.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/StaticType.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/tree_util/FindMain.h" +#include "compiler/translator/tree_util/IntermNode_util.h" +#include "compiler/translator/tree_util/IntermTraverse.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ +constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDepthRangeParams"); + +constexpr const char kAcbBufferOffsets[] = "acbBufferOffsets"; +constexpr const char kDepthRange[] = "depthRange"; +constexpr const char kRenderArea[] = "renderArea"; +constexpr const char kFlipXY[] = "flipXY"; +constexpr const char kDither[] = "dither"; +constexpr const char kMisc[] = "misc"; + +// Extended uniforms +constexpr const char kXfbBufferOffsets[] = "xfbBufferOffsets"; +constexpr const char kXfbVerticesPerInstance[] = "xfbVerticesPerInstance"; +constexpr const char kUnused[] = "unused"; +constexpr const char kUnused2[] = "unused2"; +} // anonymous namespace + +// Class DriverUniform +bool DriverUniform::addComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable) +{ + constexpr size_t kNumComputeDriverUniforms = 1; + constexpr std::array kComputeDriverUniformNames = { + {kAcbBufferOffsets}}; + + ASSERT(!mDriverUniforms); + // This field list mirrors the structure of ComputeDriverUniforms in ContextVk.cpp. + TFieldList *driverFieldList = new TFieldList; + + const std::array kDriverUniformTypes = {{ + new TType(EbtUInt, EbpHigh, EvqGlobal, 4), + }}; + + for (size_t uniformIndex = 0; uniformIndex < kNumComputeDriverUniforms; ++uniformIndex) + { + TField *driverUniformField = + new TField(kDriverUniformTypes[uniformIndex], + ImmutableString(kComputeDriverUniformNames[uniformIndex]), TSourceLoc(), + SymbolType::AngleInternal); + driverFieldList->push_back(driverUniformField); + } + + // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". + TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); + layoutQualifier.blockStorage = EbsStd140; + layoutQualifier.pushConstant = true; + + mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, + layoutQualifier, TMemoryQualifier::Create(), 0, + ImmutableString(vk::kDriverUniformsBlockName), + ImmutableString(vk::kDriverUniformsVarName)); + return mDriverUniforms != nullptr; +} + +TFieldList *DriverUniform::createUniformFields(TSymbolTable *symbolTable) +{ + constexpr size_t kNumGraphicsDriverUniforms = 6; + constexpr std::array kGraphicsDriverUniformNames = {{ + kAcbBufferOffsets, + kDepthRange, + kRenderArea, + kFlipXY, + kDither, + kMisc, + }}; + + // This field list mirrors the structure of GraphicsDriverUniforms in ContextVk.cpp. + TFieldList *driverFieldList = new TFieldList; + + const std::array kDriverUniformTypes = {{ + // acbBufferOffsets: Packed ubyte8 + new TType(EbtUInt, EbpHigh, EvqGlobal, 2), + // depthRange: Near and far depth + new TType(EbtFloat, EbpHigh, EvqGlobal, 2), + // renderArea: Packed ushort2 + new TType(EbtUInt, EbpHigh, EvqGlobal), + // flipXY: Packed snorm4 + new TType(EbtUInt, EbpHigh, EvqGlobal), + // dither: ushort + new TType(EbtUInt, EbpHigh, EvqGlobal), + // misc: Various bits of state + new TType(EbtUInt, EbpHigh, EvqGlobal), + }}; + + for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniforms; ++uniformIndex) + { + TField *driverUniformField = + new TField(kDriverUniformTypes[uniformIndex], + ImmutableString(kGraphicsDriverUniformNames[uniformIndex]), TSourceLoc(), + SymbolType::AngleInternal); + driverFieldList->push_back(driverUniformField); + } + + return driverFieldList; +} + +const TType *DriverUniform::createEmulatedDepthRangeType(TSymbolTable *symbolTable) +{ + // If already defined, return it immediately. + if (mEmulatedDepthRangeType != nullptr) + { + return mEmulatedDepthRangeType; + } + + // Create the depth range type. + TFieldList *depthRangeParamsFields = new TFieldList(); + TType *floatType = new TType(EbtFloat, EbpHigh, EvqGlobal, 1, 1); + depthRangeParamsFields->push_back( + new TField(floatType, ImmutableString("near"), TSourceLoc(), SymbolType::AngleInternal)); + depthRangeParamsFields->push_back( + new TField(floatType, ImmutableString("far"), TSourceLoc(), SymbolType::AngleInternal)); + depthRangeParamsFields->push_back( + new TField(floatType, ImmutableString("diff"), TSourceLoc(), SymbolType::AngleInternal)); + + TStructure *emulatedDepthRangeParams = new TStructure( + symbolTable, kEmulatedDepthRangeParams, depthRangeParamsFields, SymbolType::AngleInternal); + + mEmulatedDepthRangeType = new TType(emulatedDepthRangeParams, false); + + return mEmulatedDepthRangeType; +} + +// The Add*DriverUniformsToShader operation adds an internal uniform block to a shader. The driver +// block is used to implement Vulkan-specific features and workarounds. Returns the driver uniforms +// variable. +// +// There are Graphics and Compute variations as they require different uniforms. +bool DriverUniform::addGraphicsDriverUniformsToShader(TIntermBlock *root, TSymbolTable *symbolTable) +{ + ASSERT(!mDriverUniforms); + + // Declare the depth range struct type. + const TType *emulatedDepthRangeType = createEmulatedDepthRangeType(symbolTable); + const TType *emulatedDepthRangeDeclType = new TType(emulatedDepthRangeType->getStruct(), true); + + const TVariable *depthRangeVar = + new TVariable(symbolTable->nextUniqueId(), kEmptyImmutableString, SymbolType::Empty, + TExtension::UNDEFINED, emulatedDepthRangeDeclType); + + DeclareGlobalVariable(root, depthRangeVar); + + TFieldList *driverFieldList = createUniformFields(symbolTable); + if (mMode == DriverUniformMode::InterfaceBlock) + { + // Define a driver uniform block "ANGLEUniformBlock" with instance name "ANGLEUniforms". + TLayoutQualifier layoutQualifier = TLayoutQualifier::Create(); + layoutQualifier.blockStorage = EbsStd140; + layoutQualifier.pushConstant = true; + + mDriverUniforms = DeclareInterfaceBlock(root, symbolTable, driverFieldList, EvqUniform, + layoutQualifier, TMemoryQualifier::Create(), 0, + ImmutableString(vk::kDriverUniformsBlockName), + ImmutableString(vk::kDriverUniformsVarName)); + } + else + { + // Declare a structure "ANGLEUniformBlock" with instance name "ANGLE_angleUniforms". + // This code path is taken only by the direct-to-Metal backend, and the assumptions + // about the naming conventions of ANGLE-internal variables run too deeply to rename + // this one. + auto varName = ImmutableString("ANGLE_angleUniforms"); + auto result = DeclareStructure(root, symbolTable, driverFieldList, EvqUniform, + TMemoryQualifier::Create(), 0, + ImmutableString(vk::kDriverUniformsBlockName), &varName); + mDriverUniforms = result.second; + } + + return mDriverUniforms != nullptr; +} + +TIntermTyped *DriverUniform::createDriverUniformRef(const char *fieldName) const +{ + size_t fieldIndex = 0; + if (mMode == DriverUniformMode::InterfaceBlock) + { + fieldIndex = + FindFieldIndex(mDriverUniforms->getType().getInterfaceBlock()->fields(), fieldName); + } + else + { + fieldIndex = FindFieldIndex(mDriverUniforms->getType().getStruct()->fields(), fieldName); + } + + TIntermSymbol *angleUniformsRef = new TIntermSymbol(mDriverUniforms); + TConstantUnion *uniformIndex = new TConstantUnion; + uniformIndex->setIConst(static_cast(fieldIndex)); + TIntermConstantUnion *indexRef = + new TIntermConstantUnion(uniformIndex, *StaticType::GetBasic()); + if (mMode == DriverUniformMode::InterfaceBlock) + { + return new TIntermBinary(EOpIndexDirectInterfaceBlock, angleUniformsRef, indexRef); + } + return new TIntermBinary(EOpIndexDirectStruct, angleUniformsRef, indexRef); +} + +TIntermTyped *DriverUniform::getAcbBufferOffsets() const +{ + return createDriverUniformRef(kAcbBufferOffsets); +} + +TIntermTyped *DriverUniform::getDepthRange() const +{ + ASSERT(mEmulatedDepthRangeType != nullptr); + + TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange); + TIntermTyped *nearRef = new TIntermSwizzle(depthRangeRef, {0}); + TIntermTyped *farRef = new TIntermSwizzle(depthRangeRef->deepCopy(), {1}); + TIntermTyped *diff = new TIntermBinary(EOpSub, farRef, nearRef); + + TIntermSequence args = { + nearRef->deepCopy(), + farRef->deepCopy(), + diff, + }; + + return TIntermAggregate::CreateConstructor(*mEmulatedDepthRangeType, &args); +} + +TIntermTyped *DriverUniform::getViewportZScale() const +{ + ASSERT(mEmulatedDepthRangeType != nullptr); + + TIntermTyped *depthRangeRef = createDriverUniformRef(kDepthRange); + TIntermTyped *nearRef = new TIntermSwizzle(depthRangeRef, {0}); + TIntermTyped *farRef = new TIntermSwizzle(depthRangeRef->deepCopy(), {1}); + + TIntermTyped *isNegative = new TIntermBinary(EOpLessThan, farRef, nearRef); + + return new TIntermTernary(isNegative, CreateFloatNode(-1, EbpMedium), + CreateFloatNode(1, EbpMedium)); +} + +TIntermTyped *DriverUniform::getHalfRenderArea() const +{ + TIntermTyped *renderAreaRef = createDriverUniformRef(kRenderArea); + TIntermTyped *width = new TIntermBinary(EOpBitwiseAnd, renderAreaRef, CreateUIntNode(0xFFFF)); + TIntermTyped *height = + new TIntermBinary(EOpBitShiftRight, renderAreaRef->deepCopy(), CreateUIntNode(16)); + + TIntermSequence widthArgs = { + width, + }; + TIntermTyped *widthAsFloat = + TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), &widthArgs); + + TIntermSequence heightArgs = { + height, + }; + TIntermTyped *heightAsFloat = TIntermAggregate::CreateConstructor( + *StaticType::GetBasic(), &heightArgs); + + TIntermSequence args = { + widthAsFloat, + heightAsFloat, + }; + + TIntermTyped *renderArea = + TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), &args); + return new TIntermBinary(EOpVectorTimesScalar, renderArea, CreateFloatNode(0.5, EbpMedium)); +} + +TIntermTyped *DriverUniform::getFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const +{ + TIntermTyped *flipXY = createDriverUniformRef(kFlipXY); + TIntermTyped *values = CreateBuiltInUnaryFunctionCallNode( + "unpackSnorm4x8", flipXY, *symbolTable, + GetESSLOrGLSLVersion(symbolTable->getShaderSpec(), 310, 400)); + + if (stage == DriverUniformFlip::Fragment) + { + return new TIntermSwizzle(values, {0, 1}); + } + + return new TIntermSwizzle(values, {2, 3}); +} + +TIntermTyped *DriverUniform::getNegFlipXY(TSymbolTable *symbolTable, DriverUniformFlip stage) const +{ + TIntermTyped *flipXY = getFlipXY(symbolTable, stage); + + constexpr std::array kMultiplier = {1, -1}; + return new TIntermBinary(EOpMul, flipXY, CreateVecNode(kMultiplier.data(), 2, EbpLow)); +} + +TIntermTyped *DriverUniform::getDither() const +{ + return createDriverUniformRef(kDither); +} + +TIntermTyped *DriverUniform::getSwapXY() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *swapXY = new TIntermBinary(EOpBitwiseAnd, miscRef, + CreateUIntNode(vk::kDriverUniformsMiscSwapXYMask)); + + TIntermSequence args = { + swapXY, + }; + return TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), + &args); +} + +TIntermTyped *DriverUniform::getAdvancedBlendEquation() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *equation = + new TIntermBinary(EOpBitShiftRight, miscRef, + CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationOffset)); + equation = new TIntermBinary(EOpBitwiseAnd, equation, + CreateUIntNode(vk::kDriverUniformsMiscAdvancedBlendEquationMask)); + + return equation; +} + +TIntermTyped *DriverUniform::getNumSamples() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *sampleCount = new TIntermBinary( + EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscSampleCountOffset)); + sampleCount = new TIntermBinary(EOpBitwiseAnd, sampleCount, + CreateUIntNode(vk::kDriverUniformsMiscSampleCountMask)); + + return sampleCount; +} + +TIntermTyped *DriverUniform::getClipDistancesEnabled() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *enabledMask = new TIntermBinary( + EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesOffset)); + enabledMask = new TIntermBinary(EOpBitwiseAnd, enabledMask, + CreateUIntNode(vk::kDriverUniformsMiscEnabledClipPlanesMask)); + + return enabledMask; +} + +TIntermTyped *DriverUniform::getTransformDepth() const +{ + TIntermTyped *miscRef = createDriverUniformRef(kMisc); + TIntermTyped *transformDepth = new TIntermBinary( + EOpBitShiftRight, miscRef, CreateUIntNode(vk::kDriverUniformsMiscTransformDepthOffset)); + transformDepth = new TIntermBinary(EOpBitwiseAnd, transformDepth, + CreateUIntNode(vk::kDriverUniformsMiscTransformDepthMask)); + + TIntermSequence args = { + transformDepth, + }; + return TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), + &args); +} + +// +// Class DriverUniformExtended +// +TFieldList *DriverUniformExtended::createUniformFields(TSymbolTable *symbolTable) +{ + TFieldList *driverFieldList = DriverUniform::createUniformFields(symbolTable); + + constexpr size_t kNumGraphicsDriverUniformsExt = 4; + constexpr std::array + kGraphicsDriverUniformNamesExt = { + {kXfbBufferOffsets, kXfbVerticesPerInstance, kUnused, kUnused2}}; + + const std::array kDriverUniformTypesExt = {{ + // xfbBufferOffsets: uvec4 + new TType(EbtInt, EbpHigh, EvqGlobal, 4), + // xfbVerticesPerInstance: uint + new TType(EbtInt, EbpHigh, EvqGlobal), + // unused: uvec3 + new TType(EbtUInt, EbpHigh, EvqGlobal), + new TType(EbtUInt, EbpHigh, EvqGlobal, 2), + }}; + + for (size_t uniformIndex = 0; uniformIndex < kNumGraphicsDriverUniformsExt; ++uniformIndex) + { + TField *driverUniformField = + new TField(kDriverUniformTypesExt[uniformIndex], + ImmutableString(kGraphicsDriverUniformNamesExt[uniformIndex]), TSourceLoc(), + SymbolType::AngleInternal); + driverFieldList->push_back(driverUniformField); + } + + return driverFieldList; +} + +TIntermTyped *DriverUniformExtended::getXfbBufferOffsets() const +{ + return createDriverUniformRef(kXfbBufferOffsets); +} + +TIntermTyped *DriverUniformExtended::getXfbVerticesPerInstance() const +{ + return createDriverUniformRef(kXfbVerticesPerInstance); +} + +TIntermTyped *MakeSwapXMultiplier(TIntermTyped *swapped) +{ + // float(!swapped) + TIntermSequence args = { + new TIntermUnary(EOpLogicalNot, swapped, nullptr), + }; + return TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), &args); +} + +TIntermTyped *MakeSwapYMultiplier(TIntermTyped *swapped) +{ + // float(swapped) + TIntermSequence args = { + swapped, + }; + return TIntermAggregate::CreateConstructor(*StaticType::GetBasic(), &args); +} +} // namespace sh -- cgit v1.2.3