瀏覽代碼

[dxil2spv] Add FileCheck testing (#4431)

Add FileCheck testing to dxil2spv, and a first static vertex shader test case to test #4426. Also includes documentation for how to add additional tests, and replaces the existing WholeFileTestFixture with regular FileCheck.
Natalie Chouinard 3 年之前
父節點
當前提交
d6cec44c6f

+ 4 - 0
include/dxc/Test/DxcTestUtils.h

@@ -126,6 +126,10 @@ private:
   FileRunCommandResult RunTee(const FileRunCommandResult *Prior);
   FileRunCommandResult RunXFail(const FileRunCommandResult *Prior);
   FileRunCommandResult RunDxilVer(dxc::DxcDllSupport& DllSupport, const FileRunCommandResult* Prior);
+#ifdef ENABLE_DXIL2SPV
+  FileRunCommandResult RunDxil2Spv(dxc::DxcDllSupport &DllSupport,
+                                   const FileRunCommandResult *Prior);
+#endif
   FileRunCommandResult RunDxcHashTest(dxc::DxcDllSupport &DllSupport);
   FileRunCommandResult RunFromPath(const std::string &path, const FileRunCommandResult *Prior);
   FileRunCommandResult RunFileCompareText(const FileRunCommandResult *Prior);

+ 11 - 10
tools/clang/unittests/HLSL/HLSLTestOptions.h → include/dxc/Test/HLSLTestOptions.h

@@ -26,18 +26,19 @@ namespace hlsl {
 namespace testOptions {
 
 /// \brief Command line option that specifies the path to the directory that
-/// contains files that have the HLSL source code (used for the CodeGen test flow).
+/// contains files that have the HLSL source code (used for the CodeGen test
+/// flow).
 #define ARG_DECLARE(argname) extern std::string argname;
 
-#define ARG_LIST(ARGOP)\
-    ARGOP(HlslDataDir)\
-    ARGOP(TestName)\
-    ARGOP(DXBC)\
-    ARGOP(SaveImages)\
-    ARGOP(ExperimentalShaders)\
-    ARGOP(DebugLayer)\
-    ARGOP(SuitePath)\
-    ARGOP(InputPath)
+#define ARG_LIST(ARGOP)                                                        \
+  ARGOP(HlslDataDir)                                                           \
+  ARGOP(TestName)                                                              \
+  ARGOP(DXBC)                                                                  \
+  ARGOP(SaveImages)                                                            \
+  ARGOP(ExperimentalShaders)                                                   \
+  ARGOP(DebugLayer)                                                            \
+  ARGOP(SuitePath)                                                             \
+  ARGOP(InputPath)
 
 ARG_LIST(ARG_DECLARE)
 

+ 91 - 92
tools/clang/test/Dxil2Spv/passthru-cs.ll

@@ -1,4 +1,4 @@
-; RUN: %dxil2spv
+; RUN: %dxil2spv | %FileCheck %s
 ;
 ; Input signature:
 ;
@@ -82,94 +82,93 @@ attributes #2 = { nounwind }
 !10 = !{i32 0, i64 16, i32 4, !11}
 !11 = !{i32 1, i32 1, i32 1}
 
-; CHECK-WHOLE-SPIR-V:
-; ; SPIR-V
-; ; Version: 1.0
-; ; Generator: Google spiregg; 0
-; ; Bound: 59
-; ; Schema: 0
-;                OpCapability Shader
-;                OpMemoryModel Logical GLSL450
-;                OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
-;                OpExecutionMode %main LocalSize 1 1 1
-;                OpName %type_ByteAddressBuffer "type.ByteAddressBuffer"
-;                OpName %type_RWByteAddressBuffer "type.RWByteAddressBuffer"
-;                OpName %main "main"
-;                OpName %dx_types_ResRet_i32 "dx.types.ResRet.i32"
-;                OpDecorate %3 DescriptorSet 0
-;                OpDecorate %3 Binding 0
-;                OpDecorate %4 DescriptorSet 0
-;                OpDecorate %4 Binding 1
-;                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
-;                OpDecorate %_runtimearr_uint ArrayStride 4
-;                OpMemberDecorate %type_ByteAddressBuffer 0 Offset 0
-;                OpMemberDecorate %type_ByteAddressBuffer 0 NonWritable
-;                OpDecorate %type_ByteAddressBuffer BufferBlock
-;                OpMemberDecorate %type_RWByteAddressBuffer 0 Offset 0
-;                OpDecorate %type_RWByteAddressBuffer BufferBlock
-;        %uint = OpTypeInt 32 0
-;      %uint_0 = OpConstant %uint 0
-;      %uint_2 = OpConstant %uint 2
-;      %uint_1 = OpConstant %uint 1
-;      %uint_3 = OpConstant %uint 3
-;      %uint_4 = OpConstant %uint 4
-; %_runtimearr_uint = OpTypeRuntimeArray %uint
-; %type_ByteAddressBuffer = OpTypeStruct %_runtimearr_uint
-; %_ptr_Uniform_type_ByteAddressBuffer = OpTypePointer Uniform %type_ByteAddressBuffer
-; %type_RWByteAddressBuffer = OpTypeStruct %_runtimearr_uint
-; %_ptr_Uniform_type_RWByteAddressBuffer = OpTypePointer Uniform %type_RWByteAddressBuffer
-;      %v3uint = OpTypeVector %uint 3
-; %_ptr_Input_v3uint = OpTypePointer Input %v3uint
-;        %void = OpTypeVoid
-;          %19 = OpTypeFunction %void
-;         %int = OpTypeInt 32 1
-; %dx_types_ResRet_i32 = OpTypeStruct %int %int %int %int %int
-; %_ptr_Function_dx_types_ResRet_i32 = OpTypePointer Function %dx_types_ResRet_i32
-; %_ptr_Input_uint = OpTypePointer Input %uint
-; %_ptr_Uniform_uint = OpTypePointer Uniform %uint
-; %_ptr_Function_int = OpTypePointer Function %int
-;           %3 = OpVariable %_ptr_Uniform_type_ByteAddressBuffer Uniform
-;           %4 = OpVariable %_ptr_Uniform_type_RWByteAddressBuffer Uniform
-; %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
-;        %main = OpFunction %void None %19
-;          %20 = OpLabel
-;          %24 = OpVariable %_ptr_Function_dx_types_ResRet_i32 Function
-;          %26 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0
-;          %27 = OpLoad %uint %26
-;          %28 = OpShiftLeftLogical %uint %27 %uint_2
-;          %29 = OpIAdd %uint %28 %uint_0
-;          %31 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %29
-;          %32 = OpLoad %uint %31
-;          %34 = OpAccessChain %_ptr_Function_int %24 %uint_0
-;          %35 = OpBitcast %int %32
-;                OpStore %34 %35
-;          %36 = OpIAdd %uint %28 %uint_1
-;          %37 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %36
-;          %38 = OpLoad %uint %37
-;          %39 = OpAccessChain %_ptr_Function_int %24 %uint_1
-;          %40 = OpBitcast %int %38
-;                OpStore %39 %40
-;          %41 = OpIAdd %uint %28 %uint_2
-;          %42 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %41
-;          %43 = OpLoad %uint %42
-;          %44 = OpAccessChain %_ptr_Function_int %24 %uint_2
-;          %45 = OpBitcast %int %43
-;                OpStore %44 %45
-;          %46 = OpIAdd %uint %28 %uint_3
-;          %47 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %46
-;          %48 = OpLoad %uint %47
-;          %49 = OpAccessChain %_ptr_Function_int %24 %uint_3
-;          %50 = OpBitcast %int %48
-;                OpStore %49 %50
-;          %51 = OpIAdd %uint %28 %uint_4
-;          %52 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %51
-;          %53 = OpLoad %uint %52
-;          %54 = OpAccessChain %_ptr_Function_int %24 %uint_4
-;          %55 = OpBitcast %int %53
-;                OpStore %54 %55
-;          %56 = OpAccessChain %_ptr_Function_int %24 %uint_0
-;          %57 = OpAccessChain %_ptr_Uniform_uint %4 %uint_0 %28
-;          %58 = OpBitcast %uint %56
-;                OpStore %57 %58
-;                OpReturn
-;                OpFunctionEnd
+; CHECK:      ; SPIR-V
+; CHECK-NEXT: ; Version: 1.0
+; CHECK-NEXT: ; Generator: Google spiregg; 0
+; CHECK-NEXT: ; Bound: 59
+; CHECK-NEXT: ; Schema: 0
+; CHECK-NEXT:                OpCapability Shader
+; CHECK-NEXT:                OpMemoryModel Logical GLSL450
+; CHECK-NEXT:                OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
+; CHECK-NEXT:                OpExecutionMode %main LocalSize 1 1 1
+; CHECK-NEXT:                OpName %type_ByteAddressBuffer "type.ByteAddressBuffer"
+; CHECK-NEXT:                OpName %type_RWByteAddressBuffer "type.RWByteAddressBuffer"
+; CHECK-NEXT:                OpName %main "main"
+; CHECK-NEXT:                OpName %dx_types_ResRet_i32 "dx.types.ResRet.i32"
+; CHECK-NEXT:                OpDecorate %3 DescriptorSet 0
+; CHECK-NEXT:                OpDecorate %3 Binding 0
+; CHECK-NEXT:                OpDecorate %4 DescriptorSet 0
+; CHECK-NEXT:                OpDecorate %4 Binding 1
+; CHECK-NEXT:                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
+; CHECK-NEXT:                OpDecorate %_runtimearr_uint ArrayStride 4
+; CHECK-NEXT:                OpMemberDecorate %type_ByteAddressBuffer 0 Offset 0
+; CHECK-NEXT:                OpMemberDecorate %type_ByteAddressBuffer 0 NonWritable
+; CHECK-NEXT:                OpDecorate %type_ByteAddressBuffer BufferBlock
+; CHECK-NEXT:                OpMemberDecorate %type_RWByteAddressBuffer 0 Offset 0
+; CHECK-NEXT:                OpDecorate %type_RWByteAddressBuffer BufferBlock
+; CHECK-NEXT:        %uint = OpTypeInt 32 0
+; CHECK-NEXT:      %uint_0 = OpConstant %uint 0
+; CHECK-NEXT:      %uint_2 = OpConstant %uint 2
+; CHECK-NEXT:      %uint_1 = OpConstant %uint 1
+; CHECK-NEXT:      %uint_3 = OpConstant %uint 3
+; CHECK-NEXT:      %uint_4 = OpConstant %uint 4
+; CHECK-NEXT: %_runtimearr_uint = OpTypeRuntimeArray %uint
+; CHECK-NEXT: %type_ByteAddressBuffer = OpTypeStruct %_runtimearr_uint
+; CHECK-NEXT: %_ptr_Uniform_type_ByteAddressBuffer = OpTypePointer Uniform %type_ByteAddressBuffer
+; CHECK-NEXT: %type_RWByteAddressBuffer = OpTypeStruct %_runtimearr_uint
+; CHECK-NEXT: %_ptr_Uniform_type_RWByteAddressBuffer = OpTypePointer Uniform %type_RWByteAddressBuffer
+; CHECK-NEXT:      %v3uint = OpTypeVector %uint 3
+; CHECK-NEXT: %_ptr_Input_v3uint = OpTypePointer Input %v3uint
+; CHECK-NEXT:        %void = OpTypeVoid
+; CHECK-NEXT:          %19 = OpTypeFunction %void
+; CHECK-NEXT:         %int = OpTypeInt 32 1
+; CHECK-NEXT: %dx_types_ResRet_i32 = OpTypeStruct %int %int %int %int %int
+; CHECK-NEXT: %_ptr_Function_dx_types_ResRet_i32 = OpTypePointer Function %dx_types_ResRet_i32
+; CHECK-NEXT: %_ptr_Input_uint = OpTypePointer Input %uint
+; CHECK-NEXT: %_ptr_Uniform_uint = OpTypePointer Uniform %uint
+; CHECK-NEXT: %_ptr_Function_int = OpTypePointer Function %int
+; CHECK-NEXT:           %3 = OpVariable %_ptr_Uniform_type_ByteAddressBuffer Uniform
+; CHECK-NEXT:           %4 = OpVariable %_ptr_Uniform_type_RWByteAddressBuffer Uniform
+; CHECK-NEXT: %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
+; CHECK-NEXT:        %main = OpFunction %void None %19
+; CHECK-NEXT:          %20 = OpLabel
+; CHECK-NEXT:          %24 = OpVariable %_ptr_Function_dx_types_ResRet_i32 Function
+; CHECK-NEXT:          %26 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0
+; CHECK-NEXT:          %27 = OpLoad %uint %26
+; CHECK-NEXT:          %28 = OpShiftLeftLogical %uint %27 %uint_2
+; CHECK-NEXT:          %29 = OpIAdd %uint %28 %uint_0
+; CHECK-NEXT:          %31 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %29
+; CHECK-NEXT:          %32 = OpLoad %uint %31
+; CHECK-NEXT:          %34 = OpAccessChain %_ptr_Function_int %24 %uint_0
+; CHECK-NEXT:          %35 = OpBitcast %int %32
+; CHECK-NEXT:                OpStore %34 %35
+; CHECK-NEXT:          %36 = OpIAdd %uint %28 %uint_1
+; CHECK-NEXT:          %37 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %36
+; CHECK-NEXT:          %38 = OpLoad %uint %37
+; CHECK-NEXT:          %39 = OpAccessChain %_ptr_Function_int %24 %uint_1
+; CHECK-NEXT:          %40 = OpBitcast %int %38
+; CHECK-NEXT:                OpStore %39 %40
+; CHECK-NEXT:          %41 = OpIAdd %uint %28 %uint_2
+; CHECK-NEXT:          %42 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %41
+; CHECK-NEXT:          %43 = OpLoad %uint %42
+; CHECK-NEXT:          %44 = OpAccessChain %_ptr_Function_int %24 %uint_2
+; CHECK-NEXT:          %45 = OpBitcast %int %43
+; CHECK-NEXT:                OpStore %44 %45
+; CHECK-NEXT:          %46 = OpIAdd %uint %28 %uint_3
+; CHECK-NEXT:          %47 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %46
+; CHECK-NEXT:          %48 = OpLoad %uint %47
+; CHECK-NEXT:          %49 = OpAccessChain %_ptr_Function_int %24 %uint_3
+; CHECK-NEXT:          %50 = OpBitcast %int %48
+; CHECK-NEXT:                OpStore %49 %50
+; CHECK-NEXT:          %51 = OpIAdd %uint %28 %uint_4
+; CHECK-NEXT:          %52 = OpAccessChain %_ptr_Uniform_uint %3 %uint_0 %51
+; CHECK-NEXT:          %53 = OpLoad %uint %52
+; CHECK-NEXT:          %54 = OpAccessChain %_ptr_Function_int %24 %uint_4
+; CHECK-NEXT:          %55 = OpBitcast %int %53
+; CHECK-NEXT:                OpStore %54 %55
+; CHECK-NEXT:          %56 = OpAccessChain %_ptr_Function_int %24 %uint_0
+; CHECK-NEXT:          %57 = OpAccessChain %_ptr_Uniform_uint %4 %uint_0 %28
+; CHECK-NEXT:          %58 = OpBitcast %uint %56
+; CHECK-NEXT:                OpStore %57 %58
+; CHECK-NEXT:                OpReturn
+; CHECK-NEXT:                OpFunctionEnd

+ 52 - 53
tools/clang/test/Dxil2Spv/passthru-ps.ll

@@ -1,4 +1,4 @@
-; RUN: %dxil2spv
+; RUN: %dxil2spv | %FileCheck %s
 ;
 ; Input signature:
 ;
@@ -101,55 +101,54 @@ attributes #1 = { nounwind }
 !12 = !{!13}
 !13 = !{i32 0, !"SV_Target", i8 9, i8 16, !9, i8 0, i32 1, i8 4, i32 0, i8 0, !11}
 
-; CHECK-WHOLE-SPIR-V:
-; ; SPIR-V
-; ; Version: 1.0
-; ; Generator: Google spiregg; 0
-; ; Bound: 31
-; ; Schema: 0
-;                OpCapability Shader
-;                OpMemoryModel Logical GLSL450
-;                OpEntryPoint Fragment %PSMain "PSMain" %gl_Position %COLOR %SV_Target
-;                OpExecutionMode %PSMain OriginUpperLeft
-;                OpName %COLOR "COLOR"
-;                OpName %SV_Target "SV_Target"
-;                OpName %PSMain "PSMain"
-;                OpDecorate %gl_Position BuiltIn Position
-;                OpDecorate %COLOR Location 1
-;                OpDecorate %SV_Target Location 0
-;        %uint = OpTypeInt 32 0
-;      %uint_0 = OpConstant %uint 0
-;      %uint_1 = OpConstant %uint 1
-;      %uint_2 = OpConstant %uint 2
-;      %uint_3 = OpConstant %uint 3
-;       %float = OpTypeFloat 32
-;     %v4float = OpTypeVector %float 4
-; %_ptr_Input_v4float = OpTypePointer Input %v4float
-; %_ptr_Output_v4float = OpTypePointer Output %v4float
-;        %void = OpTypeVoid
-;          %15 = OpTypeFunction %void
-; %_ptr_Input_float = OpTypePointer Input %float
-; %_ptr_Output_float = OpTypePointer Output %float
-; %gl_Position = OpVariable %_ptr_Input_v4float Input
-;       %COLOR = OpVariable %_ptr_Input_v4float Input
-;   %SV_Target = OpVariable %_ptr_Output_v4float Output
-;      %PSMain = OpFunction %void None %15
-;          %16 = OpLabel
-;          %18 = OpAccessChain %_ptr_Input_float %COLOR %uint_0
-;          %19 = OpLoad %float %18
-;          %20 = OpAccessChain %_ptr_Input_float %COLOR %uint_1
-;          %21 = OpLoad %float %20
-;          %22 = OpAccessChain %_ptr_Input_float %COLOR %uint_2
-;          %23 = OpLoad %float %22
-;          %24 = OpAccessChain %_ptr_Input_float %COLOR %uint_3
-;          %25 = OpLoad %float %24
-;          %27 = OpAccessChain %_ptr_Output_float %SV_Target %uint_0
-;                OpStore %27 %19
-;          %28 = OpAccessChain %_ptr_Output_float %SV_Target %uint_1
-;                OpStore %28 %21
-;          %29 = OpAccessChain %_ptr_Output_float %SV_Target %uint_2
-;                OpStore %29 %23
-;          %30 = OpAccessChain %_ptr_Output_float %SV_Target %uint_3
-;                OpStore %30 %25
-;                OpReturn
-;                OpFunctionEnd
+; CHECK:      ; SPIR-V
+; CHECK-NEXT: ; Version: 1.0
+; CHECK-NEXT: ; Generator: Google spiregg; 0
+; CHECK-NEXT: ; Bound: 31
+; CHECK-NEXT: ; Schema: 0
+; CHECK-NEXT:                OpCapability Shader
+; CHECK-NEXT:                OpMemoryModel Logical GLSL450
+; CHECK-NEXT:                OpEntryPoint Fragment %PSMain "PSMain" %gl_Position %COLOR %SV_Target
+; CHECK-NEXT:                OpExecutionMode %PSMain OriginUpperLeft
+; CHECK-NEXT:                OpName %COLOR "COLOR"
+; CHECK-NEXT:                OpName %SV_Target "SV_Target"
+; CHECK-NEXT:                OpName %PSMain "PSMain"
+; CHECK-NEXT:                OpDecorate %gl_Position BuiltIn Position
+; CHECK-NEXT:                OpDecorate %COLOR Location 1
+; CHECK-NEXT:                OpDecorate %SV_Target Location 0
+; CHECK-NEXT:        %uint = OpTypeInt 32 0
+; CHECK-NEXT:      %uint_0 = OpConstant %uint 0
+; CHECK-NEXT:      %uint_1 = OpConstant %uint 1
+; CHECK-NEXT:      %uint_2 = OpConstant %uint 2
+; CHECK-NEXT:      %uint_3 = OpConstant %uint 3
+; CHECK-NEXT:       %float = OpTypeFloat 32
+; CHECK-NEXT:     %v4float = OpTypeVector %float 4
+; CHECK-NEXT: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK-NEXT: %_ptr_Output_v4float = OpTypePointer Output %v4float
+; CHECK-NEXT:        %void = OpTypeVoid
+; CHECK-NEXT:          %15 = OpTypeFunction %void
+; CHECK-NEXT: %_ptr_Input_float = OpTypePointer Input %float
+; CHECK-NEXT: %_ptr_Output_float = OpTypePointer Output %float
+; CHECK-NEXT: %gl_Position = OpVariable %_ptr_Input_v4float Input
+; CHECK-NEXT:       %COLOR = OpVariable %_ptr_Input_v4float Input
+; CHECK-NEXT:   %SV_Target = OpVariable %_ptr_Output_v4float Output
+; CHECK-NEXT:      %PSMain = OpFunction %void None %15
+; CHECK-NEXT:          %16 = OpLabel
+; CHECK-NEXT:          %18 = OpAccessChain %_ptr_Input_float %COLOR %uint_0
+; CHECK-NEXT:          %19 = OpLoad %float %18
+; CHECK-NEXT:          %20 = OpAccessChain %_ptr_Input_float %COLOR %uint_1
+; CHECK-NEXT:          %21 = OpLoad %float %20
+; CHECK-NEXT:          %22 = OpAccessChain %_ptr_Input_float %COLOR %uint_2
+; CHECK-NEXT:          %23 = OpLoad %float %22
+; CHECK-NEXT:          %24 = OpAccessChain %_ptr_Input_float %COLOR %uint_3
+; CHECK-NEXT:          %25 = OpLoad %float %24
+; CHECK-NEXT:          %27 = OpAccessChain %_ptr_Output_float %SV_Target %uint_0
+; CHECK-NEXT:                OpStore %27 %19
+; CHECK-NEXT:          %28 = OpAccessChain %_ptr_Output_float %SV_Target %uint_1
+; CHECK-NEXT:                OpStore %28 %21
+; CHECK-NEXT:          %29 = OpAccessChain %_ptr_Output_float %SV_Target %uint_2
+; CHECK-NEXT:                OpStore %29 %23
+; CHECK-NEXT:          %30 = OpAccessChain %_ptr_Output_float %SV_Target %uint_3
+; CHECK-NEXT:                OpStore %30 %25
+; CHECK-NEXT:                OpReturn
+; CHECK-NEXT:                OpFunctionEnd

+ 70 - 71
tools/clang/test/Dxil2Spv/passthru-vs.ll

@@ -1,4 +1,4 @@
-; RUN: %dxil2spv
+; RUN: %dxil2spv | %FileCheck %s
 ;
 ; Input signature:
 ;
@@ -115,73 +115,72 @@ attributes #1 = { nounwind }
 !13 = !{i32 0, !"SV_Position", i8 9, i8 3, !9, i8 4, i32 1, i8 4, i32 0, i8 0, !10}
 !14 = !{i32 1, !"COLOR", i8 9, i8 0, !9, i8 2, i32 1, i8 4, i32 1, i8 0, !10}
 
-; CHECK-WHOLE-SPIR-V:
-; ; SPIR-V
-; ; Version: 1.0
-; ; Generator: Google spiregg; 0
-; ; Bound: 44
-; ; Schema: 0
-;                OpCapability Shader
-;                OpMemoryModel Logical GLSL450
-;                OpEntryPoint Vertex %VSMain "VSMain" %POSITION %COLOR %gl_Position %COLOR_0
-;                OpName %POSITION "POSITION"
-;                OpName %COLOR "COLOR"
-;                OpName %COLOR_0 "COLOR"
-;                OpName %VSMain "VSMain"
-;                OpDecorate %POSITION Location 0
-;                OpDecorate %COLOR Location 1
-;                OpDecorate %gl_Position BuiltIn Position
-;                OpDecorate %COLOR_0 Location 1
-;        %uint = OpTypeInt 32 0
-;      %uint_0 = OpConstant %uint 0
-;      %uint_1 = OpConstant %uint 1
-;      %uint_2 = OpConstant %uint 2
-;      %uint_3 = OpConstant %uint 3
-;       %float = OpTypeFloat 32
-;     %v4float = OpTypeVector %float 4
-; %_ptr_Input_v4float = OpTypePointer Input %v4float
-; %_ptr_Output_v4float = OpTypePointer Output %v4float
-;        %void = OpTypeVoid
-;          %16 = OpTypeFunction %void
-; %_ptr_Input_float = OpTypePointer Input %float
-; %_ptr_Output_float = OpTypePointer Output %float
-;    %POSITION = OpVariable %_ptr_Input_v4float Input
-;       %COLOR = OpVariable %_ptr_Input_v4float Input
-; %gl_Position = OpVariable %_ptr_Output_v4float Output
-;     %COLOR_0 = OpVariable %_ptr_Output_v4float Output
-;      %VSMain = OpFunction %void None %16
-;          %17 = OpLabel
-;          %19 = OpAccessChain %_ptr_Input_float %COLOR %uint_0
-;          %20 = OpLoad %float %19
-;          %21 = OpAccessChain %_ptr_Input_float %COLOR %uint_1
-;          %22 = OpLoad %float %21
-;          %23 = OpAccessChain %_ptr_Input_float %COLOR %uint_2
-;          %24 = OpLoad %float %23
-;          %25 = OpAccessChain %_ptr_Input_float %COLOR %uint_3
-;          %26 = OpLoad %float %25
-;          %27 = OpAccessChain %_ptr_Input_float %POSITION %uint_0
-;          %28 = OpLoad %float %27
-;          %29 = OpAccessChain %_ptr_Input_float %POSITION %uint_1
-;          %30 = OpLoad %float %29
-;          %31 = OpAccessChain %_ptr_Input_float %POSITION %uint_2
-;          %32 = OpLoad %float %31
-;          %33 = OpAccessChain %_ptr_Input_float %POSITION %uint_3
-;          %34 = OpLoad %float %33
-;          %36 = OpAccessChain %_ptr_Output_float %gl_Position %uint_0
-;                OpStore %36 %28
-;          %37 = OpAccessChain %_ptr_Output_float %gl_Position %uint_1
-;                OpStore %37 %30
-;          %38 = OpAccessChain %_ptr_Output_float %gl_Position %uint_2
-;                OpStore %38 %32
-;          %39 = OpAccessChain %_ptr_Output_float %gl_Position %uint_3
-;                OpStore %39 %34
-;          %40 = OpAccessChain %_ptr_Output_float %COLOR_0 %uint_0
-;                OpStore %40 %20
-;          %41 = OpAccessChain %_ptr_Output_float %COLOR_0 %uint_1
-;                OpStore %41 %22
-;          %42 = OpAccessChain %_ptr_Output_float %COLOR_0 %uint_2
-;                OpStore %42 %24
-;          %43 = OpAccessChain %_ptr_Output_float %COLOR_0 %uint_3
-;                OpStore %43 %26
-;                OpReturn
-;                OpFunctionEnd
+; CHECK:      ; SPIR-V
+; CHECK-NEXT: ; Version: 1.0
+; CHECK-NEXT: ; Generator: Google spiregg; 0
+; CHECK-NEXT: ; Bound: 44
+; CHECK-NEXT: ; Schema: 0
+; CHECK-NEXT:                OpCapability Shader
+; CHECK-NEXT:                OpMemoryModel Logical GLSL450
+; CHECK-NEXT:                OpEntryPoint Vertex %VSMain "VSMain" %POSITION %COLOR %gl_Position %COLOR_0
+; CHECK-NEXT:                OpName %POSITION "POSITION"
+; CHECK-NEXT:                OpName %COLOR "COLOR"
+; CHECK-NEXT:                OpName %COLOR_0 "COLOR"
+; CHECK-NEXT:                OpName %VSMain "VSMain"
+; CHECK-NEXT:                OpDecorate %POSITION Location 0
+; CHECK-NEXT:                OpDecorate %COLOR Location 1
+; CHECK-NEXT:                OpDecorate %gl_Position BuiltIn Position
+; CHECK-NEXT:                OpDecorate %COLOR_0 Location 1
+; CHECK-NEXT:        %uint = OpTypeInt 32 0
+; CHECK-NEXT:      %uint_0 = OpConstant %uint 0
+; CHECK-NEXT:      %uint_1 = OpConstant %uint 1
+; CHECK-NEXT:      %uint_2 = OpConstant %uint 2
+; CHECK-NEXT:      %uint_3 = OpConstant %uint 3
+; CHECK-NEXT:       %float = OpTypeFloat 32
+; CHECK-NEXT:     %v4float = OpTypeVector %float 4
+; CHECK-NEXT: %_ptr_Input_v4float = OpTypePointer Input %v4float
+; CHECK-NEXT: %_ptr_Output_v4float = OpTypePointer Output %v4float
+; CHECK-NEXT:        %void = OpTypeVoid
+; CHECK-NEXT:          %16 = OpTypeFunction %void
+; CHECK-NEXT: %_ptr_Input_float = OpTypePointer Input %float
+; CHECK-NEXT: %_ptr_Output_float = OpTypePointer Output %float
+; CHECK-NEXT:    %POSITION = OpVariable %_ptr_Input_v4float Input
+; CHECK-NEXT:       %COLOR = OpVariable %_ptr_Input_v4float Input
+; CHECK-NEXT: %gl_Position = OpVariable %_ptr_Output_v4float Output
+; CHECK-NEXT:     %COLOR_0 = OpVariable %_ptr_Output_v4float Output
+; CHECK-NEXT:      %VSMain = OpFunction %void None %16
+; CHECK-NEXT:          %17 = OpLabel
+; CHECK-NEXT:          %19 = OpAccessChain %_ptr_Input_float %COLOR %uint_0
+; CHECK-NEXT:          %20 = OpLoad %float %19
+; CHECK-NEXT:          %21 = OpAccessChain %_ptr_Input_float %COLOR %uint_1
+; CHECK-NEXT:          %22 = OpLoad %float %21
+; CHECK-NEXT:          %23 = OpAccessChain %_ptr_Input_float %COLOR %uint_2
+; CHECK-NEXT:          %24 = OpLoad %float %23
+; CHECK-NEXT:          %25 = OpAccessChain %_ptr_Input_float %COLOR %uint_3
+; CHECK-NEXT:          %26 = OpLoad %float %25
+; CHECK-NEXT:          %27 = OpAccessChain %_ptr_Input_float %POSITION %uint_0
+; CHECK-NEXT:          %28 = OpLoad %float %27
+; CHECK-NEXT:          %29 = OpAccessChain %_ptr_Input_float %POSITION %uint_1
+; CHECK-NEXT:          %30 = OpLoad %float %29
+; CHECK-NEXT:          %31 = OpAccessChain %_ptr_Input_float %POSITION %uint_2
+; CHECK-NEXT:          %32 = OpLoad %float %31
+; CHECK-NEXT:          %33 = OpAccessChain %_ptr_Input_float %POSITION %uint_3
+; CHECK-NEXT:          %34 = OpLoad %float %33
+; CHECK-NEXT:          %36 = OpAccessChain %_ptr_Output_float %gl_Position %uint_0
+; CHECK-NEXT:                OpStore %36 %28
+; CHECK-NEXT:          %37 = OpAccessChain %_ptr_Output_float %gl_Position %uint_1
+; CHECK-NEXT:                OpStore %37 %30
+; CHECK-NEXT:          %38 = OpAccessChain %_ptr_Output_float %gl_Position %uint_2
+; CHECK-NEXT:                OpStore %38 %32
+; CHECK-NEXT:          %39 = OpAccessChain %_ptr_Output_float %gl_Position %uint_3
+; CHECK-NEXT:                OpStore %39 %34
+; CHECK-NEXT:          %40 = OpAccessChain %_ptr_Output_float %COLOR_0 %uint_0
+; CHECK-NEXT:                OpStore %40 %20
+; CHECK-NEXT:          %41 = OpAccessChain %_ptr_Output_float %COLOR_0 %uint_1
+; CHECK-NEXT:                OpStore %41 %22
+; CHECK-NEXT:          %42 = OpAccessChain %_ptr_Output_float %COLOR_0 %uint_2
+; CHECK-NEXT:                OpStore %42 %24
+; CHECK-NEXT:          %43 = OpAccessChain %_ptr_Output_float %COLOR_0 %uint_3
+; CHECK-NEXT:                OpStore %43 %26
+; CHECK-NEXT:                OpReturn
+; CHECK-NEXT:                OpFunctionEnd

+ 10 - 0
tools/clang/test/Dxil2Spv/static-vertex.hlsl

@@ -0,0 +1,10 @@
+// dxc -T ps_6_0 static-vertex.hlsl -Fc static-vertex.ll
+struct VSOutput {
+	float4 Position : SV_POSITION;
+	float3 Color    : COLOR;
+};
+
+float4 main(VSOutput input) : SV_TARGET
+{
+	return float4(input.Color, 1);
+};

+ 113 - 0
tools/clang/test/Dxil2Spv/static-vertex.ll

@@ -0,0 +1,113 @@
+; RUN: %dxil2spv %s | %FileCheck %s
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Position              0   xyzw        0      POS   float       
+; COLOR                    0   xyz         1     NONE   float   xyz 
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: c23cfb9164637d35921d87c5895173ea
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Position              0          noperspective       
+; COLOR                    0                 linear       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+;
+;
+; ViewId state:
+;
+; Number of inputs: 7, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 4 }
+;   output 1 depends on inputs: { 5 }
+;   output 2 depends on inputs: { 6 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+; CHECK:    %float_1 = OpConstant %float 1
+
+define void @main() {
+; CHECK:    %gl_Position = OpVariable %_ptr_Input_v4float Input
+  %1 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+
+; CHECK:    %COLOR = OpVariable %_ptr_Input_v3float Input
+  %2 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+
+; CHECK:    %SV_Target = OpVariable %_ptr_Output_v4float Output
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %1)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %2)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %3)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+
+; CHECK:    [[v0:%[0-9]+]] = OpAccessChain %_ptr_Output_float %SV_Target %uint_3
+; CHECK:                  OpStore [[v0]] %float_1
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float 1.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.viewIdState = !{!4}
+!dx.entryPoints = !{!5}
+
+!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 7}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{[9 x i32] [i32 7, i32 4, i32 0, i32 0, i32 0, i32 0, i32 1, i32 2, i32 4]}
+!5 = !{void ()* @main, !"main", !6, null, null}
+!6 = !{!7, !12, null}
+!7 = !{!8, !10}
+!8 = !{i32 0, !"SV_Position", i8 9, i8 3, !9, i8 4, i32 1, i8 4, i32 0, i8 0, null}
+!9 = !{i32 0}
+!10 = !{i32 1, !"COLOR", i8 9, i8 0, !9, i8 2, i32 1, i8 3, i32 1, i8 0, !11}
+!11 = !{i32 3, i32 7}
+!12 = !{!13}
+!13 = !{i32 0, !"SV_Target", i8 9, i8 16, !9, i8 0, i32 1, i8 4, i32 0, i8 0, !14}
+!14 = !{i32 3, i32 15}
+

+ 6 - 8
tools/clang/unittests/Dxil2Spv/CMakeLists.txt

@@ -1,27 +1,25 @@
 set(LLVM_LINK_COMPONENTS
-  Support
   dxcsupport
   dxil
   dxilrootsignature
   hlsl
+  Support
   )
 
 add_clang_unittest(clang-dxil2spv-tests
-  TestMain.cpp
-  LitTest.cpp
-  WholeFileTestFixture.cpp
-  WholeFileTestFixture.h
-  FileTestUtils.cpp
-  FileTestUtils.h
   Dxil2SpvTestOptions.cpp
   Dxil2SpvTestOptions.h
+  FileTestUtils.cpp
+  FileTestUtils.h
+  LitTest.cpp
+  TestMain.cpp
   )
 
 target_link_libraries(clang-dxil2spv-tests
   clangSPIRV
   dxcompiler
   dxil2spvlib
-  effcee
+  HLSLTestLib
   )
 
 include_directories(${LLVM_SOURCE_DIR}/tools/clang/tools)

+ 43 - 10
tools/clang/unittests/Dxil2Spv/LitTest.cpp

@@ -7,21 +7,54 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "WholeFileTestFixture.h"
+#include "FileTestUtils.h"
+#include "dxc/Test/DxcTestUtils.h"
+#include "dxc/Test/WEXAdapter.h"
 
 namespace {
-using clang::dxil2spv::WholeFileTest;
 
-TEST_F(WholeFileTest, PassThruPixelShader) {
-  runWholeFileTest("passthru-ps.ll");
-}
+#ifdef _WIN32
+class FileTest {
+#else
+class FileTest : public ::testing::Test {
+#endif
+public:
+  BEGIN_TEST_CLASS(FileTest)
+  TEST_CLASS_PROPERTY(L"Parallel", L"true")
+  TEST_METHOD_PROPERTY(L"Priority", L"0")
+  END_TEST_CLASS()
 
-TEST_F(WholeFileTest, PassThruVertexShader) {
-  runWholeFileTest("passthru-vs.ll");
-}
+  TEST_CLASS_SETUP(InitSupport);
+
+  dxc::DxcDllSupport m_dllSupport;
+  VersionSupportInfo m_version;
+
+  void runFileTest(std::string name) {
+    std::string fullPath =
+        clang::dxil2spv::utils::getAbsPathOfInputDataFile(name);
+    FileRunTestResult result =
+        FileRunTestResult::RunFromFileCommands(CA2W(fullPath.c_str()));
+    if (result.RunResult != 0) {
+      WEX::Logging::Log::Error(L"FileTest failed");
+      WEX::Logging::Log::Error(CA2W(result.ErrorMessage.c_str(), CP_UTF8));
+    }
+  }
+};
 
-TEST_F(WholeFileTest, PassThruComputeShader) {
-  runWholeFileTest("passthru-cs.ll");
+bool FileTest::InitSupport() {
+  if (!m_dllSupport.IsEnabled()) {
+    VERIFY_SUCCEEDED(m_dllSupport.Initialize());
+    m_version.Initialize(m_dllSupport);
+  }
+  return true;
 }
 
+TEST_F(FileTest, PassThruPixelShader) { runFileTest("passthru-ps.ll"); }
+
+TEST_F(FileTest, PassThruVertexShader) { runFileTest("passthru-vs.ll"); }
+
+TEST_F(FileTest, PassThruComputeShader) { runFileTest("passthru-cs.ll"); }
+
+TEST_F(FileTest, StaticVertex) { runFileTest("static-vertex.ll"); }
+
 } // namespace

+ 72 - 0
tools/clang/unittests/Dxil2Spv/README.md

@@ -0,0 +1,72 @@
+# `dxil2spv` Tests
+
+## How to Add a Test
+
+These instructions assume the new test will be generated from HLSL source,
+rather than hand-writing DXIL directly. Whenever this is the case, the HLSL
+source should be preserved to aid in regenerating tests in future as needed
+(i.e. if changes are made to `dxc` that warrant recompiling, or a new test needs
+to be created as a modified version of an existing test).
+
+1.  Create a new HLSL source file in `tools/clang/test/Dxil2Spv/`.
+
+    For example, `my-new-test.hlsl`:
+
+    ```
+    struct VSOutput {
+        float4 Position : SV_POSITION;
+        float3 Color    : COLOR;
+    };
+
+    float4 main(VSOutput input) : SV_TARGET
+    {
+        return float4(input.Color, 1);
+    };
+    ```
+
+2.  Compile HLSL source file to DXIL.
+
+    Use the appropriate `dxc` command to compile the HLSL source and output the
+    disassembled DXIL to a file with the same name and a `.ll` extension using
+    the option `-Fc`.
+
+    For example: `dxc -T ps_6_0 my-new-test.hlsl -Fc my-new-test.ll`
+
+3.  Add a comment the to the top of your HLSL source file with the compile
+    command used.
+
+    `my-new-test.hlsl`:
+
+    ```
+    // dxc -T ps_6_0 my-new-test.hlsl -Fc my-new-test.ll
+    struct VSOutput {
+    [...]
+    ```
+
+4.  Add a `; RUN: %dxil2spv %s | %FileCheck %s` command to the top of your DXIL
+    test file.
+
+    `my-new-test.ll`:
+
+    ```
+    ; RUN: %dxil2spv %s | %FileCheck %s
+    ;
+    ; Input signature:
+    [...]
+    ```
+
+5.  Add `CHECK` lines to test the generated SPIR-V.
+
+    As needed for your test, add `CHECK` lines throughout the DXIL test file. See
+    the LLVM FileCheck documentation for more information about the `CHECK` types
+    supported and pattern matching syntax.
+
+6.  Add the test to `tools/clang/unittests/Dxil2Spv/LitTest.cpp`.
+
+    For example:
+
+    ```
+    TEST_F(FileTest, MyNewTest) {
+      runFileTest("my-new-test.ll");
+    }
+    ```

+ 0 - 121
tools/clang/unittests/Dxil2Spv/WholeFileTestFixture.cpp

@@ -1,121 +0,0 @@
-//===- WholeFileTestFixture.cpp - WholeFileTest impl-----------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <fstream>
-
-#include "FileTestUtils.h"
-#include "WholeFileTestFixture.h"
-
-namespace clang {
-namespace dxil2spv {
-
-namespace {
-const char dxilStartLabel[] = "; RUN:";
-const char spirvStartLabel[] = "; CHECK-WHOLE-SPIR-V:";
-const char errorStartLabel[] = "; CHECK-ERRORS:";
-
-enum class ParsingStage : unsigned {
-  None = 0,
-  DXIL = 1,
-  SPIRV = 2,
-  ERRORS = 3
-};
-} // namespace
-
-bool WholeFileTest::parseInputFile() {
-  ParsingStage stage = ParsingStage::None;
-  bool foundRunCommand = false;
-  bool foundCheckCommand = false;
-  std::ostringstream outString;
-  std::ostringstream errString;
-  std::ifstream inputFile;
-  inputFile.exceptions(std::ifstream::failbit);
-  try {
-    inputFile.open(inputFilePath);
-    for (std::string line; std::getline(inputFile, line);) {
-      if (line.find(dxilStartLabel) != std::string::npos) {
-        stage = ParsingStage::DXIL;
-        foundRunCommand = true;
-      } else if (line.find(spirvStartLabel) != std::string::npos) {
-        // SPIR-V source starts on the next line.
-        stage = ParsingStage::SPIRV;
-        foundCheckCommand = true;
-      } else if (line.find(errorStartLabel) != std::string::npos) {
-        // Expected errors starts on the next line.
-        stage = ParsingStage::ERRORS;
-        foundCheckCommand = true;
-      } else if (stage == ParsingStage::SPIRV) {
-        // Strip the leading "; " from the SPIR-V assembly (skip 1 characters)
-        if (line.size() > 2u) {
-          line = line.substr(2);
-        }
-        if (line[line.size() - 1] == '\r')
-          line = line.substr(0, line.size() - 1);
-        outString << line << std::endl;
-      } else if (stage == ParsingStage::ERRORS) {
-        // Strip the leading "; " (skip 1 characters)
-        if (line.size() > 2u) {
-          line = line.substr(2);
-        }
-        if (line[line.size() - 1] == '\r')
-          line = line.substr(0, line.size() - 1);
-        errString << line << std::endl;
-      }
-    }
-  } catch (...) {
-    if (!inputFile.eof()) {
-      fprintf(
-          stderr,
-          "Error: Exception occurred while opening/reading the input file %s\n",
-          inputFilePath.c_str());
-      return false;
-    }
-  }
-
-  if (!foundRunCommand) {
-    fprintf(stderr, "Error: Missing \"RUN:\" command.\n");
-    return false;
-  }
-  if (!foundCheckCommand) {
-    fprintf(stderr, "Error: Missing \"CHECK-WHOLE-SPIR-V:\" and/or "
-                    "\"CHECK-ERRORS:\" command.\n");
-    return false;
-  }
-
-  // Reached the end of the file. SPIR-V source has ended. Store it for
-  // comparison.
-  expectedSpirvAsm = outString.str();
-  expectedErrors = errString.str();
-
-  // Close the input file.
-  inputFile.close();
-
-  // Everything was successful.
-  return true;
-}
-
-void WholeFileTest::runWholeFileTest(llvm::StringRef filename) {
-  inputFilePath = utils::getAbsPathOfInputDataFile(filename);
-
-  // Parse the input file.
-  ASSERT_TRUE(parseInputFile());
-
-  // Feed the HLSL source into the Compiler.
-  ASSERT_TRUE(utils::translateFileWithDxil2Spv(
-      inputFilePath, &generatedSpirvAsm, &generatedErrors));
-
-  // Compare the expected and the generted SPIR-V code.
-  EXPECT_EQ(expectedSpirvAsm, generatedSpirvAsm);
-
-  // Compare the expected and the generted errors.
-  EXPECT_EQ(expectedErrors, generatedErrors);
-}
-
-} // end namespace dxil2spv
-} // end namespace clang

+ 0 - 63
tools/clang/unittests/Dxil2Spv/WholeFileTestFixture.h

@@ -1,63 +0,0 @@
-//===- WholeFileTestFixture.h - Whole file test Fixture--------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNITTESTS_DXIL2SPV_WHOLEFILETESTFIXTURE_H
-#define LLVM_CLANG_UNITTESTS_DXIL2SPV_WHOLEFILETESTFIXTURE_H
-
-#include "llvm/ADT/StringRef.h"
-#include "gtest/gtest.h"
-
-namespace clang {
-namespace dxil2spv {
-
-/// \brief The purpose of the this test class is to take in an input file with
-/// the following format:
-///
-///    ; Comments...
-///    ; More comments...
-///    ; RUN: %dxil2spv
-///    ...
-///    <DXIL bitcode goes here>
-///    ...
-///    ; CHECK-WHOLE-SPIR-V:
-///    ; ...
-///    ; <SPIR-V code goes here>
-///    ; ...
-///
-/// This file is fully read in as the DXIL source (therefore any non-DXIL must
-/// be commented out). It is fed to dxil2spv to translate to SPIR-V. The
-/// resulting SPIR-V assembly text is compared to the second part of the input
-/// file (after the <CHECK-WHOLE-SPIR-V:> directive). If these match, the test
-/// is marked as a PASS, and marked as a FAILED otherwise.
-class WholeFileTest : public ::testing::Test {
-public:
-  /// \brief Runs a WHOLE-FILE-TEST! (See class description for more info)
-  /// Returns true if the test passes; false otherwise.
-  void runWholeFileTest(llvm::StringRef path);
-
-  WholeFileTest() {}
-
-private:
-  /// \brief Reads in the given input file.
-  /// Stores the SPIR-V portion of the file into the <expectedSpirvAsm>
-  /// member variable.
-  /// Returns true on success, and false on failure.
-  bool parseInputFile();
-
-  std::string inputFilePath;     ///< Path to the input test file
-  std::string expectedSpirvAsm;  ///< Expected SPIR-V parsed from input
-  std::string generatedSpirvAsm; ///< Disassembled binary (SPIR-V code)
-  std::string expectedErrors;    ///< Expected errors parsed from input
-  std::string generatedErrors;   ///< Actual errors from running
-};
-
-} // end namespace dxil2spv
-} // end namespace clang
-
-#endif

+ 0 - 2
tools/clang/unittests/HLSL/CMakeLists.txt

@@ -26,7 +26,6 @@ set( LLVM_LINK_COMPONENTS
 if(WIN32)
 set(HLSL_IGNORE_SOURCES
   TestMain.cpp
-  HLSLTestOptions.cpp
 )
 add_clang_library(clang-hlsl-tests SHARED
   AllocatorTest.cpp
@@ -70,7 +69,6 @@ add_clang_unittest(clang-hlsl-tests
   DXIsenseTest.cpp
   ExtensionTest.cpp
   FunctionTest.cpp
-  HLSLTestOptions.cpp
   Objects.cpp
   OptimizerTest.cpp
   OptionsTest.cpp

+ 1 - 1
tools/clang/unittests/HLSL/TestMain.cpp

@@ -12,7 +12,7 @@
 
 #include "llvm/Support/Signals.h"
 
-#include "HLSLTestOptions.h"
+#include "dxc/Test/HLSLTestOptions.h"
 #include "dxc/Test/WEXAdapter.h"
 
 #if defined(_WIN32)

+ 19 - 0
tools/clang/unittests/HLSLTestLib/CMakeLists.txt

@@ -1,5 +1,8 @@
 
 if(WIN32)
+set(HLSL_IGNORE_SOURCES
+  HLSLTestOptions.cpp
+)
 find_package(TAEF REQUIRED)
 include_directories(${TAEF_INCLUDE_DIRS})
 
@@ -19,10 +22,26 @@ add_clang_library(HLSLTestLib
   DxcTestUtils.cpp
   FileCheckerTest.cpp
   FileCheckForTest.cpp
+  HLSLTestOptions.cpp
 )
 include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include)
 include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock/include)
 
+if(ENABLE_DXIL2SPV)
+target_compile_definitions(HLSLTestLib PRIVATE ENABLE_DXIL2SPV)
+
+target_include_directories(HLSLTestLib PRIVATE
+  ${LLVM_SOURCE_DIR}/tools/clang/tools
+  ${SPIRV_TOOLS_INCLUDE_DIR}
+  ${SPIRV_HEADER_INCLUDE_DIR}
+  )
+target_link_libraries(HLSLTestLib
+  clangSPIRV
+  dxcompiler
+  dxil2spvlib
+  )
+endif(ENABLE_DXIL2SPV)
+
 endif(WIN32)
 
 add_dependencies(HLSLTestLib TablegenHLSLOptions)

+ 70 - 8
tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp

@@ -29,18 +29,21 @@
 #include "dxc/Test/HlslTestUtils.h"
 #include "dxc/Test/DxcTestUtils.h"
 
-#include "llvm/Support/raw_os_ostream.h"
-#include "llvm/Support/MD5.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
+#include "dxc/DxilContainer/DxilContainer.h"
 #include "dxc/Support/Global.h"
-#include "dxc/Support/dxcapi.use.h"
-#include "dxc/dxctools.h"
 #include "dxc/Support/HLSLOptions.h"
 #include "dxc/Support/Unicode.h"
+#include "dxc/Support/dxcapi.use.h"
 #include "dxc/Support/microcom.h"
-#include "dxc/DxilContainer/DxilContainer.h"
+#include "dxc/dxctools.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/MSFileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_os_ostream.h"
+#include "llvm/Support/raw_ostream.h"
 
 #ifdef _WIN32 // Reflection unsupported
 #include "dxc/Test/D3DReflectionDumper.h"
@@ -51,6 +54,10 @@
 using namespace hlsl::dump;
 #endif // WIN32 - Reflection unsupported
 
+#ifdef ENABLE_DXIL2SPV
+#include "dxil2spv/lib/dxil2spv.h"
+#endif // ENABLE_DXIL2SPV
+
 using namespace std;
 using namespace hlsl_test;
 
@@ -137,6 +144,11 @@ FileRunCommandResult FileRunCommandPart::Run(dxc::DxcDllSupport &DllSupport, con
     return result;
 #endif // WIN32 - Linking unsupported
   }
+#ifdef ENABLE_DXIL2SPV
+  else if (0 == _stricmp(Command.c_str(), "%dxil2spv")) {
+    return RunDxil2Spv(DllSupport, Prior);
+  }
+#endif // ENABLE_DXIL2SPV
   else if (pPluginToolsPaths != nullptr) {
     auto it = pPluginToolsPaths->find(Command.c_str());
     if (it != pPluginToolsPaths->end()) {
@@ -1091,6 +1103,56 @@ FileRunCommandResult FileRunCommandPart::RunDxilVer(dxc::DxcDllSupport& DllSuppo
   return CheckDxilVer(DllSupport, RequiredDxilMajor, RequiredDxilMinor);
 }
 
+#ifdef ENABLE_DXIL2SPV
+FileRunCommandResult
+FileRunCommandPart::RunDxil2Spv(dxc::DxcDllSupport &DllSupport,
+                                const FileRunCommandResult *Prior) {
+  // Support piping stdin from prior if needed.
+  UNREFERENCED_PARAMETER(Prior);
+  bool success = true;
+
+  std::string stdoutString;
+  std::string stderrString;
+  llvm::raw_string_ostream stdoutStream(stdoutString);
+  llvm::raw_string_ostream stderrStream(stderrString);
+
+  try {
+    // Configure filesystem.
+    llvm::sys::fs::MSFileSystem *msf = nullptr;
+    HRESULT hr;
+    if (SUCCEEDED(hr = CreateMSFileSystemForDisk(&msf))) {
+      llvm::sys::fs::AutoPerThreadSystem pts(msf);
+      IFTLLVM(pts.error_code());
+
+      // Set up diagnostics.
+      clang::CompilerInstance instance;
+      auto *diagnosticPrinter = new clang::TextDiagnosticPrinter(
+          stderrStream, new clang::DiagnosticOptions());
+      instance.createDiagnostics(diagnosticPrinter, false);
+      instance.setOutStream(&stdoutStream);
+
+      // Set compiler options.
+      instance.getCodeGenOpts().MainFileName = CW2A(CommandFileName, CP_UTF8);
+      instance.getCodeGenOpts().SpirvOptions.targetEnv = "vulkan1.0";
+
+      clang::dxil2spv::Translator translator(instance);
+      translator.Run();
+    } else {
+      success = false;
+    }
+  } catch (...) {
+    success = false;
+  }
+
+  FileRunCommandResult result = {};
+  result.StdOut = stdoutStream.str();
+  result.StdErr = stderrStream.str();
+  result.ExitCode = success ? 0 : 1;
+
+  return result;
+}
+#endif // ENABLE_DXIL2SPV
+
 #ifndef _WIN32
 FileRunCommandResult FileRunCommandPart::RunFromPath(const std::string &toolPath, const FileRunCommandResult *Prior) {
   return FileRunCommandResult::Error("RunFromPath not supported");

+ 2 - 2
tools/clang/unittests/HLSL/HLSLTestOptions.cpp → tools/clang/unittests/HLSLTestLib/HLSLTestOptions.cpp

@@ -12,9 +12,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "HLSLTestOptions.h"
-#include "dxc/Test/WEXAdapter.h"
+#include "dxc/Test/HLSLTestOptions.h"
 #include "dxc/Support/WinAdapter.h"
+#include "dxc/Test/WEXAdapter.h"
 
 namespace clang {
 namespace hlsl {