Browse Source

Fill in usage flags for constant buffers for library reflection. (#2028)

TODO: drill into ConstantBuffer<> type to make cbuffer reflection useful here.  The change would be something like this: CShaderReflectionConstantBuffer::Initialize:
   if (!annotation)
     return;

+  if (ST->getNumElements() == 1 &&
+      isa<StructType>(Ty->getContainedType(0)) &&
+      annotation->GetFieldAnnotation(0).GetFieldName() == CB.GetGlobalName()) {
+    // Assume we need to drill one level deeper into struct.
+    // This is the case when you use ConstantBuffer<MyStruct> ...
+    // It could also misfire in a narrow case where you use:
+    // struct MyStruct { ... }; cbuffer MyCBuffer { MyStruct MyCBuffer; }
+    // But the effect would be to drill one level into MyCBuffer for cbuffer VarDesc,
+    // which wouldn't be bad.
+    ST = cast<StructType>(Ty->getContainedType(0));
+    annotation =
+      typeSys.GetStructAnnotation(cast<StructType>(ST));
+  }
+
   m_Desc.Variables = ST->getNumContainedTypes();
   unsigned lastIndex = ST->getNumContainedTypes() - 1;
Tex Riddell 6 years ago
parent
commit
00089a69b4

+ 28 - 0
lib/HLSL/DxilContainerReflection.cpp

@@ -12,6 +12,7 @@
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Operator.h"
 #include "dxc/DxilContainer/DxilContainer.h"
 #include "dxc/DXIL/DxilModule.h"
 #include "dxc/DXIL/DxilShaderModel.h"
@@ -203,6 +204,7 @@ private:
 
   void AddResourceUseToFunctions(DxilResourceBase &resource, unsigned resIndex);
   void AddResourceDependencies();
+  void SetCBufferUsage();
 
 public:
   DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
@@ -2324,6 +2326,31 @@ void DxilLibraryReflection::AddResourceDependencies() {
   }
 }
 
+static void CollectCBufUsageForLib(Value *V, std::vector<unsigned> &cbufUsage) {
+  for (auto user : V->users()) {
+    Value *V = user;
+    if (auto *CI = dyn_cast<CallInst>(V)) {
+      if (hlsl::OP::IsDxilOpFuncCallInst(CI, hlsl::OP::OpCode::CreateHandleForLib)) {
+        CollectCBufUsage(CI, cbufUsage);
+      }
+    } else if (isa<GEPOperator>(V) ||
+               isa<LoadInst>(V)) {
+      CollectCBufUsageForLib(user, cbufUsage);
+    }
+  }
+}
+
+void DxilLibraryReflection::SetCBufferUsage() {
+  unsigned cbSize = std::min(m_CBs.size(), m_pDxilModule->GetCBuffers().size());
+
+  for (unsigned i=0;i<cbSize;i++) {
+    std::vector<unsigned> cbufUsage;
+    CollectCBufUsageForLib(m_pDxilModule->GetCBuffer(i).GetGlobalSymbol(), cbufUsage);
+    SetCBufVarUsage(*m_CBs[i], cbufUsage);
+  }
+}
+
+
 // ID3D12LibraryReflection
 
 HRESULT DxilLibraryReflection::Load(IDxcBlob *pBlob,
@@ -2332,6 +2359,7 @@ HRESULT DxilLibraryReflection::Load(IDxcBlob *pBlob,
 
   try {
     AddResourceDependencies();
+    SetCBufferUsage();
     return S_OK;
   }
   CATCH_CPP_RETURN_HRESULT();

+ 52 - 0
tools/clang/test/CodeGenHLSL/quick-test/d3dreflect/cbuf-usage-lib.hlsl

@@ -0,0 +1,52 @@
+// RUN: %dxc -auto-binding-space 13 -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
+
+// Make sure usage flag is set properly for cbuffers used in libraries
+
+// CHECK-NOT: CBufUnused
+
+// CHECK: D3D12_SHADER_BUFFER_DESC: Name: CBuf1
+// CHECK: Num Variables: 1
+// CHECK: D3D12_SHADER_VARIABLE_DESC: Name: CBuf1
+// CHECK: uFlags: 0x2
+// CHECK: CBuffer: CBuf1
+
+// CHECK: D3D12_SHADER_BUFFER_DESC: Name: CBuf0
+// CHECK: Num Variables: 2
+// CHECK: D3D12_SHADER_VARIABLE_DESC: Name: i1
+// CHECK: uFlags: 0
+// CHECK: D3D12_SHADER_VARIABLE_DESC: Name: f1
+// CHECK: uFlags: 0x2
+// CHECK: CBuffer: CBuf0
+
+// CHECK: D3D12_SHADER_BUFFER_DESC: Name: CBuf2
+// CHECK: Num Variables: 1
+// CHECK: D3D12_SHADER_VARIABLE_DESC: Name: CBuf2
+// CHECK: uFlags: 0x2
+// CHECK: CBuffer: CBuf2
+
+cbuffer CBuf0 {
+  int i1;
+  float f1;
+}
+
+struct CBStruct {
+  int i2;
+  float f2;
+};
+
+ConstantBuffer<CBStruct> CBuf1;
+ConstantBuffer<CBStruct> CBufUnused;
+ConstantBuffer<CBStruct> CBuf2[];
+
+float unused_func() {
+  return CBufUnused.i2;
+}
+
+export float foo() {
+  return CBuf1.i2;
+}
+
+[shader("vertex")]
+float main(int idx : IDX) : OUT {
+  return f1 * CBuf2[idx].f2;
+}