ソースを参照

Replacing fileIO exceptions with error codes (#4841)

Exceptions for error handling can have a significant performance impact. The exception-throw codepaths are usually cold, and rely on large in-memory tables that need to be paged in.

This change to instead propagate returned error codes simplifies the code and allows the compiler to more aggressively optimize around both success and failure conditions.
harshpg 2 年 前
コミット
6eedcd2afa

+ 7 - 8
include/dxc/Support/FileIOHelper.h

@@ -116,16 +116,16 @@ public:
   }
 };
 
-void ReadBinaryFile(_In_opt_ IMalloc *pMalloc,
+HRESULT ReadBinaryFile(_In_opt_ IMalloc *pMalloc,
                     _In_z_ LPCWSTR pFileName,
                     _Outptr_result_bytebuffer_(*pDataSize) void **ppData,
-                    _Out_ DWORD *pDataSize);
-void ReadBinaryFile(_In_z_ LPCWSTR pFileName,
+                    _Out_ DWORD *pDataSize) throw();
+HRESULT ReadBinaryFile(_In_z_ LPCWSTR pFileName,
                     _Outptr_result_bytebuffer_(*pDataSize) void **ppData,
-                    _Out_ DWORD *pDataSize);
-void WriteBinaryFile(_In_z_ LPCWSTR pFileName,
+                    _Out_ DWORD *pDataSize) throw();
+HRESULT WriteBinaryFile(_In_z_ LPCWSTR pFileName,
                      _In_reads_bytes_(DataSize) const void *pData,
-                     _In_ DWORD DataSize);
+                     _In_ DWORD DataSize) throw();
 
 ///////////////////////////////////////////////////////////////////////////////
 // Blob and encoding manipulation functions.
@@ -153,8 +153,7 @@ HRESULT DxcCreateBlobEncodingFromBlob(
     IMalloc *pMalloc, IDxcBlobEncoding **ppBlobEncoding) throw();
 
 // Load files
-HRESULT
-DxcCreateBlobFromFile(_In_opt_ IMalloc *pMalloc, LPCWSTR pFileName,
+HRESULT DxcCreateBlobFromFile(_In_opt_ IMalloc *pMalloc, LPCWSTR pFileName,
                       _In_opt_ UINT32 *pCodePage,
                       _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw();
 

+ 19 - 16
lib/DxcSupport/FileIOHelper.cpp

@@ -92,60 +92,63 @@ IMalloc *GetGlobalHeapMalloc() throw() {
 }
 
 _Use_decl_annotations_
-void ReadBinaryFile(IMalloc *pMalloc, LPCWSTR pFileName, void **ppData,
-                    DWORD *pDataSize) {
+HRESULT ReadBinaryFile(IMalloc *pMalloc, LPCWSTR pFileName, void **ppData,
+                    DWORD *pDataSize) throw() {
   HANDLE hFile = CreateFileW(pFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                              OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
   if (hFile == INVALID_HANDLE_VALUE) {
-    IFT(HRESULT_FROM_WIN32(GetLastError()));
+    return HRESULT_FROM_WIN32(GetLastError());
   }
 
   CHandle h(hFile);
 
   LARGE_INTEGER FileSize;
   if (!GetFileSizeEx(hFile, &FileSize)) {
-    IFT(HRESULT_FROM_WIN32(GetLastError()));
+    return HRESULT_FROM_WIN32(GetLastError());
   }
   if (FileSize.u.HighPart != 0) {
-    throw(hlsl::Exception(DXC_E_INPUT_FILE_TOO_LARGE, "input file is too large"));
+    return DXC_E_INPUT_FILE_TOO_LARGE;
   }
 
   char *pData = (char *)pMalloc->Alloc(FileSize.u.LowPart);
   if (!pData) {
-    throw std::bad_alloc();
+    return E_OUTOFMEMORY;
   }
 
   DWORD BytesRead;
   if (!ReadFile(hFile, pData, FileSize.u.LowPart, &BytesRead, nullptr)) {
     HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
     pMalloc->Free(pData);
-    throw ::hlsl::Exception(hr);
+    return hr;
   }
   DXASSERT(FileSize.u.LowPart == BytesRead, "ReadFile operation failed");
 
   *ppData = pData;
   *pDataSize = FileSize.u.LowPart;
 
+  return S_OK;
 }
 
 _Use_decl_annotations_
-void ReadBinaryFile(LPCWSTR pFileName, void **ppData, DWORD *pDataSize) {
+HRESULT ReadBinaryFile(LPCWSTR pFileName, void **ppData, DWORD *pDataSize) throw() {
   return ReadBinaryFile(GetGlobalHeapMalloc(), pFileName, ppData, pDataSize);
 }
 
 _Use_decl_annotations_
-void WriteBinaryFile(LPCWSTR pFileName, const void *pData, DWORD DataSize) {
+HRESULT WriteBinaryFile(LPCWSTR pFileName, const void *pData, DWORD DataSize) throw() {
   HANDLE hFile = CreateFileW(pFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
   if(hFile == INVALID_HANDLE_VALUE) {
-    IFT(HRESULT_FROM_WIN32(GetLastError()));
+    return HRESULT_FROM_WIN32(GetLastError());
   }
   CHandle h(hFile);
 
   DWORD BytesWritten;
   if(!WriteFile(hFile, pData, DataSize, &BytesWritten, nullptr)) {
-    IFT(HRESULT_FROM_WIN32(GetLastError()));
+    return HRESULT_FROM_WIN32(GetLastError());
   }
   DXASSERT(DataSize == BytesWritten, "WriteFile operation failed");
+
+  return S_OK;
 }
 
 _Use_decl_annotations_
@@ -825,15 +828,15 @@ DxcCreateBlobFromFile(IMalloc *pMalloc, LPCWSTR pFileName, UINT32 *pCodePage,
   LPVOID pData;
   DWORD dataSize;
   *ppBlobEncoding = nullptr;
-  try {
-    ReadBinaryFile(pMalloc, pFileName, &pData, &dataSize);
-  }
-  CATCH_CPP_RETURN_HRESULT();
+
+  HRESULT hr = ReadBinaryFile(pMalloc, pFileName, &pData, &dataSize);
+  if (FAILED(hr))
+    return hr;
 
   bool known = (pCodePage != nullptr);
   UINT32 codePage = (pCodePage != nullptr) ? *pCodePage : 0;
 
-  HRESULT hr = DxcCreateBlob(pData, dataSize, false, false, known, codePage, pMalloc, ppBlobEncoding);
+  hr = DxcCreateBlob(pData, dataSize, false, false, known, codePage, pMalloc, ppBlobEncoding);
   if (FAILED(hr))
     pMalloc->Free(pData);
   return hr;

+ 3 - 3
projects/dxilconv/tools/dxbc2dxil/dxbc2dxil.cpp

@@ -200,7 +200,7 @@ void Converter::Run() {
   // Load DXBC blob.
   CComHeapPtr<void> pDxbcPtr;
   DWORD DxbcSize;
-  hlsl::ReadBinaryFile(m_InputFile.c_str(), &pDxbcPtr, &DxbcSize);
+  IFT(hlsl::ReadBinaryFile(m_InputFile.c_str(), &pDxbcPtr, &DxbcSize));
 
   // Disassemble Dxbc blob and exit.
   if (m_bDisasmDxbc) {
@@ -222,7 +222,7 @@ void Converter::Run() {
     if (m_OutputFile.empty())
       printf("%s", pText);
     else
-      hlsl::WriteBinaryFile(m_OutputFile.c_str(), pText, strlen(pText));
+      IFT(hlsl::WriteBinaryFile(m_OutputFile.c_str(), pText, strlen(pText)));
 
     return;
   }
@@ -291,7 +291,7 @@ void Converter::Run() {
     }
   }
 
-  hlsl::WriteBinaryFile(m_OutputFile.c_str(), pOutput, OutputSize);
+  IFT(hlsl::WriteBinaryFile(m_OutputFile.c_str(), pOutput, OutputSize));
 }
 
 HRESULT Converter::CreateDxcLibrary(_Outptr_ IDxcLibrary **ppLibrary) {

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

@@ -535,7 +535,7 @@ HRESULT DxcContext::ReadFileIntoPartContent(hlsl::DxilFourCC fourCC, LPCWSTR fil
     CComPtr<IDxcBlob> pResult;
     CComHeapPtr<BYTE> pData;
     DWORD dataSize;
-    hlsl::ReadBinaryFile(fileName, (void**)&pData, &dataSize);
+    IFT(hlsl::ReadBinaryFile(fileName, (void**)&pData, &dataSize));
     DXASSERT(pData != nullptr, "otherwise ReadBinaryFile should throw an exception");
     hlsl::DxilContainerHeader *pHeader = hlsl::IsDxilContainerLike(pData.m_pData, dataSize);
     IFRBOOL(hlsl::IsValidDxilContainer(pHeader, dataSize), E_INVALIDARG);

+ 1 - 4
tools/clang/tools/dxcompiler/dxclibrary.cpp

@@ -277,10 +277,7 @@ public:
     _In_z_ LPCWSTR pFileName, _In_opt_ UINT32* pCodePage,
     _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) override {
     DxcThreadMalloc TM(m_pMalloc);
-    try {
-      return ::hlsl::DxcCreateBlobFromFile(pFileName, pCodePage, pBlobEncoding);
-    }
-    CATCH_CPP_RETURN_HRESULT();
+    return ::hlsl::DxcCreateBlobFromFile(pFileName, pCodePage, pBlobEncoding);
   }
 
   HRESULT STDMETHODCALLTYPE CreateReadOnlyStreamFromBlob(

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

@@ -193,7 +193,7 @@ static void SavePixelsToFile(LPCVOID pPixels, DXGI_FORMAT format, UINT32 m_width
   VERIFY_SUCCEEDED(pFrameEncode->WriteSource(pBitmap, nullptr));
   VERIFY_SUCCEEDED(pFrameEncode->Commit());
   VERIFY_SUCCEEDED(pEncoder->Commit());
-  hlsl::WriteBinaryFile(pFileName, pStream->GetPtr(), pStream->GetPtrSize());
+  IFT(hlsl::WriteBinaryFile(pFileName, pStream->GetPtr(), pStream->GetPtrSize()));
 }
 
 // Checks if the given warp version supports the given operation.

+ 1 - 1
tools/clang/unittests/dxc_batch/dxc_batch.cpp

@@ -406,7 +406,7 @@ HRESULT DxcContext::ReadFileIntoPartContent(hlsl::DxilFourCC fourCC,
     CComPtr<IDxcBlob> pResult;
     CComHeapPtr<BYTE> pData;
     DWORD dataSize;
-    hlsl::ReadBinaryFile(fileName, (void **)&pData, &dataSize);
+    IFT(hlsl::ReadBinaryFile(fileName, (void **)&pData, &dataSize));
     DXASSERT(pData != nullptr,
              "otherwise ReadBinaryFile should throw an exception");
     hlsl::DxilContainerHeader *pHeader =