Просмотр исходного кода

Fixes #679 - missing scenario with *it is of type FunctionDecl (#1012)

Functions within cbuffers declarations are effectively global functions.
Includes a test case for copying cbuffers that have nested functions.
Marcelo Lopez Ruiz 7 лет назад
Родитель
Сommit
a3b3c37720

+ 8 - 2
tools/clang/lib/CodeGen/CGHLSLMS.cpp

@@ -2546,10 +2546,16 @@ uint32_t CGMSHLSLRuntime::AddCBuffer(HLSLBufferDecl *D) {
     auto declsEnds = D->decls_end();
     CB->SetRangeSize(1);
     for (auto it = D->decls_begin(); it != declsEnds; it++) {
-      if (VarDecl *constDecl = dyn_cast<VarDecl>(*it))
+      if (VarDecl *constDecl = dyn_cast<VarDecl>(*it)) {
         AddConstant(constDecl, *CB.get());
-      else if (isa<EmptyDecl>(*it)) {
+      } else if (isa<EmptyDecl>(*it)) {
+        // Nothing to do for this declaration.
       } else if (isa<CXXRecordDecl>(*it)) {
+        // Nothing to do for this declaration.
+      } else if (isa<FunctionDecl>(*it)) {
+        // A function within an cbuffer is effectively a top-level function,
+        // as it only refers to globally scoped declarations.
+        this->CGM.EmitTopLevelDecl(*it);
       } else {
         HLSLBufferDecl *inner = cast<HLSLBufferDecl>(*it);
         GetOrCreateCBuffer(inner);

+ 22 - 0
tools/clang/test/CodeGenHLSL/cbuffer_fn.hlsl

@@ -0,0 +1,22 @@
+// RUN: %dxc -E VSMain -T vs_6_0 %s | FileCheck %s
+
+// CHECK: call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(
+
+cbuffer C {
+  float4 f4;
+  float4 get_f4() { return f4; }
+};
+
+struct PSInput {
+ float4 position : SV_POSITION;
+ float4 color : COLOR;
+};
+
+PSInput VSMain(float4 position: POSITION, float4 color: COLOR) {
+ float aspect = 320.0 / 200.0;
+ PSInput result;
+ result.position = position;
+ result.position.y *= aspect;
+ result.color = color * get_f4();
+ return result;
+}

+ 27 - 0
tools/clang/test/CodeGenHLSL/cbuffer_fn_copy.hlsl

@@ -0,0 +1,27 @@
+// RUN: %dxc -E VSMain -T vs_6_0 %s | FileCheck %s
+
+// CHECK: call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(
+
+struct S {
+  float4 f4;
+  float4 get_f4() { return f4; }
+};
+
+cbuffer C {
+  S s1;
+  S s2;
+};
+
+struct PSInput {
+ float4 position : SV_POSITION;
+ float4 color : COLOR;
+};
+
+PSInput VSMain(float4 position: POSITION, float4 color: COLOR) {
+ float aspect = 320.0 / 200.0;
+ PSInput result;
+ S s3 = s2;
+ result.position = s1.get_f4();
+ result.color = s2.get_f4() * s3.get_f4();
+ return result;
+}

+ 10 - 0
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -501,6 +501,8 @@ public:
   TEST_METHOD(CodeGenCbufferCopy2)
   TEST_METHOD(CodeGenCbufferCopy3)
   TEST_METHOD(CodeGenCbufferCopy4)
+  TEST_METHOD(CodeGenCbufferWithFunction)
+  TEST_METHOD(CodeGenCbufferWithFunctionCopy)
   TEST_METHOD(CodeGenCbuffer_unused)
   TEST_METHOD(CodeGenCbuffer1_50)
   TEST_METHOD(CodeGenCbuffer1_51)
@@ -3181,6 +3183,14 @@ TEST_F(CompilerTest, CodeGenCbufferCopy4) {
   CodeGenTestCheck(L"..\\CodeGenHLSL\\cbuffer_copy4.hlsl");
 }
 
+TEST_F(CompilerTest, CodeGenCbufferWithFunction) {
+  CodeGenTestCheck(L"..\\CodeGenHLSL\\cbuffer_fn.hlsl");
+}
+
+TEST_F(CompilerTest, CodeGenCbufferWithFunctionCopy) {
+  CodeGenTestCheck(L"..\\CodeGenHLSL\\cbuffer_fn_copy.hlsl");
+}
+
 TEST_F(CompilerTest, CodeGenCbuffer_unused) {
   CodeGenTest(L"..\\CodeGenHLSL\\cbuffer_unused.hlsl");
 }