浏览代码

Add functions for DxilContainer (#19)

- Add function to get dxilpart by type
- Add function to get ProgramHeader given a DxilContainer
- Add unit test for functions in dxilcontainer.cpp
Young Kim 8 年之前
父节点
当前提交
43aebafa62

+ 14 - 0
include/dxc/HLSL/DxilContainer.h

@@ -232,6 +232,20 @@ inline const char *GetDxilPartData(const DxilPartHeader *pPart) {
 inline char *GetDxilPartData(DxilPartHeader *pPart) {
   return reinterpret_cast<char *>(pPart + 1);
 }
+/// Gets a part header by fourCC
+DxilPartHeader *GetDxilPartByType(DxilContainerHeader *pHeader,
+                                           DxilFourCC fourCC);
+/// Gets a part header by fourCC 
+const DxilPartHeader *
+GetDxilPartByType(const DxilContainerHeader *pHeader,
+                           DxilFourCC fourCC);
+
+/// Returns valid DxilProgramHeader. nullptr if does not exist.
+DxilProgramHeader *GetDxilProgramHeader(DxilContainerHeader *pHeader, DxilFourCC fourCC);
+
+/// Returns valid DxilProgramHeader. nullptr if does not exist.
+const DxilProgramHeader *
+GetDxilProgramHeader(const DxilContainerHeader *pHeader, DxilFourCC fourCC);
 
 /// Initializes container with the specified values.
 void InitDxilContainer(_Out_ DxilContainerHeader *pHeader, uint32_t partCount,

+ 1 - 1
include/dxc/Support/HLSLOptions.td

@@ -259,7 +259,7 @@ def Fc : JoinedOrSeparate<["-", "/"], "Fc">, MetaVarName<"<file>">, HelpText<"Ou
 def Fh : JoinedOrSeparate<["-", "/"], "Fh">, MetaVarName<"<file>">, HelpText<"Output header file containing object code">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Fe : JoinedOrSeparate<["-", "/"], "Fe">, MetaVarName<"<file>">, HelpText<"Output warnings and errors to a specific file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">, HelpText<"Extract shader PDB and write to given file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
-def Vn : JoinedOrSeparate<["-", "/"], "Vn">, HelpText<"Use <name> as variable name in header file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
+def Vn : JoinedOrSeparate<["-", "/"], "Vn">, MetaVarName<"<name>">, HelpText<"Use <name> as variable name in header file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Cc : Flag<["-", "/"], "Cc">, HelpText<"Output color coded assembly listings">, Group<hlslcomp_Group>;
 def Ni : Flag<["-", "/"], "Ni">, HelpText<"Output instruction numbers in assembly listings">, Group<hlslcomp_Group>;
 def No : Flag<["-", "/"], "No">, HelpText<"Output instruction byte offsets in assembly listings">, Group<hlslcomp_Group>;

+ 40 - 0
lib/HLSL/DxilContainer.cpp

@@ -10,6 +10,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "dxc/HLSL/DxilContainer.h"
+#include <algorithm>
 
 namespace hlsl {
 
@@ -82,4 +83,43 @@ bool IsValidDxilContainer(const DxilContainerHeader *pHeader, size_t length) {
   return true;
 }
 
+const DxilPartHeader *GetDxilPartByType(const DxilContainerHeader *pHeader, DxilFourCC fourCC) {
+  if (!IsDxilContainerLike(pHeader, pHeader->ContainerSizeInBytes)) {
+    return nullptr;
+  }
+  const DxilPartIterator partIter =
+      find_if(begin(pHeader), end(pHeader), DxilPartIsType(fourCC));
+  if (partIter == end(pHeader)) {
+    return nullptr;
+  }
+  return *partIter;
+}
+
+DxilPartHeader *GetDxilPartByType(DxilContainerHeader *pHeader,
+                                  DxilFourCC fourCC) {
+  return const_cast<DxilPartHeader *>(GetDxilPartByType(
+      static_cast<const DxilContainerHeader *>(pHeader), fourCC));
+}
+
+const DxilProgramHeader *GetDxilProgramHeader(const DxilContainerHeader *pHeader, DxilFourCC fourCC) {
+  if (!IsDxilContainerLike(pHeader, pHeader->ContainerSizeInBytes)) {
+    return nullptr;
+  }
+  const DxilPartHeader *PartHeader = GetDxilPartByType(pHeader, fourCC);
+  if (!PartHeader) {
+    return nullptr;
+  }
+  const DxilProgramHeader *ProgramHeader =
+      reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(PartHeader));
+  return IsValidDxilProgramHeader(ProgramHeader,
+                                  ProgramHeader->SizeInUint32 * 4)
+             ? ProgramHeader
+             : nullptr;
+}
+
+DxilProgramHeader *GetDxilProgramHeader(DxilContainerHeader *pHeader, DxilFourCC fourCC) {
+  return const_cast<DxilProgramHeader *>(
+      GetDxilProgramHeader(static_cast<const DxilContainerHeader *>(pHeader), fourCC));
+}
+
 } // namespace hlsl

+ 49 - 1
tools/clang/unittests/HLSL/DxilContainerTest.cpp

@@ -72,7 +72,7 @@ public:
   TEST_METHOD(DisassemblyWhenInvalidThenFails)
   TEST_METHOD(DisassemblyWhenValidThenOK)
   TEST_METHOD(ValidateFromLL_Abs2)
-
+  TEST_METHOD(DxilContainerUnitTest)
 
   TEST_METHOD(ReflectionMatchesDXBC_CheckIn)
   BEGIN_TEST_METHOD(ReflectionMatchesDXBC_Full)
@@ -773,3 +773,51 @@ TEST_F(DxilContainerTest, ReflectionMatchesDXBC_Full) {
 TEST_F(DxilContainerTest, ValidateFromLL_Abs2) {
   CodeGenTestCheck(L"abs2_m.ll");
 }
+
+TEST_F(DxilContainerTest, DxilContainerUnitTest) {
+  CComPtr<IDxcCompiler> pCompiler;
+  CComPtr<IDxcBlobEncoding> pSource;
+  CComPtr<IDxcBlob> pProgram;
+  CComPtr<IDxcBlobEncoding> pDisassembly;
+  CComPtr<IDxcOperationResult> pResult;
+  std::vector<LPCWSTR> arguments;
+  arguments.emplace_back(L"/Zi");
+  
+  VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
+  CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
+  // Test DxilContainer with ShaderDebugInfoDXIL
+  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0", arguments.data(), 1, nullptr, 0, nullptr, &pResult));
+  VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
+  
+  const hlsl::DxilContainerHeader *pHeader = static_cast<const hlsl::DxilContainerHeader *> (pProgram->GetBufferPointer());
+  VERIFY_IS_TRUE(hlsl::IsValidDxilContainer(pHeader, pProgram->GetBufferSize()));
+  VERIFY_IS_NOT_NULL(hlsl::IsDxilContainerLike(pHeader, pProgram->GetBufferSize()));
+  VERIFY_IS_NOT_NULL(hlsl::GetDxilProgramHeader(pHeader, hlsl::DxilFourCC::DFCC_DXIL));
+  VERIFY_IS_NOT_NULL(hlsl::GetDxilProgramHeader(pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
+  VERIFY_IS_NOT_NULL(hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_DXIL));
+  VERIFY_IS_NOT_NULL(hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
+  
+  pResult.Release();
+  pProgram.Release();
+
+  // Test DxilContainer without ShaderDebugInfoDXIL
+  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0", nullptr, 0, nullptr, 0, nullptr, &pResult));
+  VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
+  
+  pHeader = static_cast<const hlsl::DxilContainerHeader *> (pProgram->GetBufferPointer());
+  VERIFY_IS_TRUE(hlsl::IsValidDxilContainer(pHeader, pProgram->GetBufferSize()));
+  VERIFY_IS_NOT_NULL(hlsl::IsDxilContainerLike(pHeader, pProgram->GetBufferSize()));
+  VERIFY_IS_NOT_NULL(hlsl::GetDxilProgramHeader(pHeader, hlsl::DxilFourCC::DFCC_DXIL));
+  VERIFY_IS_NULL(hlsl::GetDxilProgramHeader(pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
+  VERIFY_IS_NOT_NULL(hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_DXIL));
+  VERIFY_IS_NULL(hlsl::GetDxilPartByType(pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
+
+  // Test Empty DxilContainer
+  hlsl::DxilContainerHeader header;
+  SetupBasicHeader(&header);
+  VERIFY_IS_TRUE(hlsl::IsValidDxilContainer(&header, header.ContainerSizeInBytes));
+  VERIFY_IS_NOT_NULL(hlsl::IsDxilContainerLike(&header, header.ContainerSizeInBytes));
+  VERIFY_IS_NULL(hlsl::GetDxilProgramHeader(&header, hlsl::DxilFourCC::DFCC_DXIL));
+  VERIFY_IS_NULL(hlsl::GetDxilPartByType(&header, hlsl::DxilFourCC::DFCC_DXIL));
+
+}