瀏覽代碼

Add IDxcVersionInfo2 for querying Git commit info (#1304)

This will give users a way to know the commit from which a DXC
library/binary was built from, so that they can compare different
libraries/binaries and report bugs easily.

dxc.exe now also prints the commit info using this new interface
method. It uses the following format:

  (dev;<commit-count>-<commit-hash>)
Lei Zhang 7 年之前
父節點
當前提交
94ec193042

+ 8 - 1
CMakeLists.txt

@@ -83,11 +83,18 @@ option(HLSL_ENABLE_FIXED_VER "Sets up fixed version information." OFF) # HLSL Ch
 option(HLSL_ENABLE_ANALYZE "Enables compiler analysis during compilation." OFF) # HLSL Change
 option(HLSL_ENABLE_ANALYZE "Enables compiler analysis during compilation." OFF) # HLSL Change
 option(HLSL_OPTIONAL_PROJS_IN_DEFAULT "Include optional projects in default build target." OFF) # HLSL Change
 option(HLSL_OPTIONAL_PROJS_IN_DEFAULT "Include optional projects in default build target." OFF) # HLSL Change
 
 
+# HLSL Change Starts - support commit querying
+option(HLSL_SUPPORT_QUERY_GIT_COMMIT_INFO "Supports querying Git commit info." ON)
+if ( HLSL_SUPPORT_QUERY_GIT_COMMIT_INFO )
+  add_definitions(-DSUPPORT_QUERY_GIT_COMMIT_INFO)
+endif()
+# HLSL Chnage Ends
+
 # HLSL Change Starts - set flag for Appveyor CI
 # HLSL Change Starts - set flag for Appveyor CI
 if ( "$ENV{CI}" AND "$ENV{APPVEYOR}" )
 if ( "$ENV{CI}" AND "$ENV{APPVEYOR}" )
   add_definitions(-DDXC_ON_APPVEYOR_CI)
   add_definitions(-DDXC_ON_APPVEYOR_CI)
 endif()
 endif()
-# HLSL Change ends
+# HLSL Change Ends
 
 
 # SPIRV change starts
 # SPIRV change starts
 option(ENABLE_SPIRV_CODEGEN "Enables SPIR-V code generation." OFF)
 option(ENABLE_SPIRV_CODEGEN "Enables SPIR-V code generation." OFF)

+ 5 - 0
include/dxc/dxcapi.h

@@ -298,6 +298,11 @@ IDxcVersionInfo : public IUnknown {
   virtual HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) = 0;
 };
 };
 
 
+struct __declspec(uuid("fb6904c4-42f0-4b62-9c46-983af7da7c83"))
+IDxcVersionInfo2 : public IDxcVersionInfo {
+  virtual HRESULT STDMETHODCALLTYPE GetCommitInfo(_Out_ UINT32 *pCommitCount, _Out_ char **pCommitHash) = 0;
+};
+
 // {73e22d93-e6ce-47f3-b5bf-f0664f39c1b0}
 // {73e22d93-e6ce-47f3-b5bf-f0664f39c1b0}
 __declspec(selectany) extern const CLSID CLSID_DxcCompiler = {
 __declspec(selectany) extern const CLSID CLSID_DxcCompiler = {
   0x73e22d93,
   0x73e22d93,

+ 18 - 1
tools/clang/tools/dxc/dxc.cpp

@@ -1017,10 +1017,22 @@ void DxcContext::GetCompilerVersionInfo(llvm::raw_string_ostream &OS) {
     UINT32 compilerMajor = 1;
     UINT32 compilerMajor = 1;
     UINT32 compilerMinor = 0;
     UINT32 compilerMinor = 0;
     CComPtr<IDxcVersionInfo> VerInfo;
     CComPtr<IDxcVersionInfo> VerInfo;
+
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+    UINT32 commitCount = 0;
+    CComHeapPtr<char> commitHash;
+    CComPtr<IDxcVersionInfo2> VerInfo2;
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+
     const char *compilerName =
     const char *compilerName =
         m_Opts.ExternalFn.empty() ? "dxcompiler.dll" : m_Opts.ExternalFn.data();
         m_Opts.ExternalFn.empty() ? "dxcompiler.dll" : m_Opts.ExternalFn.data();
+
     if (SUCCEEDED(CreateInstance(CLSID_DxcCompiler, &VerInfo))) {
     if (SUCCEEDED(CreateInstance(CLSID_DxcCompiler, &VerInfo))) {
       VerInfo->GetVersion(&compilerMajor, &compilerMinor);
       VerInfo->GetVersion(&compilerMajor, &compilerMinor);
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+      if (SUCCEEDED(VerInfo->QueryInterface(&VerInfo2)))
+        VerInfo2->GetCommitInfo(&commitCount, &commitHash);
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
       OS << compilerName << ": " << compilerMajor << "." << compilerMinor;
       OS << compilerName << ": " << compilerMajor << "." << compilerMinor;
     }
     }
     // compiler.dll 1.0 did not support IdxcVersionInfo
     // compiler.dll 1.0 did not support IdxcVersionInfo
@@ -1033,7 +1045,12 @@ void DxcContext::GetCompilerVersionInfo(llvm::raw_string_ostream &OS) {
       // unofficial version always have file version 3.7.0.0
       // unofficial version always have file version 3.7.0.0
       if (version[0] == 3 && version[1] == 7 && version[2] == 0 &&
       if (version[0] == 3 && version[1] == 7 && version[2] == 0 &&
           version[3] == 0) {
           version[3] == 0) {
-        OS << "(unofficial)";
+        OS << "(dev"
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+           << ";" << commitCount << "-"
+           << (commitHash.m_pData ? commitHash.m_pData : "<unknown-git-hash>")
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+           << ")";
       } else {
       } else {
         OS << "(" << version[0] << "." << version[1] << "." << version[2] << "."
         OS << "(" << version[0] << "." << version[1] << "." << version[2] << "."
            << version[3] << ")";
            << version[3] << ")";

+ 21 - 0
tools/clang/tools/dxcompiler/CMakeLists.txt

@@ -127,6 +127,27 @@ else ()
   include_directories(AFTER ${LLVM_INCLUDE_DIR}/dxc/Tracing)
   include_directories(AFTER ${LLVM_INCLUDE_DIR}/dxc/Tracing)
 endif (WIN32)
 endif (WIN32)
 
 
+if ( HLSL_SUPPORT_QUERY_GIT_COMMIT_INFO )
+  set(GIT_COMMIT_INFO_FILE ${CMAKE_CURRENT_BINARY_DIR}/GitCommitInfo.inc)
+  set(GET_GIT_COMMIT_SCRIPT ${PROJECT_SOURCE_DIR}/utils/GetCommitInfo.py)
+  add_custom_command(
+    OUTPUT  ${GIT_COMMIT_INFO_FILE}
+    COMMAND ${PYTHON_EXECUTABLE} ${GET_GIT_COMMIT_SCRIPT}
+            ${PROJECT_SOURCE_DIR} ${GIT_COMMIT_INFO_FILE}
+    DEPENDS ${GET_GIT_COMMIT_SCRIPT} GIT_COMMIT_INFO_ALWAYS_REBUILD
+    COMMENT "Collect Git commit info for versioning"
+  )
+  add_custom_target(
+    GIT_COMMIT_INFO_ALWAYS_REBUILD
+    ${CMAKE_COMMAND} -E touch ${GET_GIT_COMMIT_SCRIPT}
+    COMMENT "Touch GetCommitInfo.py to trigger rebuild"
+  )
+  set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/dxcompilerobj.cpp
+    PROPERTIES OBJECT_DEPENDS "${GIT_COMMIT_INFO_FILE}")
+  set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/dxcvalidator.cpp
+    PROPERTIES OBJECT_DEPENDS "${GIT_COMMIT_INFO_FILE}")
+endif()
+
 set_target_properties(dxcompiler
 set_target_properties(dxcompiler
   PROPERTIES
   PROPERTIES
   OUTPUT_NAME "dxcompiler"
   OUTPUT_NAME "dxcompiler"

+ 41 - 11
tools/clang/tools/dxcompiler/dxcompilerobj.cpp

@@ -29,14 +29,6 @@
 #include "dxc/HLSL/DxilRootSignature.h"
 #include "dxc/HLSL/DxilRootSignature.h"
 #include "dxcutil.h"
 #include "dxcutil.h"
 #include "dxc/Support/dxcfilesystem.h"
 #include "dxc/Support/dxcfilesystem.h"
-
-// SPIRV change starts
-#ifdef ENABLE_SPIRV_CODEGEN
-#include "clang/SPIRV/EmitSPIRVAction.h"
-#endif
-// SPIRV change ends
-
-
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/HLSL/DxilContainer.h"
 #include "dxc/HLSL/DxilContainer.h"
 #include "dxc/dxcapi.internal.h"
 #include "dxc/dxcapi.internal.h"
@@ -55,6 +47,16 @@
 #include "dxillib.h"
 #include "dxillib.h"
 #include <algorithm>
 #include <algorithm>
 
 
+// SPIRV change starts
+#ifdef ENABLE_SPIRV_CODEGEN
+#include "clang/SPIRV/EmitSPIRVAction.h"
+#endif
+// SPIRV change ends
+
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+#include "GitCommitInfo.inc" // Auto generated file containing Git commit info
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+
 #define CP_UTF16 1200
 #define CP_UTF16 1200
 
 
 using namespace llvm;
 using namespace llvm;
@@ -196,7 +198,15 @@ public:
   }
   }
 };
 };
 
 
-class DxcCompiler : public IDxcCompiler2, public IDxcLangExtensions, public IDxcContainerEvent, public IDxcVersionInfo {
+class DxcCompiler : public IDxcCompiler2,
+                    public IDxcLangExtensions,
+                    public IDxcContainerEvent,
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+                    public IDxcVersionInfo2
+#else
+                    public IDxcVersionInfo
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+{
 private:
 private:
   DXC_MICROCOM_TM_REF_FIELDS()
   DXC_MICROCOM_TM_REF_FIELDS()
   DxcLangExtensionsHelper m_langExtensionsHelper;
   DxcLangExtensionsHelper m_langExtensionsHelper;
@@ -260,7 +270,11 @@ public:
                                  IDxcCompiler2,
                                  IDxcCompiler2,
                                  IDxcLangExtensions,
                                  IDxcLangExtensions,
                                  IDxcContainerEvent,
                                  IDxcContainerEvent,
-                                 IDxcVersionInfo>
+                                 IDxcVersionInfo
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+                                ,IDxcVersionInfo2
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+                                >
                                  (this, iid, ppvObject);
                                  (this, iid, ppvObject);
   }
   }
 
 
@@ -908,6 +922,23 @@ public:
     *pMinor = DXIL::kDxilMinor;
     *pMinor = DXIL::kDxilMinor;
     return S_OK;
     return S_OK;
   }
   }
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+  HRESULT STDMETHODCALLTYPE GetCommitInfo(_Out_ UINT32 *pCommitCount,
+                                          _Out_ char **pCommitHash) override {
+    if (pCommitCount == nullptr || pCommitHash == nullptr)
+      return E_INVALIDARG;
+
+    char *const hash = (char *)CoTaskMemAlloc(ARRAYSIZE(kGitCommitHash) + 1);
+    if (hash == nullptr)
+      return E_OUTOFMEMORY;
+    std::strcpy(hash, kGitCommitHash);
+
+    *pCommitHash = hash;
+    *pCommitCount = kGitCommitCount;
+
+    return S_OK;
+  }
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
   HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) override {
   HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) override {
     if (pFlags == nullptr)
     if (pFlags == nullptr)
       return E_INVALIDARG;
       return E_INVALIDARG;
@@ -917,7 +948,6 @@ public:
 #endif
 #endif
     return S_OK;
     return S_OK;
   }
   }
-
 };
 };
 
 
 HRESULT CreateDxcCompiler(_In_ REFIID riid, _Out_ LPVOID* ppv) {
 HRESULT CreateDxcCompiler(_In_ REFIID riid, _Out_ LPVOID* ppv) {

+ 34 - 1
tools/clang/tools/dxcompiler/dxcvalidator.cpp

@@ -29,6 +29,10 @@
 #include "dxcetw.h"
 #include "dxcetw.h"
 #endif
 #endif
 
 
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+#include "GitCommitInfo.inc" // Auto generated file containing Git commit info
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+
 using namespace llvm;
 using namespace llvm;
 using namespace hlsl;
 using namespace hlsl;
 
 
@@ -49,7 +53,13 @@ struct DiagRestore {
   }
   }
 };
 };
 
 
-class DxcValidator : public IDxcValidator, public IDxcVersionInfo {
+class DxcValidator : public IDxcValidator,
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+                     public IDxcVersionInfo2
+#else
+                     public IDxcVersionInfo
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+{
 private:
 private:
   DXC_MICROCOM_TM_REF_FIELDS()
   DXC_MICROCOM_TM_REF_FIELDS()
 
 
@@ -91,6 +101,11 @@ public:
   // IDxcVersionInfo
   // IDxcVersionInfo
   HRESULT STDMETHODCALLTYPE GetVersion(_Out_ UINT32 *pMajor, _Out_ UINT32 *pMinor) override;
   HRESULT STDMETHODCALLTYPE GetVersion(_Out_ UINT32 *pMajor, _Out_ UINT32 *pMinor) override;
   HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) override;
   HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) override;
+
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+  // IDxcVersionInfo2
+  HRESULT STDMETHODCALLTYPE GetCommitInfo(_Out_ UINT32 *pCommitCount, _Out_ char **pCommitHash) override;
+#endif
 };
 };
 
 
 // Compile a single entry point to the target shader model
 // Compile a single entry point to the target shader model
@@ -156,6 +171,24 @@ HRESULT STDMETHODCALLTYPE DxcValidator::GetVersion(_Out_ UINT32 *pMajor, _Out_ U
   return S_OK;
   return S_OK;
 }
 }
 
 
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+HRESULT STDMETHODCALLTYPE DxcValidator::GetCommitInfo(
+    _Out_ UINT32 *pCommitCount, _Out_ char **pCommitHash) {
+  if (pCommitCount == nullptr || pCommitHash == nullptr)
+    return E_INVALIDARG;
+
+  char *const hash = (char *)CoTaskMemAlloc(ARRAYSIZE(kGitCommitHash) + 1);
+  if (hash == nullptr)
+    return E_OUTOFMEMORY;
+  std::strcpy(hash, kGitCommitHash);
+
+  *pCommitHash = hash;
+  *pCommitCount = kGitCommitCount;
+
+  return S_OK;
+}
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+
 HRESULT STDMETHODCALLTYPE DxcValidator::GetFlags(_Out_ UINT32 *pFlags) {
 HRESULT STDMETHODCALLTYPE DxcValidator::GetFlags(_Out_ UINT32 *pFlags) {
   if (pFlags == nullptr)
   if (pFlags == nullptr)
     return E_INVALIDARG;
     return E_INVALIDARG;

+ 60 - 0
utils/GetCommitInfo.py

@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+import os
+import subprocess
+
+
+def git_get_commit_hash():
+    return subprocess.check_output(
+        ['git', 'rev-parse', '--short', 'HEAD']).decode('ascii').strip()
+
+
+def git_get_commit_count():
+    return subprocess.check_output(
+        ['git', 'rev-list', '--count', 'HEAD']).decode('ascii').strip()
+
+
+def compose_commit_namespace(git_count, git_hash):
+    return ('namespace {{\n'
+            '  const uint32_t kGitCommitCount = {}u;\n'
+            '  const char kGitCommitHash[] = "{}";\n'
+            '}}\n').format(git_count, git_hash)
+
+def update(srcdir, commit_file):
+    # Read the original commit info
+    try:
+        f = open(commit_file)
+        prev_commit = f.read()
+        f.close()
+    except:
+        prev_commit = ''
+
+    prev_cwd = os.getcwd()
+    os.chdir(srcdir)
+    cur_commit = compose_commit_namespace(
+        git_get_commit_count(), git_get_commit_hash())
+    os.chdir(prev_cwd)
+
+    # Update if different: avoid triggering rebuilding unnecessarily
+    if cur_commit != prev_commit:
+        with open(commit_file, 'w') as f:
+            f.write(cur_commit)
+
+
+def main():
+    import argparse
+
+    parser = argparse.ArgumentParser(
+        description='Generate file containing Git commit information')
+    parser.add_argument('srcpath', metavar='<src-dir-path>', type=str,
+                        help='Path to the source code directory')
+    parser.add_argument('dstpath', metavar='<dst-file-path>', type=str,
+                        help='Path to the generated file')
+
+    args = parser.parse_args()
+
+    update(args.srcpath, args.dstpath)
+
+
+if __name__ == '__main__':
+    main()