瀏覽代碼

Added mechanism for extra file outputs (#3060)

Adam Yang 5 年之前
父節點
當前提交
c684cc0421
共有 4 個文件被更改,包括 173 次插入1 次删除
  1. 96 1
      include/dxc/Support/dxcapi.impl.h
  2. 17 0
      include/dxc/dxcapi.h
  3. 59 0
      tools/clang/tools/dxclib/dxc.cpp
  4. 1 0
      tools/clang/tools/dxcompiler/dxcapi.cpp

+ 96 - 1
include/dxc/Support/dxcapi.impl.h

@@ -102,7 +102,7 @@ inline DxcOutputType DxcGetOutputType(DXC_OUT_KIND kind) {
 }
 }
 
 
 // Update when new results are allowed
 // Update when new results are allowed
-static const unsigned kNumDxcOutputTypes = DXC_OUT_ROOT_SIGNATURE;
+static const unsigned kNumDxcOutputTypes = DXC_OUT_EXTRA_OUTPUTS;
 static const SIZE_T kAutoSize = (SIZE_T)-1;
 static const SIZE_T kAutoSize = (SIZE_T)-1;
 static const LPCWSTR DxcOutNoName = nullptr;
 static const LPCWSTR DxcOutNoName = nullptr;
 
 
@@ -258,6 +258,15 @@ struct DxcOutputObject {
                                     _In_opt_ IDxcBlob *pBlob) {
                                     _In_opt_ IDxcBlob *pBlob) {
     return DataOutput(kind, codePage, pBlob, DxcOutNoName);
     return DataOutput(kind, codePage, pBlob, DxcOutNoName);
   }
   }
+  static DxcOutputObject DataOutput(_In_ DXC_OUT_KIND kind,
+                                    _In_ UINT32 codePage,
+                                    _In_opt_ IUnknown *pBlob) {
+    DxcOutputObject output;
+    output.kind = kind;
+    IFT(output.SetObject(pBlob, codePage));
+    IFT(output.SetName(DxcOutNoName));
+    return output;
+  }
 
 
   template<typename DataTy>
   template<typename DataTy>
   static DxcOutputObject ErrorOutput(UINT32 codePage, DataTy pText, SIZE_T size) {
   static DxcOutputObject ErrorOutput(UINT32 codePage, DataTy pText, SIZE_T size) {
@@ -276,6 +285,92 @@ struct DxcOutputObject {
   }
   }
 };
 };
 
 
+struct DxcExtraOutputObject {
+  CComPtr<IDxcBlobUtf16> pType; // Custom name to identify the object
+  CComPtr<IDxcBlobUtf16> pName; // The file path for the output
+  CComPtr<IUnknown> pObject;    // The object itself
+};
+
+class DxcExtraOutputs : public IDxcExtraOutputs {
+  DXC_MICROCOM_TM_REF_FIELDS()
+
+  DxcExtraOutputObject *m_Objects = nullptr;
+  UINT32 m_uCount = 0;
+
+public:
+
+  DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
+  DXC_MICROCOM_TM_CTOR(DxcExtraOutputs)
+
+  ~DxcExtraOutputs() {
+    Clear();
+  }
+
+  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) override {
+    return DoBasicQueryInterface<IDxcExtraOutputs>(this, iid, ppvObject);
+  }
+
+  /////////////////////
+  // IDxcExtraOutputs
+  /////////////////////
+
+  UINT32 STDMETHODCALLTYPE GetOutputCount() override {
+    return m_uCount;
+  }
+
+  HRESULT STDMETHODCALLTYPE GetOutput(_In_ UINT32 uIndex,
+    _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject,
+    _COM_Outptr_opt_result_maybenull_ IDxcBlobUtf16 **ppOutputType,
+    _COM_Outptr_opt_result_maybenull_ IDxcBlobUtf16 **ppOutputName) override
+  {
+    if (uIndex >= m_uCount)
+      return E_INVALIDARG;
+
+    DxcExtraOutputObject *pObject = &m_Objects[uIndex];
+
+    if (ppOutputType) {
+      *ppOutputType = nullptr;
+      IFR(pObject->pType.CopyTo(ppOutputType));
+    }
+
+    if (ppOutputName) {
+      *ppOutputName = nullptr;
+      IFR(pObject->pName.CopyTo(ppOutputName));
+    }
+
+    if (ppvObject) {
+      *ppvObject = nullptr;
+      if (pObject->pObject) {
+        IFR(pObject->pObject->QueryInterface(iid, ppvObject));
+      }
+    }
+
+    return S_OK;
+  }
+
+  /////////////////////
+  // Internal Interface
+  /////////////////////
+  void Clear() {
+    m_uCount = 0;
+    if (m_Objects) {
+      delete[] m_Objects;
+      m_Objects = nullptr;
+    }
+  }
+
+  void SetOutputs(const llvm::ArrayRef<DxcExtraOutputObject> outputs) {
+    Clear();
+
+    m_uCount = outputs.size();
+    if (m_uCount > 0) {
+      m_Objects = new DxcExtraOutputObject[m_uCount];
+      for (UINT32 i = 0; i < outputs.size(); i++)
+        m_Objects[i] = outputs[i];
+    }
+  }
+};
+
 class DxcResult : public IDxcResult {
 class DxcResult : public IDxcResult {
 private:
 private:
   DXC_MICROCOM_TM_REF_FIELDS()
   DXC_MICROCOM_TM_REF_FIELDS()

+ 17 - 0
include/dxc/dxcapi.h

@@ -461,6 +461,7 @@ typedef enum DXC_OUT_KIND {
   DXC_OUT_TEXT = 7,           // IDxcBlobUtf8 or IDxcBlobUtf16 - other text, such as -ast-dump or -Odump
   DXC_OUT_TEXT = 7,           // IDxcBlobUtf8 or IDxcBlobUtf16 - other text, such as -ast-dump or -Odump
   DXC_OUT_REFLECTION = 8,     // IDxcBlob - RDAT part with reflection data
   DXC_OUT_REFLECTION = 8,     // IDxcBlob - RDAT part with reflection data
   DXC_OUT_ROOT_SIGNATURE = 9, // IDxcBlob - Serialized root signature output
   DXC_OUT_ROOT_SIGNATURE = 9, // IDxcBlob - Serialized root signature output
+  DXC_OUT_EXTRA_OUTPUTS  = 10,// IDxcExtraResults - Extra outputs
 
 
   DXC_OUT_FORCE_DWORD = 0xFFFFFFFF
   DXC_OUT_FORCE_DWORD = 0xFFFFFFFF
 } DXC_OUT_KIND;
 } DXC_OUT_KIND;
@@ -479,6 +480,22 @@ IDxcResult : public IDxcOperationResult {
   DECLARE_CROSS_PLATFORM_UUIDOF(IDxcResult)
   DECLARE_CROSS_PLATFORM_UUIDOF(IDxcResult)
 };
 };
 
 
+// Special names for extra output that should get written to specific streams
+#define DXC_EXTRA_OUTPUT_NAME_STDOUT L"*stdout*"
+#define DXC_EXTRA_OUTPUT_NAME_STDERR L"*stderr*"
+
+struct __declspec(uuid("319b37a2-a5c2-494a-a5de-4801b2faf989"))
+IDxcExtraOutputs : public IUnknown {
+
+  virtual UINT32 STDMETHODCALLTYPE GetOutputCount() = 0;
+  virtual HRESULT STDMETHODCALLTYPE GetOutput(_In_ UINT32 uIndex,
+    _In_ REFIID iid, _COM_Outptr_opt_result_maybenull_ void **ppvObject,
+    _COM_Outptr_opt_result_maybenull_ IDxcBlobUtf16 **ppOutputType,
+    _COM_Outptr_opt_result_maybenull_ IDxcBlobUtf16 **ppOutputName) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcExtraOutputs)
+};
+
 struct __declspec(uuid("228B4687-5A6A-4730-900C-9702B2203F54"))
 struct __declspec(uuid("228B4687-5A6A-4730-900C-9702B2203F54"))
 IDxcCompiler3 : public IUnknown {
 IDxcCompiler3 : public IUnknown {
   // Compile a single entry point to the target shader model,
   // Compile a single entry point to the target shader model,

+ 59 - 0
tools/clang/tools/dxclib/dxc.cpp

@@ -204,6 +204,64 @@ static void WriteDxcOutputToFile(DXC_OUT_KIND kind, IDxcResult *pResult, UINT32
   }
   }
 }
 }
 
 
+static bool StringBlobEqualUtf16(IDxcBlobUtf16 *pBlob, const WCHAR *pStr) {
+  size_t uSize = wcslen(pStr);
+  if (pBlob && pBlob->GetStringLength() == uSize) {
+    return 0 == memcmp(pBlob->GetBufferPointer(), pStr, pBlob->GetBufferSize());
+  }
+  return false;
+}
+
+static void WriteDxcExtraOuputs(IDxcResult *pResult) {
+  DXC_OUT_KIND kind = DXC_OUT_EXTRA_OUTPUTS;
+  if (!pResult->HasOutput(kind)) {
+    return;
+  }
+
+  CComPtr<IDxcExtraOutputs> pOutputs;
+  CComPtr<IDxcBlobUtf16> pName;
+  IFT(pResult->GetOutput(kind, IID_PPV_ARGS(&pOutputs), &pName));
+
+  UINT32 uOutputCount = pOutputs->GetOutputCount();
+  for (UINT32 i = 0; i < uOutputCount; i++) {
+    CComPtr<IDxcBlobUtf16> pFileName;
+    CComPtr<IDxcBlobUtf16> pType;
+    CComPtr<IDxcBlob> pBlob;
+    IFT(pOutputs->GetOutput(i, IID_PPV_ARGS(&pBlob), &pType, &pFileName));
+
+    // Not a blob
+    if (!pBlob)
+      continue;
+
+    UINT32 uCodePage = CP_ACP;
+    CComPtr<IDxcBlobEncoding> pBlobEncoding;
+    if (SUCCEEDED(pBlob.QueryInterface(&pBlobEncoding))) {
+      BOOL bKnown = FALSE;
+      UINT32 uKnownCodePage = CP_ACP;
+      IFT(pBlobEncoding->GetEncoding(&bKnown, &uKnownCodePage));
+      if (bKnown) {
+        uCodePage = uKnownCodePage;
+      }
+    }
+
+    if (pFileName && pFileName->GetStringLength() > 0) {
+      if (StringBlobEqualUtf16(pFileName, DXC_EXTRA_OUTPUT_NAME_STDOUT)) {
+        if (uCodePage != CP_ACP) {
+          WriteBlobToConsole(pBlob, STD_OUTPUT_HANDLE);
+        }
+      }
+      else if (StringBlobEqualUtf16(pFileName, DXC_EXTRA_OUTPUT_NAME_STDERR)) {
+        if (uCodePage != CP_ACP) {
+          WriteBlobToConsole(pBlob, STD_ERROR_HANDLE);
+        }
+      }
+      else {
+        WriteBlobToFile(pBlob, pFileName->GetStringPointer(), uCodePage);
+      }
+    }
+  }
+}
+
 // This function is called either after the compilation is done or /dumpbin option is provided
 // This function is called either after the compilation is done or /dumpbin option is provided
 // Performing options that are used to process dxil container.
 // Performing options that are used to process dxil container.
 int DxcContext::ActOnBlob(IDxcBlob *pBlob) {
 int DxcContext::ActOnBlob(IDxcBlob *pBlob) {
@@ -846,6 +904,7 @@ int DxcContext::Compile() {
         WriteDxcOutputToFile(DXC_OUT_ROOT_SIGNATURE, pResult, m_Opts.DefaultTextCodePage);
         WriteDxcOutputToFile(DXC_OUT_ROOT_SIGNATURE, pResult, m_Opts.DefaultTextCodePage);
         WriteDxcOutputToFile(DXC_OUT_SHADER_HASH, pResult, m_Opts.DefaultTextCodePage);
         WriteDxcOutputToFile(DXC_OUT_SHADER_HASH, pResult, m_Opts.DefaultTextCodePage);
         WriteDxcOutputToFile(DXC_OUT_REFLECTION, pResult, m_Opts.DefaultTextCodePage);
         WriteDxcOutputToFile(DXC_OUT_REFLECTION, pResult, m_Opts.DefaultTextCodePage);
+        WriteDxcExtraOuputs(pResult);
       }
       }
     }
     }
   }
   }

+ 1 - 0
tools/clang/tools/dxcompiler/dxcapi.cpp

@@ -51,6 +51,7 @@ DEFINE_CROSS_PLATFORM_UUIDOF(IDxcBlobUtf8)
 DEFINE_CROSS_PLATFORM_UUIDOF(IDxcCompilerArgs)
 DEFINE_CROSS_PLATFORM_UUIDOF(IDxcCompilerArgs)
 DEFINE_CROSS_PLATFORM_UUIDOF(IDxcUtils)
 DEFINE_CROSS_PLATFORM_UUIDOF(IDxcUtils)
 DEFINE_CROSS_PLATFORM_UUIDOF(IDxcResult)
 DEFINE_CROSS_PLATFORM_UUIDOF(IDxcResult)
+DEFINE_CROSS_PLATFORM_UUIDOF(IDxcExtraOutputs)
 DEFINE_CROSS_PLATFORM_UUIDOF(IDxcCompiler3)
 DEFINE_CROSS_PLATFORM_UUIDOF(IDxcCompiler3)
 
 
 HRESULT CreateDxcCompiler(_In_ REFIID riid, _Out_ LPVOID *ppv);
 HRESULT CreateDxcCompiler(_In_ REFIID riid, _Out_ LPVOID *ppv);