Selaa lähdekoodia

Fix static global resource arrays. (#2786)

Allow static global resource arrays to be lowered to allocas
Note: allowing other aggregate types here leads to problems due to
not properly translating aggregate initializers.
Tex Riddell 5 vuotta sitten
vanhempi
commit
9729946be7

+ 13 - 2
lib/HLSL/DxilPromoteResourcePasses.cpp

@@ -18,6 +18,7 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
 #include "llvm/Transforms/Utils/PromoteMemToReg.h"
 #include "llvm/Transforms/Utils/SSAUpdater.h"
 #include <unordered_set>
@@ -184,11 +185,21 @@ bool DxilPromoteStaticResources::PromoteStaticGlobalResources(
       GlobalVariable *GV = *(it++);
       // Build list of instructions to promote.
       for (User *U : GV->users()) {
-        Instruction *I = cast<Instruction>(U);
-        Insts.emplace_back(I);
+        if (isa<LoadInst>(U) || isa<StoreInst>(U)) {
+          Insts.emplace_back(cast<Instruction>(U));
+        } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
+          for (User *gepU : GEP->users()) {
+            DXASSERT_NOMSG(isa<LoadInst>(gepU) || isa<StoreInst>(gepU));
+            if (isa<LoadInst>(gepU) || isa<StoreInst>(gepU))
+              Insts.emplace_back(cast<Instruction>(gepU));
+          }
+        } else {
+          DXASSERT(false, "Unhandled user of resource static global");
+        }
       }
 
       LoadAndStorePromoter(Insts, SSA).run(Insts);
+      GV->removeDeadConstantUsers();
       if (GV->user_empty()) {
         bUpdated = true;
         staticResources.erase(GV);

+ 13 - 8
lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp

@@ -3307,8 +3307,9 @@ bool SROA_Helper::DoScalarReplacement(GlobalVariable *GV,
     }
 
     if (ElTy->isStructTy() &&
-        // Skip Matrix type.
-        !HLMatrixType::isa(ElTy)) {
+        // Skip Matrix and Resource type.
+        !HLMatrixType::isa(ElTy) &&
+        !dxilutil::IsHLSLResourceType(ElTy)) {
       // for array of struct
       // split into arrays of struct elements
       StructType *ElST = cast<StructType>(ElTy);
@@ -6245,13 +6246,17 @@ public:
     // Lower static global into allocas.
     std::vector<GlobalVariable *> staticGVs;
     for (GlobalVariable &GV : M.globals()) {
-      bool isStaticGlobal =
-          dxilutil::IsStaticGlobal(&GV) &&
-          GV.getType()->getAddressSpace() == DXIL::kDefaultAddrSpace;
-
-      if (isStaticGlobal &&
-          !GV.getType()->getElementType()->isAggregateType()) {
+      // only for non-constant static globals
+      if (!dxilutil::IsStaticGlobal(&GV) || GV.isConstant())
+        continue;
+      Type *EltTy = GV.getType()->getElementType();
+      if (!EltTy->isAggregateType()) {
         staticGVs.emplace_back(&GV);
+      } else {
+        // Lower static [array of] resources
+        if (dxilutil::IsHLSLObjectType(dxilutil::GetArrayEltTy(EltTy))) {
+          staticGVs.emplace_back(&GV);
+        }
       }
     }
     bool bUpdated = false;

+ 32 - 0
tools/clang/test/HLSLFileCheck/hlsl/types/modifiers/static/static_res_array.hlsl

@@ -0,0 +1,32 @@
+// RUN: %dxc -E main -T vs_6_0 %s | FileCheck %s
+// RUN: %dxc -E main -T vs_6_0 -Od %s | FileCheck %s -check-prefix=CHECKOD
+
+// CHECK: @dx.op.textureLoad.f32(i32 66,
+// CHECK: @dx.op.textureLoad.f32(i32 66,
+// CHECK-NOT: @dx.op.textureLoad.f32(i32 66,
+
+// CHECKOD: @dx.op.textureLoad.f32(i32 66,
+// CHECKOD: @dx.op.textureLoad.f32(i32 66,
+// CHECKOD: @dx.op.textureLoad.f32(i32 66,
+// CHECKOD: @dx.op.textureLoad.f32(i32 66,
+// CHECKOD: @dx.op.textureLoad.f32(i32 66,
+// CHECKOD: @dx.op.textureLoad.f32(i32 66,
+
+Texture2D<float4> A, B;
+
+struct ResStruct {
+  Texture2D<float4> arr[2];
+};
+
+static ResStruct RS = { { A, B } };
+static const ResStruct RS_const = { { A, B } };
+
+float4 main() : OUT {
+  float4 result = RS.arr[1].Load(uint3(0,0,0))
+                + RS_const.arr[1].Load(uint3(0,0,0));
+  [unroll]
+  for (uint i = 0; i < 2; i++)
+    result += RS.arr[i].Load(uint3(0,0,0))
+            + RS_const.arr[i].Load(uint3(0,0,0));
+  return result;
+}