/* * Copyright 1993-2018 NVIDIA Corporation. All rights reserved. * * Please refer to the NVIDIA end user license agreement (EULA) associated * with this source code for terms and conditions that govern your use of * this software. Any use, reproduction, disclosure, or distribution of * this software and related documentation outside the terms of the EULA * is strictly prohibited. * */ #pragma once // Note that while ComPtr is used to manage the lifetime of resources on the CPU, // it has no understanding of the lifetime of resources on the GPU. Apps must account // for the GPU lifetime of resources to avoid destroying objects that may still be // referenced by the GPU. using Microsoft::WRL::ComPtr; inline std::string HrToString(HRESULT hr) { char s_str[64] = {}; sprintf_s(s_str, "HRESULT of 0x%08X", static_cast(hr)); return std::string(s_str); } class HrException : public std::runtime_error { public: HrException(HRESULT hr) : std::runtime_error(HrToString(hr)), m_hr(hr) {} HRESULT Error() const { return m_hr; } private: const HRESULT m_hr; }; #define SAFE_RELEASE(p) if (p) (p)->Release() inline void ThrowIfFailed(HRESULT hr) { if (FAILED(hr)) { throw HrException(hr); } } inline HRESULT ReadDataFromFile(LPCWSTR filename, byte** data, UINT* size) { using namespace Microsoft::WRL; CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {}; extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN; extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; extendedParams.lpSecurityAttributes = nullptr; extendedParams.hTemplateFile = nullptr; Wrappers::FileHandle file(CreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &extendedParams)); if (file.Get() == INVALID_HANDLE_VALUE) { throw std::exception(); } FILE_STANDARD_INFO fileInfo = {}; if (!GetFileInformationByHandleEx(file.Get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) { throw std::exception(); } if (fileInfo.EndOfFile.HighPart != 0) { throw std::exception(); } *data = reinterpret_cast(malloc(fileInfo.EndOfFile.LowPart)); *size = fileInfo.EndOfFile.LowPart; if (!ReadFile(file.Get(), *data, fileInfo.EndOfFile.LowPart, nullptr, nullptr)) { throw std::exception(); } return S_OK; } // Assign a name to the object to aid with debugging. #if defined(_DEBUG) || defined(DBG) inline void SetName(ID3D12Object* pObject, LPCWSTR name) { pObject->SetName(name); } inline void SetNameIndexed(ID3D12Object* pObject, LPCWSTR name, UINT index) { WCHAR fullName[50]; if (swprintf_s(fullName, L"%s[%u]", name, index) > 0) { pObject->SetName(fullName); } } #else inline void SetName(ID3D12Object*, LPCWSTR) { } inline void SetNameIndexed(ID3D12Object*, LPCWSTR, UINT) { } #endif // Naming helper for ComPtr. // Assigns the name of the variable as the name of the object. // The indexed variant will include the index in the name of the object. #define NAME_D3D12_OBJECT(x) SetName((x).Get(), L#x) #define NAME_D3D12_OBJECT_INDEXED(x, n) SetNameIndexed((x)[n].Get(), L#x, n) inline UINT CalculateConstantBufferByteSize(UINT byteSize) { // Constant buffer size is required to be aligned. return (byteSize + (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1)) & ~(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1); } #ifdef D3D_COMPILE_STANDARD_FILE_INCLUDE inline Microsoft::WRL::ComPtr CompileShader( const std::wstring& filename, const D3D_SHADER_MACRO* defines, const std::string& entrypoint, const std::string& target) { UINT compileFlags = 0; #if defined(_DEBUG) || defined(DBG) compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #endif HRESULT hr; Microsoft::WRL::ComPtr byteCode = nullptr; Microsoft::WRL::ComPtr errors; hr = D3DCompileFromFile(filename.c_str(), defines, D3D_COMPILE_STANDARD_FILE_INCLUDE, entrypoint.c_str(), target.c_str(), compileFlags, 0, &byteCode, &errors); if (errors != nullptr) { OutputDebugStringA((char*)errors->GetBufferPointer()); } ThrowIfFailed(hr); return byteCode; } #endif // Resets all elements in a ComPtr array. template void ResetComPtrArray(T* comPtrArray) { for (auto &i : *comPtrArray) { i.Reset(); } } // Resets all elements in a unique_ptr array. template void ResetUniquePtrArray(T* uniquePtrArray) { for (auto &i : *uniquePtrArray) { i.reset(); } }