Prechádzať zdrojové kódy

Call ctor function for static globals in patch constant function. (#3122)

* Call ctor function for static globals in patch constant function.

* Also copy static globals which has const initialize value at beginning of patch constant.
Xiang Li 5 rokov pred
rodič
commit
4446237655

+ 25 - 1
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -3333,8 +3333,32 @@ void CGMSHLSLRuntime::FinishCodeGen() {
   bool bIsLib = HLM.GetShaderModel()->IsLib();
   if (!bIsLib) {
     // need this for "llvm.global_dtors"?
+    if (HLM.GetShaderModel()->IsHS()) {
+      if (Function *patchConstantFn = HLM.GetPatchConstantFunction()) {
+        // static globals are independent for entry function and patch constant function.
+        // Update static global in entry function will not affect value in patch constant function.
+        // So just call ctors for patch constant function too.
+        ProcessCtorFunctions(
+            M, "llvm.global_ctors",
+            patchConstantFn->getEntryBlock().getFirstInsertionPt(), false);
+        IRBuilder<> B(patchConstantFn->getEntryBlock().getFirstInsertionPt());
+        // For static globals which has const initialize value, copy it at
+        // beginning of patch constant function to avoid use value updated by
+        // entry function.
+        for (GlobalVariable &GV : M.globals()) {
+          if (GV.isConstant())
+            continue;
+          if (!GV.hasInitializer())
+            continue;
+          if (GV.getName() == "llvm.global_ctors")
+            continue;
+          Value *V = GV.getInitializer();
+          B.CreateStore(V, &GV);
+        }
+      }
+    }
     ProcessCtorFunctions(M, "llvm.global_ctors",
-                         Entry.Func->getEntryBlock().getFirstInsertionPt());
+                         Entry.Func->getEntryBlock().getFirstInsertionPt(), true);
   }
 
   UpdateLinkage(HLM, CGM, m_ExportMap, entryFunctionMap,

+ 4 - 2
tools/clang/lib/CodeGen/CGHLSLMSFinishCodeGen.cpp

@@ -2190,7 +2190,7 @@ bool BuildImmInit(Function *Ctor) {
 namespace CGHLSLMSHelper {
 
 void ProcessCtorFunctions(llvm::Module &M, StringRef globalName,
-                          Instruction *InsertPt) {
+                          Instruction *InsertPt, bool bRemoveGlobal) {
   // add global call to entry func
   GlobalVariable *GV = M.getGlobalVariable(globalName);
   if (!GV)
@@ -2228,7 +2228,9 @@ void ProcessCtorFunctions(llvm::Module &M, StringRef globalName,
     }
   }
   // remove the GV
-  GV->eraseFromParent();
+  if (bRemoveGlobal) {
+    GV->eraseFromParent();
+  }
 }
 
 void FinishCBuffer(

+ 1 - 1
tools/clang/lib/CodeGen/CGHLSLMSHelper.h

@@ -173,7 +173,7 @@ void FinishCBuffer(
         &AnnotationMap);
 
 void ProcessCtorFunctions(llvm::Module &M, llvm::StringRef globalName,
-                          llvm::Instruction *InsertPt);
+                          llvm::Instruction *InsertPt, bool bRemoveGlobal);
 
 void TranslateRayQueryConstructor(hlsl::HLModule &HLM);
 

+ 39 - 0
tools/clang/test/HLSLFileCheck/shader_targets/hull/static_res_in_patch_constant_func.hlsl

@@ -0,0 +1,39 @@
+// RUN: %dxc -E main -T hs_6_0  %s 2>&1 | FileCheck %s
+
+// Make sure generated buffer load for static buffer used in patch constant function.
+// CHECK:call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68,
+
+struct HSPerPatchData
+{
+	float	edges[3] : SV_TessFactor;
+	float	inside   : SV_InsideTessFactor;
+};
+
+Buffer<float> buf;
+
+const static Buffer<float> static_buf = buf;
+
+HSPerPatchData HSPerPatchFunc()
+{
+  HSPerPatchData d;
+
+  d.edges[0] = -5;
+  d.edges[1] = -6;
+  d.edges[2] = -7;
+  d.inside = static_buf[0];
+
+  return d;
+}
+
+
+
+// hull per-control point shader
+[domain("tri")]
+[partitioning("fractional_odd")]
+[outputtopology("triangle_cw")]
+[patchconstantfunc("HSPerPatchFunc")]
+[outputcontrolpoints(3)]
+void main( const uint id : SV_OutputControlPointID )
+{
+  
+}

+ 42 - 0
tools/clang/test/HLSLFileCheck/shader_targets/hull/static_res_in_patch_constant_func2.hlsl

@@ -0,0 +1,42 @@
+// RUN: %dxc -E main -T hs_6_0  %s 2>&1 | FileCheck %s
+
+// Make sure @sf is restored to original value in patch constant function.
+// CHECK:define void @"\01?HSPerPatchFunc@@YA?AUHSPerPatchData@@XZ"() {
+// CHECK:store float 3.000000e+00, float* @sf, align 4
+// CHECK-NEXT:call void @dx.op.storePatchConstant.f32
+// CHECK-NEXT:call void @dx.op.storePatchConstant.f32
+// CHECK-NEXT:call void @dx.op.storePatchConstant.f32
+// CHECK-NEXT:load float, float* @sf, align 4
+// CHECK-NEXT:call void @dx.op.storePatchConstant.f32
+struct HSPerPatchData
+{
+	float	edges[3] : SV_TessFactor;
+	float	inside   : SV_InsideTessFactor;
+};
+
+static float sf = 3;
+
+HSPerPatchData HSPerPatchFunc()
+{
+  HSPerPatchData d;
+
+  d.edges[0] = -5;
+  d.edges[1] = -6;
+  d.edges[2] = -7;
+  d.inside = sf;
+
+  return d;
+}
+
+
+
+// hull per-control point shader
+[domain("tri")]
+[partitioning("fractional_odd")]
+[outputtopology("triangle_cw")]
+[patchconstantfunc("HSPerPatchFunc")]
+[outputcontrolpoints(3)]
+void main( const uint id : SV_OutputControlPointID )
+{
+  sf = 0;
+}