Browse Source

Support local resource array which don't have dynamic indexing. (#938)

Xiang Li 7 years ago
parent
commit
ba844c25fe

+ 1 - 0
include/dxc/HLSL/DxilUtil.h

@@ -31,6 +31,7 @@ namespace dxilutil {
   GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
   GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
                                    llvm::Type *Ty, DxilTypeSystem &typeSys);
                                    llvm::Type *Ty, DxilTypeSystem &typeSys);
   llvm::Type *GetArrayEltTy(llvm::Type *Ty);
   llvm::Type *GetArrayEltTy(llvm::Type *Ty);
+  bool HasDynamicIndexing(llvm::Value *V);
 
 
   bool IsStaticGlobal(llvm::GlobalVariable *GV);
   bool IsStaticGlobal(llvm::GlobalVariable *GV);
   bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV);
   bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV);

+ 3 - 0
include/dxc/Support/ErrorCodes.h

@@ -101,3 +101,6 @@
 
 
 // 0X80AA0018 - General internal error.
 // 0X80AA0018 - General internal error.
 #define DXC_E_GENERAL_INTERNAL_ERROR                  DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0018))
 #define DXC_E_GENERAL_INTERNAL_ERROR                  DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0018))
+
+// 0X80AA0019 - Abort compilation error.
+#define DXC_E_ABORT_COMPILATION_ERROR                 DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0019))

+ 9 - 1
lib/HLSL/DxilGenerationPass.cpp

@@ -21,6 +21,7 @@
 #include "dxc/HLSL/HLOperationLower.h"
 #include "dxc/HLSL/HLOperationLower.h"
 #include "HLSignatureLower.h"
 #include "HLSignatureLower.h"
 #include "dxc/HLSL/DxilUtil.h"
 #include "dxc/HLSL/DxilUtil.h"
+#include "dxc/Support/exception.h"
 
 
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/IRBuilder.h"
@@ -1626,7 +1627,14 @@ void DxilLegalizeResourceUsePass::PromoteLocalResource(Function &F) {
           // Skip for unpromotable for lib.
           // Skip for unpromotable for lib.
           if (!isAllocaPromotable(AI) && IsLib)
           if (!isAllocaPromotable(AI) && IsLib)
             continue;
             continue;
-          DXASSERT(isAllocaPromotable(AI), "otherwise, non-promotable resource array alloca found");
+          if (!isAllocaPromotable(AI)) {
+            static const StringRef kNonPromotableLocalResourceErrorMsg =
+                "non-promotable local resource found.";
+            F.getContext().emitError(kNonPromotableLocalResourceErrorMsg);
+            throw hlsl::Exception(DXC_E_ABORT_COMPILATION_ERROR,
+                                  kNonPromotableLocalResourceErrorMsg);
+            continue;
+          }
           Allocas.push_back(AI);
           Allocas.push_back(AI);
         }
         }
       }
       }

+ 14 - 0
lib/HLSL/DxilUtil.cpp

@@ -21,6 +21,8 @@
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Constants.h"
 
 
 using namespace llvm;
 using namespace llvm;
 using namespace hlsl;
 using namespace hlsl;
@@ -38,6 +40,18 @@ Type *GetArrayEltTy(Type *Ty) {
   return Ty;
   return Ty;
 }
 }
 
 
+bool HasDynamicIndexing(Value *V) {
+  for (auto User : V->users()) {
+    if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
+      for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) {
+        if (!isa<ConstantInt>(Idx))
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
 unsigned
 unsigned
 GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
 GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
                                            llvm::Type *Ty,
                                            llvm::Type *Ty,

+ 38 - 35
lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp

@@ -2570,7 +2570,9 @@ void SROA_Helper::RewriteForGEP(GEPOperator *GEP, IRBuilder<> &Builder) {
   } else {
   } else {
     // End at array of basic type.
     // End at array of basic type.
     Type *Ty = GEP->getType()->getPointerElementType();
     Type *Ty = GEP->getType()->getPointerElementType();
-    if (Ty->isVectorTy() || Ty->isStructTy() || Ty->isArrayTy()) {
+    if (Ty->isVectorTy() ||
+        (Ty->isStructTy() && !HLModule::IsHLSLObjectType(Ty)) ||
+        Ty->isArrayTy()) {
       SmallVector<Value *, 8> NewArgs;
       SmallVector<Value *, 8> NewArgs;
       NewArgs.append(GEP->idx_begin(), GEP->idx_end());
       NewArgs.append(GEP->idx_begin(), GEP->idx_end());
 
 
@@ -3225,32 +3227,41 @@ bool SROA_Helper::DoScalarReplacement(Value *V, std::vector<Value *> &Elts,
     if (ElTy->isStructTy() &&
     if (ElTy->isStructTy() &&
         // Skip Matrix type.
         // Skip Matrix type.
         !HLMatrixLower::IsMatrixType(ElTy)) {
         !HLMatrixLower::IsMatrixType(ElTy)) {
-      // Skip HLSL object types.
-      if (HLModule::IsHLSLObjectType(ElTy)) {
-        return false;
-      }
-
-      // for array of struct
-      // split into arrays of struct elements
-      StructType *ElST = cast<StructType>(ElTy);
-      unsigned numTypes = ElST->getNumContainedTypes();
-      Elts.reserve(numTypes);
-      DxilStructAnnotation *SA = typeSys.GetStructAnnotation(ElST);
-      // Skip empty struct.
-      if (SA && SA->IsEmptyStruct())
-        return true;
-      for (int i = 0, e = numTypes; i != e; ++i) {
-        AllocaInst *NA = Builder.CreateAlloca(
-            CreateNestArrayTy(ElST->getContainedType(i), nestArrayTys), nullptr,
-            V->getName() + "." + Twine(i));
-        bool markPrecise = hasPrecise;
-        if (SA) {
-          DxilFieldAnnotation &FA = SA->GetFieldAnnotation(i);
-          markPrecise |= FA.IsPrecise();
+      if (!HLModule::IsHLSLObjectType(ElTy)) {
+        // for array of struct
+        // split into arrays of struct elements
+        StructType *ElST = cast<StructType>(ElTy);
+        unsigned numTypes = ElST->getNumContainedTypes();
+        Elts.reserve(numTypes);
+        DxilStructAnnotation *SA = typeSys.GetStructAnnotation(ElST);
+        // Skip empty struct.
+        if (SA && SA->IsEmptyStruct())
+          return true;
+        for (int i = 0, e = numTypes; i != e; ++i) {
+          AllocaInst *NA = Builder.CreateAlloca(
+              CreateNestArrayTy(ElST->getContainedType(i), nestArrayTys),
+              nullptr, V->getName() + "." + Twine(i));
+          bool markPrecise = hasPrecise;
+          if (SA) {
+            DxilFieldAnnotation &FA = SA->GetFieldAnnotation(i);
+            markPrecise |= FA.IsPrecise();
+          }
+          if (markPrecise)
+            HLModule::MarkPreciseAttributeWithMetadata(NA);
+          Elts.push_back(NA);
+        }
+      } else {
+        // For local resource array which not dynamic indexing,
+        // split it.
+        if (dxilutil::HasDynamicIndexing(V) ||
+            // Only support 1 dim split.
+            nestArrayTys.size() > 1)
+          return false;
+        for (int i = 0, e = AT->getNumElements(); i != e; ++i) {
+          AllocaInst *NA = Builder.CreateAlloca(ElTy, nullptr,
+                                                V->getName() + "." + Twine(i));
+          Elts.push_back(NA);
         }
         }
-        if (markPrecise)
-          HLModule::MarkPreciseAttributeWithMetadata(NA);
-        Elts.push_back(NA);
       }
       }
     } else if (ElTy->isVectorTy()) {
     } else if (ElTy->isVectorTy()) {
       // Skip vector if required.
       // Skip vector if required.
@@ -6727,15 +6738,7 @@ Constant *DynamicIndexingVectorToArray::lowerInitVal(Constant *InitVal, Type *Ne
 }
 }
 
 
 bool DynamicIndexingVectorToArray::HasVectorDynamicIndexing(Value *V) {
 bool DynamicIndexingVectorToArray::HasVectorDynamicIndexing(Value *V) {
-  for (auto User : V->users()) {
-    if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
-      for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) {
-        if (!isa<ConstantInt>(Idx))
-          return true;
-      }
-    }
-  }
-  return false;
+  return dxilutil::HasDynamicIndexing(V);
 }
 }
 
 
 }
 }

+ 17 - 0
tools/clang/test/CodeGenHLSL/quick-test/local_res_array.hlsl

@@ -0,0 +1,17 @@
+// RUN: %dxc -T cs_6_0 -E main %s | FileCheck %s
+
+// Make sure simple local resource array works.
+// CHECK: main
+
+RWByteAddressBuffer outputBuffer;
+RWByteAddressBuffer outputBuffer2;
+
+[numthreads(8, 8, 1)]
+void main( uint2 id : SV_DispatchThreadID )
+{
+	RWByteAddressBuffer buffer[2];
+	buffer[0] = outputBuffer;
+	buffer[1] = outputBuffer2;
+    buffer[0].Store(id.x, id.y);
+    buffer[1].Store(id.y, id.x);
+} 

+ 16 - 0
tools/clang/test/CodeGenHLSL/quick-test/local_res_array2.hlsl

@@ -0,0 +1,16 @@
+// RUN: %dxc -T cs_6_0 -E main %s | FileCheck %s
+
+// Report error when cannot promote local resource.
+// CHECK: non-promotable local resource found
+
+RWByteAddressBuffer outputBuffer;
+RWByteAddressBuffer outputBuffer2;
+uint i;
+[numthreads(8, 8, 1)]
+void main( uint2 id : SV_DispatchThreadID )
+{
+	RWByteAddressBuffer buffer[2];
+	buffer[0] = outputBuffer;
+	buffer[1] = outputBuffer2;
+    buffer[i].Store(id.y, id.x);
+}

+ 16 - 10
tools/clang/tools/dotnetc/EditorForm.cs

@@ -534,16 +534,22 @@ namespace MainNs
                     string[] arguments = fileVars.Arguments;
                     string[] arguments = fileVars.Arguments;
                     if (isDxil)
                     if (isDxil)
                     {
                     {
-                        var result = compiler.Compile(source, fileName, fileVars.Entry, fileVars.Target, arguments, arguments.Length, null, 0, library.CreateIncludeHandler());
-                        if (result.GetStatus() == 0)
-                        {
-                            this.SelectedShaderBlob = result.GetResult();
-                            this.DisassembleSelectedShaderBlob();
-                        }
-                        else
-                        {
-                            this.colorizationService.ClearColorization(this.DisassemblyTextBox);
-                            this.DisassemblyTextBox.Text = GetStringFromBlob(result.GetErrors());
+                        try
+                        {
+                            var result = compiler.Compile(source, fileName, fileVars.Entry, fileVars.Target, arguments, arguments.Length, null, 0, library.CreateIncludeHandler());
+                            if (result.GetStatus() == 0)
+                            {
+                                this.SelectedShaderBlob = result.GetResult();
+                                this.DisassembleSelectedShaderBlob();
+                            }
+                            else
+                            {
+                                this.colorizationService.ClearColorization(this.DisassemblyTextBox);
+                                this.DisassemblyTextBox.Text = GetStringFromBlob(result.GetErrors());
+                            }
+                        } catch (Exception e)
+                        {
+                            DisassemblyTextBox.Text = e.ToString();
                         }
                         }
                     }
                     }
                     else
                     else

+ 15 - 1
tools/clang/tools/dxcompiler/dxcompilerobj.cpp

@@ -566,8 +566,22 @@ public:
       }
       }
 
 
       hr = S_OK;
       hr = S_OK;
+    } catch (std::bad_alloc &) {
+      hr = E_OUTOFMEMORY;
+    } catch (hlsl::Exception &e) {
+      _Analysis_assume_(DXC_FAILED(e.hr));
+      if (e.hr == DXC_E_ABORT_COMPILATION_ERROR) {
+        e.hr = S_OK;
+        CComPtr<IDxcBlobEncoding> pErrorBlob;
+        IFT(DxcCreateBlobWithEncodingOnHeapCopy(e.msg.c_str(), e.msg.size(),
+                                                CP_UTF8, &pErrorBlob));
+        IFT(DxcOperationResult::CreateFromResultErrorStatus(
+            nullptr, pErrorBlob, DXC_E_GENERAL_INTERNAL_ERROR, ppResult));
+      }
+      hr = e.hr;
+    } catch (...) {
+      hr = E_FAIL;
     }
     }
-    CATCH_CPP_ASSIGN_HRESULT();
   Cleanup:
   Cleanup:
     DxcEtw_DXCompilerCompile_Stop(hr);
     DxcEtw_DXCompilerCompile_Stop(hr);
     return hr;
     return hr;