소스 검색

[DxbcConverter] Fix corruption of ICB integer values (#4790)

Use an array of 32-bit integer values instead of 32-bit float values for the `"dx.icb"` immediate constant buffer data.
This prevents the FPU flipping the 22nd bit of integer constants, when their bit pattern represents a float32 signalling NaN on x86 architecture.

Fixes #4786
Ben Clayton 2 년 전
부모
커밋
0a1f7a19f4

+ 3 - 3
projects/dxilconv/lib/DxbcConverter/DxbcConverter.cpp

@@ -2127,9 +2127,9 @@ void DxbcConverter::ConvertInstructions(D3D10ShaderBinary::CShaderCodeParser &Pa
         unsigned Size = Inst.m_CustomData.DataSizeInBytes >> 2;
         DXASSERT_DXBC(m_pIcbGV == nullptr && Inst.m_CustomData.DataSizeInBytes == Size*4);
 
-        llvm::Constant *pIcbData = ConstantDataArray::get(m_Ctx, ArrayRef<float>((float*)Inst.m_CustomData.pData, Size));
+        llvm::Constant *pIcbData = ConstantDataArray::get(m_Ctx, ArrayRef<uint32_t>((uint32_t*)Inst.m_CustomData.pData, Size));
         m_pIcbGV = new GlobalVariable(*m_pModule, pIcbData->getType(), true, GlobalValue::InternalLinkage,
-                                      pIcbData, "dx.icb", nullptr, 
+                                      pIcbData, "dx.icb", nullptr,
                                       GlobalVariable::NotThreadLocal, DXIL::kImmediateCBufferAddrSpace);
       }
       break;
@@ -6074,7 +6074,7 @@ void DxbcConverter::LoadOperand(OperandValue &SrcVal,
         Value *pPtr = m_pBuilder->CreateGEP(m_pIcbGV, pGEPIndices);
         LoadInst *pLoad = m_pBuilder->CreateLoad(pPtr);
         pLoad->setAlignment(kRegCompAlignment);
-        Value *pValue = CastDxbcValue(pLoad, CompType::getF32(), ValueType);
+        Value *pValue = CastDxbcValue(pLoad, CompType::getU32(), ValueType);
         pValue = ApplyOperandModifiers(pValue, O);
       
         OVH.SetValue(pValue);

+ 117 - 94
projects/dxilconv/test/dxbc2dxil/icb1.ref

@@ -1,5 +1,5 @@
 
[email protected] = internal addrspace(5) constant [16 x float] [float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 1.000000e+00]
[email protected] = internal addrspace(5) constant [16 x i32] [i32 1065353216, i32 0, i32 0, i32 0, i32 0, i32 1065353216, i32 0, i32 0, i32 0, i32 0, i32 1065353216, i32 0, i32 0, i32 0, i32 0, i32 1065353216]
 
 define void @main() {
 entry:
@@ -11,102 +11,122 @@ entry:
   %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 3, i32 undef)
   %6 = mul i32 %1, 4
   %7 = add i32 %6, 0
-  %8 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %7
-  %9 = load float, float addrspace(5)* %8, align 4
-  %10 = mul i32 %1, 4
-  %11 = add i32 %10, 1
-  %12 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %11
-  %13 = load float, float addrspace(5)* %12, align 4
-  %14 = mul i32 %1, 4
-  %15 = add i32 %14, 2
-  %16 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %15
-  %17 = load float, float addrspace(5)* %16, align 4
-  %18 = mul i32 %1, 4
-  %19 = add i32 %18, 3
-  %20 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %19
-  %21 = load float, float addrspace(5)* %20, align 4
-  %22 = call float @dx.op.dot4.f32(i32 56, float %2, float %3, float %4, float %5, float %9, float %13, float %17, float %21)
-  %23 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef)
-  %24 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef)
-  %25 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 2, i32 undef)
-  %26 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 3, i32 undef)
-  %27 = mul i32 %1, 4
-  %28 = add i32 %27, 0
-  %29 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %28
-  %30 = load float, float addrspace(5)* %29, align 4
+  %8 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %7
+  %9 = load i32, i32 addrspace(5)* %8, align 4
+  %10 = call float @dx.op.bitcastI32toF32(i32 126, i32 %9)
+  %11 = mul i32 %1, 4
+  %12 = add i32 %11, 1
+  %13 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %12
+  %14 = load i32, i32 addrspace(5)* %13, align 4
+  %15 = call float @dx.op.bitcastI32toF32(i32 126, i32 %14)
+  %16 = mul i32 %1, 4
+  %17 = add i32 %16, 2
+  %18 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %17
+  %19 = load i32, i32 addrspace(5)* %18, align 4
+  %20 = call float @dx.op.bitcastI32toF32(i32 126, i32 %19)
+  %21 = mul i32 %1, 4
+  %22 = add i32 %21, 3
+  %23 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %22
+  %24 = load i32, i32 addrspace(5)* %23, align 4
+  %25 = call float @dx.op.bitcastI32toF32(i32 126, i32 %24)
+  %26 = call float @dx.op.dot4.f32(i32 56, float %2, float %3, float %4, float %5, float %10, float %15, float %20, float %25)
+  %27 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef)
+  %28 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef)
+  %29 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 2, i32 undef)
+  %30 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 3, i32 undef)
   %31 = mul i32 %1, 4
-  %32 = add i32 %31, 1
-  %33 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %32
-  %34 = load float, float addrspace(5)* %33, align 4
-  %35 = mul i32 %1, 4
-  %36 = add i32 %35, 2
-  %37 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %36
-  %38 = load float, float addrspace(5)* %37, align 4
-  %39 = mul i32 %1, 4
-  %40 = add i32 %39, 3
-  %41 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %40
-  %42 = load float, float addrspace(5)* %41, align 4
-  %43 = call float @dx.op.dot4.f32(i32 56, float %23, float %24, float %25, float %26, float %30, float %34, float %38, float %42)
-  %44 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 0, i32 undef)
-  %45 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 1, i32 undef)
-  %46 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 2, i32 undef)
-  %47 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 3, i32 undef)
-  %48 = mul i32 %1, 4
-  %49 = add i32 %48, 0
-  %50 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %49
-  %51 = load float, float addrspace(5)* %50, align 4
-  %52 = mul i32 %1, 4
-  %53 = add i32 %52, 1
-  %54 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %53
-  %55 = load float, float addrspace(5)* %54, align 4
+  %32 = add i32 %31, 0
+  %33 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %32
+  %34 = load i32, i32 addrspace(5)* %33, align 4
+  %35 = call float @dx.op.bitcastI32toF32(i32 126, i32 %34)
+  %36 = mul i32 %1, 4
+  %37 = add i32 %36, 1
+  %38 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %37
+  %39 = load i32, i32 addrspace(5)* %38, align 4
+  %40 = call float @dx.op.bitcastI32toF32(i32 126, i32 %39)
+  %41 = mul i32 %1, 4
+  %42 = add i32 %41, 2
+  %43 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %42
+  %44 = load i32, i32 addrspace(5)* %43, align 4
+  %45 = call float @dx.op.bitcastI32toF32(i32 126, i32 %44)
+  %46 = mul i32 %1, 4
+  %47 = add i32 %46, 3
+  %48 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %47
+  %49 = load i32, i32 addrspace(5)* %48, align 4
+  %50 = call float @dx.op.bitcastI32toF32(i32 126, i32 %49)
+  %51 = call float @dx.op.dot4.f32(i32 56, float %27, float %28, float %29, float %30, float %35, float %40, float %45, float %50)
+  %52 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 0, i32 undef)
+  %53 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 1, i32 undef)
+  %54 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 2, i32 undef)
+  %55 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 3, i32 undef)
   %56 = mul i32 %1, 4
-  %57 = add i32 %56, 2
-  %58 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %57
-  %59 = load float, float addrspace(5)* %58, align 4
-  %60 = mul i32 %1, 4
-  %61 = add i32 %60, 3
-  %62 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %61
-  %63 = load float, float addrspace(5)* %62, align 4
-  %64 = call float @dx.op.dot4.f32(i32 56, float %44, float %45, float %46, float %47, float %51, float %55, float %59, float %63)
-  %65 = call float @dx.op.loadInput.f32(i32 4, i32 3, i32 0, i8 0, i32 undef)
-  %66 = call float @dx.op.loadInput.f32(i32 4, i32 3, i32 0, i8 1, i32 undef)
-  %67 = call float @dx.op.loadInput.f32(i32 4, i32 3, i32 0, i8 2, i32 undef)
-  %68 = call float @dx.op.loadInput.f32(i32 4, i32 3, i32 0, i8 3, i32 undef)
-  %69 = mul i32 %1, 4
-  %70 = add i32 %69, 0
-  %71 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %70
-  %72 = load float, float addrspace(5)* %71, align 4
-  %73 = mul i32 %1, 4
-  %74 = add i32 %73, 1
-  %75 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %74
-  %76 = load float, float addrspace(5)* %75, align 4
-  %77 = mul i32 %1, 4
-  %78 = add i32 %77, 2
-  %79 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %78
-  %80 = load float, float addrspace(5)* %79, align 4
+  %57 = add i32 %56, 0
+  %58 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %57
+  %59 = load i32, i32 addrspace(5)* %58, align 4
+  %60 = call float @dx.op.bitcastI32toF32(i32 126, i32 %59)
+  %61 = mul i32 %1, 4
+  %62 = add i32 %61, 1
+  %63 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %62
+  %64 = load i32, i32 addrspace(5)* %63, align 4
+  %65 = call float @dx.op.bitcastI32toF32(i32 126, i32 %64)
+  %66 = mul i32 %1, 4
+  %67 = add i32 %66, 2
+  %68 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %67
+  %69 = load i32, i32 addrspace(5)* %68, align 4
+  %70 = call float @dx.op.bitcastI32toF32(i32 126, i32 %69)
+  %71 = mul i32 %1, 4
+  %72 = add i32 %71, 3
+  %73 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %72
+  %74 = load i32, i32 addrspace(5)* %73, align 4
+  %75 = call float @dx.op.bitcastI32toF32(i32 126, i32 %74)
+  %76 = call float @dx.op.dot4.f32(i32 56, float %52, float %53, float %54, float %55, float %60, float %65, float %70, float %75)
+  %77 = call float @dx.op.loadInput.f32(i32 4, i32 3, i32 0, i8 0, i32 undef)
+  %78 = call float @dx.op.loadInput.f32(i32 4, i32 3, i32 0, i8 1, i32 undef)
+  %79 = call float @dx.op.loadInput.f32(i32 4, i32 3, i32 0, i8 2, i32 undef)
+  %80 = call float @dx.op.loadInput.f32(i32 4, i32 3, i32 0, i8 3, i32 undef)
   %81 = mul i32 %1, 4
-  %82 = add i32 %81, 3
-  %83 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %82
-  %84 = load float, float addrspace(5)* %83, align 4
-  %85 = call float @dx.op.dot4.f32(i32 56, float %65, float %66, float %67, float %68, float %72, float %76, float %80, float %84)
-  %86 = mul i32 %0, 4
-  %87 = add i32 %86, 0
-  %88 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %87
-  %89 = load float, float addrspace(5)* %88, align 4
-  %90 = mul i32 %0, 4
-  %91 = add i32 %90, 1
-  %92 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %91
-  %93 = load float, float addrspace(5)* %92, align 4
-  %94 = mul i32 %0, 4
-  %95 = add i32 %94, 2
-  %96 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %95
-  %97 = load float, float addrspace(5)* %96, align 4
-  %98 = mul i32 %0, 4
-  %99 = add i32 %98, 3
-  %100 = getelementptr [16 x float], [16 x float] addrspace(5)* @dx.icb, i32 0, i32 %99
-  %101 = load float, float addrspace(5)* %100, align 4
-  %102 = call float @dx.op.dot4.f32(i32 56, float %22, float %43, float %64, float %85, float %89, float %93, float %97, float %101)
-  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %102)
+  %82 = add i32 %81, 0
+  %83 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %82
+  %84 = load i32, i32 addrspace(5)* %83, align 4
+  %85 = call float @dx.op.bitcastI32toF32(i32 126, i32 %84)
+  %86 = mul i32 %1, 4
+  %87 = add i32 %86, 1
+  %88 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %87
+  %89 = load i32, i32 addrspace(5)* %88, align 4
+  %90 = call float @dx.op.bitcastI32toF32(i32 126, i32 %89)
+  %91 = mul i32 %1, 4
+  %92 = add i32 %91, 2
+  %93 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %92
+  %94 = load i32, i32 addrspace(5)* %93, align 4
+  %95 = call float @dx.op.bitcastI32toF32(i32 126, i32 %94)
+  %96 = mul i32 %1, 4
+  %97 = add i32 %96, 3
+  %98 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %97
+  %99 = load i32, i32 addrspace(5)* %98, align 4
+  %100 = call float @dx.op.bitcastI32toF32(i32 126, i32 %99)
+  %101 = call float @dx.op.dot4.f32(i32 56, float %77, float %78, float %79, float %80, float %85, float %90, float %95, float %100)
+  %102 = mul i32 %0, 4
+  %103 = add i32 %102, 0
+  %104 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %103
+  %105 = load i32, i32 addrspace(5)* %104, align 4
+  %106 = call float @dx.op.bitcastI32toF32(i32 126, i32 %105)
+  %107 = mul i32 %0, 4
+  %108 = add i32 %107, 1
+  %109 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %108
+  %110 = load i32, i32 addrspace(5)* %109, align 4
+  %111 = call float @dx.op.bitcastI32toF32(i32 126, i32 %110)
+  %112 = mul i32 %0, 4
+  %113 = add i32 %112, 2
+  %114 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %113
+  %115 = load i32, i32 addrspace(5)* %114, align 4
+  %116 = call float @dx.op.bitcastI32toF32(i32 126, i32 %115)
+  %117 = mul i32 %0, 4
+  %118 = add i32 %117, 3
+  %119 = getelementptr [16 x i32], [16 x i32] addrspace(5)* @dx.icb, i32 0, i32 %118
+  %120 = load i32, i32 addrspace(5)* %119, align 4
+  %121 = call float @dx.op.bitcastI32toF32(i32 126, i32 %120)
+  %122 = call float @dx.op.dot4.f32(i32 56, float %26, float %51, float %76, float %101, float %106, float %111, float %116, float %121)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %122)
   ret void
 }
 
@@ -125,6 +145,9 @@ declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
 ; Function Attrs: nounwind readonly
 declare i32 @dx.op.tempRegLoad.i32(i32, i32) #2
 
+; Function Attrs: nounwind readnone
+declare float @dx.op.bitcastI32toF32(i32, i32) #0
+
 ; Function Attrs: nounwind
 declare void @dx.op.tempRegStore.f32(i32, i32, float) #1
 

BIN
projects/dxilconv/test/dxbc2dxil/icb2.dxbc


+ 16 - 0
projects/dxilconv/test/dxbc2dxil/icb2.hlsl

@@ -0,0 +1,16 @@
+// FXC command line: fxc /T ps_5_0 %s /Fo %t.dxbc
+// RUN: %dxbc2dxil %t.dxbc /emit-llvm /o %t.ll.converted
+// RUN: fc %b.ref %t.ll.converted
+
+RWByteAddressBuffer b : register(u0, space0);
+
+[numthreads(1, 1, 1)]
+void main() {
+  {
+    for(uint i = 0u; (i < 3u); i = (i + 1u)) {
+      const uint icb[3] = {0xffbfffcau, 0x09909909u, 1u};
+      b.Store((4u * min(i, 2u)), asuint(icb[min(i, 2u)]));
+    }
+  }
+  return;
+}

+ 66 - 0
projects/dxilconv/test/dxbc2dxil/icb2.ref

@@ -0,0 +1,66 @@
+
+%dx.types.Handle = type { i8* }
+%dx.types.u32 = type { i32 }
+
[email protected] = internal addrspace(5) constant [12 x i32] [i32 -4194358, i32 0, i32 0, i32 0, i32 160471305, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0]
+
+define void @main() {
+entry:
+  br label %loop0
+
+loop0:                                            ; preds = %loop0.breakc0, %entry
+  %dx.v32.r0.0 = phi i32 [ 0, %entry ], [ %8, %loop0.breakc0 ]
+  %0 = icmp uge i32 %dx.v32.r0.0, 3
+  br i1 %0, label %loop0.end, label %loop0.breakc0
+
+loop0.breakc0:                                    ; preds = %loop0
+  %1 = call i32 @dx.op.binary.i32(i32 40, i32 %dx.v32.r0.0, i32 2)
+  %2 = shl i32 %1, 2
+  %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 0, i1 false)
+  %4 = mul i32 %1, 4
+  %5 = add i32 %4, 0
+  %6 = getelementptr [12 x i32], [12 x i32] addrspace(5)* @dx.icb, i32 0, i32 %5
+  %7 = load i32, i32 addrspace(5)* %6, align 4
+  call void @dx.op.bufferStore.i32(i32 69, %dx.types.Handle %3, i32 %2, i32 undef, i32 %7, i32 undef, i32 undef, i32 undef, i8 1)
+  %8 = add i32 %dx.v32.r0.0, 1
+  br label %loop0
+
+loop0.end:                                        ; preds = %loop0
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @dx.op.tempRegStore.i32(i32, i32, i32) #0
+
+; Function Attrs: nounwind readonly
+declare i32 @dx.op.tempRegLoad.i32(i32, i32) #1
+
+; Function Attrs: nounwind readnone
+declare i32 @dx.op.binary.i32(i32, i32, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #1
+
+; Function Attrs: nounwind
+declare void @dx.op.bufferStore.i32(i32, %dx.types.Handle, i32, i32, i32, i32, i32, i32, i8) #0
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readonly }
+attributes #2 = { nounwind readnone }
+
+!dx.version = !{!0}
+!dx.valver = !{!0}
+!dx.shaderModel = !{!1}
+!dx.resources = !{!2}
+!dx.entryPoints = !{!5}
+!llvm.ident = !{!8}
+
+!0 = !{i32 1, i32 0}
+!1 = !{!"cs", i32 6, i32 0}
+!2 = !{null, !3, null, null}
+!3 = !{!4}
+!4 = !{i32 0, %dx.types.u32 addrspace(1)* undef, !"U0", i32 0, i32 0, i32 1, i32 11, i1 false, i1 false, i1 false, null}
+!5 = !{void ()* @main, !"main", null, !2, !6}
+!6 = !{i32 4, !7}
+!7 = !{i32 1, i32 1, i32 1}
+!8 = !{!"dxbc2dxil 1.2"}