mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-25 22:28:17 +08:00
Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.
This commit is contained in:
126
Samples/5_Domain_Specific/simpleD3D12/DX12CudaSample.cpp
Executable file → Normal file
126
Samples/5_Domain_Specific/simpleD3D12/DX12CudaSample.cpp
Executable file → Normal file
@@ -50,95 +50,101 @@ The MIT License (MIT)
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DX12CudaSample.h"
|
||||
|
||||
#include <helper_string.h>
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
DX12CudaSample::DX12CudaSample(UINT width, UINT height, std::string name)
|
||||
: m_width(width), m_height(height), m_title(name), m_useWarpDevice(false) {
|
||||
m_aspectRatio = static_cast<float>(width) / static_cast<float>(height);
|
||||
: m_width(width)
|
||||
, m_height(height)
|
||||
, m_title(name)
|
||||
, m_useWarpDevice(false)
|
||||
{
|
||||
m_aspectRatio = static_cast<float>(width) / static_cast<float>(height);
|
||||
}
|
||||
|
||||
DX12CudaSample::~DX12CudaSample() {}
|
||||
|
||||
std::wstring DX12CudaSample::string2wstring(const std::string& s) {
|
||||
int len;
|
||||
int slength = (int)s.length() + 1;
|
||||
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
|
||||
wchar_t* buf = new wchar_t[len];
|
||||
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
|
||||
std::wstring r(buf);
|
||||
delete[] buf;
|
||||
return r;
|
||||
std::wstring DX12CudaSample::string2wstring(const std::string &s)
|
||||
{
|
||||
int len;
|
||||
int slength = (int)s.length() + 1;
|
||||
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
|
||||
wchar_t *buf = new wchar_t[len];
|
||||
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
|
||||
std::wstring r(buf);
|
||||
delete[] buf;
|
||||
return r;
|
||||
}
|
||||
// Helper function for resolving the full path of assets.
|
||||
std::wstring DX12CudaSample::GetAssetFullPath(const char* assetName) {
|
||||
LPTSTR lpBuffer = new char[4096];
|
||||
GetCurrentDirectory(FILENAME_MAX, lpBuffer);
|
||||
char* tmp = sdkFindFilePath((const char*)assetName, "simpleD3D12");
|
||||
if (tmp == NULL) {
|
||||
throw std::exception("File not found");
|
||||
}
|
||||
for (int i = 0; i < strlen(tmp); i++) {
|
||||
if (tmp[i] == '/') {
|
||||
tmp[i] = '\\';
|
||||
std::wstring DX12CudaSample::GetAssetFullPath(const char *assetName)
|
||||
{
|
||||
LPTSTR lpBuffer = new char[4096];
|
||||
GetCurrentDirectory(FILENAME_MAX, lpBuffer);
|
||||
char *tmp = sdkFindFilePath((const char *)assetName, "simpleD3D12");
|
||||
if (tmp == NULL) {
|
||||
throw std::exception("File not found");
|
||||
}
|
||||
}
|
||||
m_assetsPath = lpBuffer;
|
||||
m_assetsPath = m_assetsPath + "\\" + tmp;
|
||||
for (int i = 0; i < strlen(tmp); i++) {
|
||||
if (tmp[i] == '/') {
|
||||
tmp[i] = '\\';
|
||||
}
|
||||
}
|
||||
m_assetsPath = lpBuffer;
|
||||
m_assetsPath = m_assetsPath + "\\" + tmp;
|
||||
|
||||
std::wstring stemp = string2wstring(m_assetsPath);
|
||||
std::wstring stemp = string2wstring(m_assetsPath);
|
||||
|
||||
return stemp;
|
||||
return stemp;
|
||||
}
|
||||
|
||||
// Helper function for acquiring the first available hardware adapter that
|
||||
// supports Direct3D 12. If no such adapter can be found, *ppAdapter will be set
|
||||
// to nullptr.
|
||||
_Use_decl_annotations_ void DX12CudaSample::GetHardwareAdapter(
|
||||
IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter) {
|
||||
ComPtr<IDXGIAdapter1> adapter;
|
||||
*ppAdapter = nullptr;
|
||||
_Use_decl_annotations_ void DX12CudaSample::GetHardwareAdapter(IDXGIFactory2 *pFactory, IDXGIAdapter1 **ppAdapter)
|
||||
{
|
||||
ComPtr<IDXGIAdapter1> adapter;
|
||||
*ppAdapter = nullptr;
|
||||
|
||||
for (UINT adapterIndex = 0;
|
||||
DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &adapter);
|
||||
++adapterIndex) {
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
adapter->GetDesc1(&desc);
|
||||
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &adapter);
|
||||
++adapterIndex) {
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
adapter->GetDesc1(&desc);
|
||||
|
||||
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||
// Don't select the Basic Render Driver adapter.
|
||||
// If you want a software adapter, pass in "/warp" on the command line.
|
||||
continue;
|
||||
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||
// Don't select the Basic Render Driver adapter.
|
||||
// If you want a software adapter, pass in "/warp" on the command line.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check to see if the adapter supports Direct3D 12, but don't create the
|
||||
// actual device yet.
|
||||
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if the adapter supports Direct3D 12, but don't create the
|
||||
// actual device yet.
|
||||
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0,
|
||||
_uuidof(ID3D12Device), nullptr))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*ppAdapter = adapter.Detach();
|
||||
*ppAdapter = adapter.Detach();
|
||||
}
|
||||
|
||||
// Helper function for setting the window's title text.
|
||||
void DX12CudaSample::SetCustomWindowText(const char* text) {
|
||||
std::string windowText = m_title + text;
|
||||
SetWindowText(Win32Application::GetHwnd(), windowText.c_str());
|
||||
void DX12CudaSample::SetCustomWindowText(const char *text)
|
||||
{
|
||||
std::string windowText = m_title + text;
|
||||
SetWindowText(Win32Application::GetHwnd(), windowText.c_str());
|
||||
}
|
||||
|
||||
// Helper function for parsing any supplied command line args.
|
||||
_Use_decl_annotations_ void DX12CudaSample::ParseCommandLineArgs(WCHAR* argv[],
|
||||
int argc) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (_wcsnicmp(argv[i], L"-warp", wcslen(argv[i])) == 0 ||
|
||||
_wcsnicmp(argv[i], L"/warp", wcslen(argv[i])) == 0) {
|
||||
m_useWarpDevice = true;
|
||||
m_title = m_title + " (WARP)";
|
||||
_Use_decl_annotations_ void DX12CudaSample::ParseCommandLineArgs(WCHAR *argv[], int argc)
|
||||
{
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (_wcsnicmp(argv[i], L"-warp", wcslen(argv[i])) == 0 || _wcsnicmp(argv[i], L"/warp", wcslen(argv[i])) == 0) {
|
||||
m_useWarpDevice = true;
|
||||
m_title = m_title + " (WARP)";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
64
Samples/5_Domain_Specific/simpleD3D12/DX12CudaSample.h
Executable file → Normal file
64
Samples/5_Domain_Specific/simpleD3D12/DX12CudaSample.h
Executable file → Normal file
@@ -55,45 +55,45 @@ The MIT License (MIT)
|
||||
#include "DXSampleHelper.h"
|
||||
#include "Win32Application.h"
|
||||
|
||||
class DX12CudaSample {
|
||||
public:
|
||||
DX12CudaSample(UINT width, UINT height, std::string name);
|
||||
virtual ~DX12CudaSample();
|
||||
class DX12CudaSample
|
||||
{
|
||||
public:
|
||||
DX12CudaSample(UINT width, UINT height, std::string name);
|
||||
virtual ~DX12CudaSample();
|
||||
|
||||
virtual void OnInit() = 0;
|
||||
virtual void OnRender() = 0;
|
||||
virtual void OnDestroy() = 0;
|
||||
virtual void OnInit() = 0;
|
||||
virtual void OnRender() = 0;
|
||||
virtual void OnDestroy() = 0;
|
||||
|
||||
// Samples override the event handlers to handle specific messages.
|
||||
virtual void OnKeyDown(UINT8 /*key*/) {}
|
||||
virtual void OnKeyUp(UINT8 /*key*/) {}
|
||||
// Samples override the event handlers to handle specific messages.
|
||||
virtual void OnKeyDown(UINT8 /*key*/) {}
|
||||
virtual void OnKeyUp(UINT8 /*key*/) {}
|
||||
|
||||
// Accessors.
|
||||
UINT GetWidth() const { return m_width; }
|
||||
UINT GetHeight() const { return m_height; }
|
||||
const CHAR* GetTitle() const { return m_title.c_str(); }
|
||||
// Accessors.
|
||||
UINT GetWidth() const { return m_width; }
|
||||
UINT GetHeight() const { return m_height; }
|
||||
const CHAR *GetTitle() const { return m_title.c_str(); }
|
||||
|
||||
void ParseCommandLineArgs(_In_reads_(argc) WCHAR* argv[], int argc);
|
||||
void ParseCommandLineArgs(_In_reads_(argc) WCHAR *argv[], int argc);
|
||||
|
||||
protected:
|
||||
std::wstring GetAssetFullPath(const char* assetName);
|
||||
void GetHardwareAdapter(_In_ IDXGIFactory2* pFactory,
|
||||
_Outptr_result_maybenull_ IDXGIAdapter1** ppAdapter);
|
||||
void SetCustomWindowText(const char* text);
|
||||
std::wstring string2wstring(const std::string& s);
|
||||
protected:
|
||||
std::wstring GetAssetFullPath(const char *assetName);
|
||||
void GetHardwareAdapter(_In_ IDXGIFactory2 *pFactory, _Outptr_result_maybenull_ IDXGIAdapter1 **ppAdapter);
|
||||
void SetCustomWindowText(const char *text);
|
||||
std::wstring string2wstring(const std::string &s);
|
||||
|
||||
// Viewport dimensions.
|
||||
UINT m_width;
|
||||
UINT m_height;
|
||||
float m_aspectRatio;
|
||||
// Viewport dimensions.
|
||||
UINT m_width;
|
||||
UINT m_height;
|
||||
float m_aspectRatio;
|
||||
|
||||
// Adapter info.
|
||||
bool m_useWarpDevice;
|
||||
// Adapter info.
|
||||
bool m_useWarpDevice;
|
||||
|
||||
private:
|
||||
// Root assets path.
|
||||
std::string m_assetsPath;
|
||||
private:
|
||||
// Root assets path.
|
||||
std::string m_assetsPath;
|
||||
|
||||
// Window title.
|
||||
std::string m_title;
|
||||
// Window title.
|
||||
std::string m_title;
|
||||
};
|
||||
|
||||
184
Samples/5_Domain_Specific/simpleD3D12/DXSampleHelper.h
Executable file → Normal file
184
Samples/5_Domain_Specific/simpleD3D12/DXSampleHelper.h
Executable file → Normal file
@@ -59,134 +59,148 @@ The MIT License (MIT)
|
||||
// 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<UINT>(hr));
|
||||
return std::string(s_str);
|
||||
inline std::string HrToString(HRESULT hr)
|
||||
{
|
||||
char s_str[64] = {};
|
||||
sprintf_s(s_str, "HRESULT of 0x%08X", static_cast<UINT>(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; }
|
||||
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;
|
||||
private:
|
||||
const HRESULT m_hr;
|
||||
};
|
||||
|
||||
#define SAFE_RELEASE(p) \
|
||||
if (p) (p)->Release()
|
||||
if (p) \
|
||||
(p)->Release()
|
||||
|
||||
inline void ThrowIfFailed(HRESULT hr) {
|
||||
if (FAILED(hr)) {
|
||||
throw HrException(hr);
|
||||
}
|
||||
inline void ThrowIfFailed(HRESULT hr)
|
||||
{
|
||||
if (FAILED(hr)) {
|
||||
throw HrException(hr);
|
||||
}
|
||||
}
|
||||
|
||||
inline HRESULT ReadDataFromFile(LPCWSTR filename, byte** data, UINT* size) {
|
||||
using namespace Microsoft::WRL;
|
||||
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;
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
FILE_STANDARD_INFO fileInfo = {};
|
||||
if (!GetFileInformationByHandleEx(file.Get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) {
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
if (fileInfo.EndOfFile.HighPart != 0) {
|
||||
throw std::exception();
|
||||
}
|
||||
if (fileInfo.EndOfFile.HighPart != 0) {
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
*data = reinterpret_cast<byte*>(malloc(fileInfo.EndOfFile.LowPart));
|
||||
*size = fileInfo.EndOfFile.LowPart;
|
||||
*data = reinterpret_cast<byte *>(malloc(fileInfo.EndOfFile.LowPart));
|
||||
*size = fileInfo.EndOfFile.LowPart;
|
||||
|
||||
if (!ReadFile(file.Get(), *data, fileInfo.EndOfFile.LowPart, nullptr,
|
||||
nullptr)) {
|
||||
throw std::exception();
|
||||
}
|
||||
if (!ReadFile(file.Get(), *data, fileInfo.EndOfFile.LowPart, nullptr, nullptr)) {
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
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);
|
||||
}
|
||||
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) {}
|
||||
inline void SetName(ID3D12Object *, LPCWSTR) {}
|
||||
inline void SetNameIndexed(ID3D12Object *, LPCWSTR, UINT) {}
|
||||
#endif
|
||||
|
||||
// Naming helper for ComPtr<T>.
|
||||
// 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(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);
|
||||
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<ID3DBlob> CompileShader(
|
||||
const std::wstring& filename, const D3D_SHADER_MACRO* defines,
|
||||
const std::string& entrypoint, const std::string& target) {
|
||||
UINT compileFlags = 0;
|
||||
inline Microsoft::WRL::ComPtr<ID3DBlob> 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;
|
||||
compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#endif
|
||||
|
||||
HRESULT hr;
|
||||
HRESULT hr;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> byteCode = nullptr;
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> errors;
|
||||
hr = D3DCompileFromFile(filename.c_str(), defines,
|
||||
D3D_COMPILE_STANDARD_FILE_INCLUDE, entrypoint.c_str(),
|
||||
target.c_str(), compileFlags, 0, &byteCode, &errors);
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> byteCode = nullptr;
|
||||
Microsoft::WRL::ComPtr<ID3DBlob> 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);
|
||||
if (errors != nullptr) {
|
||||
OutputDebugStringA((char *)errors->GetBufferPointer());
|
||||
}
|
||||
ThrowIfFailed(hr);
|
||||
|
||||
return byteCode;
|
||||
return byteCode;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Resets all elements in a ComPtr array.
|
||||
template <class T>
|
||||
void ResetComPtrArray(T* comPtrArray) {
|
||||
for (auto& i : *comPtrArray) {
|
||||
i.Reset();
|
||||
}
|
||||
template <class T> void ResetComPtrArray(T *comPtrArray)
|
||||
{
|
||||
for (auto &i : *comPtrArray) {
|
||||
i.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Resets all elements in a unique_ptr array.
|
||||
template <class T>
|
||||
void ResetUniquePtrArray(T* uniquePtrArray) {
|
||||
for (auto& i : *uniquePtrArray) {
|
||||
i.reset();
|
||||
}
|
||||
template <class T> void ResetUniquePtrArray(T *uniquePtrArray)
|
||||
{
|
||||
for (auto &i : *uniquePtrArray) {
|
||||
i.reset();
|
||||
}
|
||||
}
|
||||
|
||||
10
Samples/5_Domain_Specific/simpleD3D12/Main.cpp
Executable file → Normal file
10
Samples/5_Domain_Specific/simpleD3D12/Main.cpp
Executable file → Normal file
@@ -25,11 +25,11 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "simpleD3D12.h"
|
||||
#include "stdafx.h"
|
||||
|
||||
_Use_decl_annotations_ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR,
|
||||
int nCmdShow) {
|
||||
DX12CudaInterop sample(1280, 720, "D3D12 CUDA Interop");
|
||||
return Win32Application::Run(&sample, hInstance, nCmdShow);
|
||||
_Use_decl_annotations_ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
|
||||
{
|
||||
DX12CudaInterop sample(1280, 720, "D3D12 CUDA Interop");
|
||||
return Win32Application::Run(&sample, hInstance, nCmdShow);
|
||||
}
|
||||
|
||||
@@ -34,4 +34,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
|
||||
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
|
||||
|
||||
## References (for more details)
|
||||
|
||||
|
||||
20
Samples/5_Domain_Specific/simpleD3D12/ShaderStructs.h
Executable file → Normal file
20
Samples/5_Domain_Specific/simpleD3D12/ShaderStructs.h
Executable file → Normal file
@@ -27,21 +27,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include <D3Dcompiler.h>
|
||||
#include <DirectXMath.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
|
||||
#include "helper_cuda.h"
|
||||
|
||||
using namespace DirectX;
|
||||
|
||||
struct Vertex {
|
||||
XMFLOAT3 position;
|
||||
XMFLOAT4 color;
|
||||
struct Vertex
|
||||
{
|
||||
XMFLOAT3 position;
|
||||
XMFLOAT4 color;
|
||||
};
|
||||
|
||||
|
||||
void RunSineWaveKernel(size_t mesh_width, size_t mesh_height,
|
||||
Vertex *cudaDevVertptr, cudaStream_t streamToRun,
|
||||
float AnimTime);
|
||||
void RunSineWaveKernel(size_t mesh_width,
|
||||
size_t mesh_height,
|
||||
Vertex *cudaDevVertptr,
|
||||
cudaStream_t streamToRun,
|
||||
float AnimTime);
|
||||
|
||||
143
Samples/5_Domain_Specific/simpleD3D12/Win32Application.cpp
Executable file → Normal file
143
Samples/5_Domain_Specific/simpleD3D12/Win32Application.cpp
Executable file → Normal file
@@ -50,103 +50,104 @@ The MIT License (MIT)
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Win32Application.h"
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
HWND Win32Application::m_hwnd = nullptr;
|
||||
|
||||
int Win32Application::Run(DX12CudaSample* pSample, HINSTANCE hInstance,
|
||||
int nCmdShow) {
|
||||
// Parse the command line parameters
|
||||
int argc;
|
||||
LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
pSample->ParseCommandLineArgs(argv, argc);
|
||||
LocalFree(argv);
|
||||
int Win32Application::Run(DX12CudaSample *pSample, HINSTANCE hInstance, int nCmdShow)
|
||||
{
|
||||
// Parse the command line parameters
|
||||
int argc;
|
||||
LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
pSample->ParseCommandLineArgs(argv, argc);
|
||||
LocalFree(argv);
|
||||
|
||||
// Initialize the window class.
|
||||
WNDCLASSEX windowClass = {0};
|
||||
windowClass.cbSize = sizeof(WNDCLASSEX);
|
||||
windowClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
windowClass.lpfnWndProc = WindowProc;
|
||||
windowClass.hInstance = hInstance;
|
||||
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
windowClass.lpszClassName = "DX12CudaSampleClass";
|
||||
RegisterClassEx(&windowClass);
|
||||
// Initialize the window class.
|
||||
WNDCLASSEX windowClass = {0};
|
||||
windowClass.cbSize = sizeof(WNDCLASSEX);
|
||||
windowClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
windowClass.lpfnWndProc = WindowProc;
|
||||
windowClass.hInstance = hInstance;
|
||||
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
windowClass.lpszClassName = "DX12CudaSampleClass";
|
||||
RegisterClassEx(&windowClass);
|
||||
|
||||
RECT windowRect = {0, 0, static_cast<LONG>(pSample->GetWidth()),
|
||||
static_cast<LONG>(pSample->GetHeight())};
|
||||
AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
RECT windowRect = {0, 0, static_cast<LONG>(pSample->GetWidth()), static_cast<LONG>(pSample->GetHeight())};
|
||||
AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
|
||||
// Create the window and store a handle to it.
|
||||
m_hwnd = CreateWindow(windowClass.lpszClassName, pSample->GetTitle(),
|
||||
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
windowRect.right - windowRect.left,
|
||||
windowRect.bottom - windowRect.top,
|
||||
nullptr, // We have no parent window.
|
||||
nullptr, // We aren't using menus.
|
||||
hInstance, pSample);
|
||||
// Create the window and store a handle to it.
|
||||
m_hwnd = CreateWindow(windowClass.lpszClassName,
|
||||
pSample->GetTitle(),
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
windowRect.right - windowRect.left,
|
||||
windowRect.bottom - windowRect.top,
|
||||
nullptr, // We have no parent window.
|
||||
nullptr, // We aren't using menus.
|
||||
hInstance,
|
||||
pSample);
|
||||
|
||||
// Initialize the sample. OnInit is defined in each child-implementation of
|
||||
// DXSample.
|
||||
pSample->OnInit();
|
||||
// Initialize the sample. OnInit is defined in each child-implementation of
|
||||
// DXSample.
|
||||
pSample->OnInit();
|
||||
|
||||
ShowWindow(m_hwnd, nCmdShow);
|
||||
ShowWindow(m_hwnd, nCmdShow);
|
||||
|
||||
// Main sample loop.
|
||||
MSG msg = {};
|
||||
while (msg.message != WM_QUIT) {
|
||||
// Process any messages in the queue.
|
||||
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
// Main sample loop.
|
||||
MSG msg = {};
|
||||
while (msg.message != WM_QUIT) {
|
||||
// Process any messages in the queue.
|
||||
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pSample->OnDestroy();
|
||||
pSample->OnDestroy();
|
||||
|
||||
// Return this part of the WM_QUIT message to Windows.
|
||||
return static_cast<char>(msg.wParam);
|
||||
// Return this part of the WM_QUIT message to Windows.
|
||||
return static_cast<char>(msg.wParam);
|
||||
}
|
||||
|
||||
// Main message handler for the sample.
|
||||
LRESULT CALLBACK Win32Application::WindowProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam) {
|
||||
DX12CudaSample* pSample =
|
||||
reinterpret_cast<DX12CudaSample*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
||||
LRESULT CALLBACK Win32Application::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
DX12CudaSample *pSample = reinterpret_cast<DX12CudaSample *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
||||
|
||||
switch (message) {
|
||||
switch (message) {
|
||||
case WM_CREATE: {
|
||||
// Save the DXSample* passed in to CreateWindow.
|
||||
LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
|
||||
SetWindowLongPtr(
|
||||
hWnd, GWLP_USERDATA,
|
||||
reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
|
||||
// Save the DXSample* passed in to CreateWindow.
|
||||
LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
|
||||
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
if (pSample) {
|
||||
pSample->OnKeyDown(static_cast<UINT8>(wParam));
|
||||
}
|
||||
return 0;
|
||||
if (pSample) {
|
||||
pSample->OnKeyDown(static_cast<UINT8>(wParam));
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_KEYUP:
|
||||
if (pSample) {
|
||||
pSample->OnKeyUp(static_cast<UINT8>(wParam));
|
||||
}
|
||||
return 0;
|
||||
if (pSample) {
|
||||
pSample->OnKeyUp(static_cast<UINT8>(wParam));
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_PAINT:
|
||||
if (pSample) {
|
||||
pSample->OnRender();
|
||||
}
|
||||
return 0;
|
||||
if (pSample) {
|
||||
pSample->OnRender();
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle any messages the switch statement didn't.
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
// Handle any messages the switch statement didn't.
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
18
Samples/5_Domain_Specific/simpleD3D12/Win32Application.h
Executable file → Normal file
18
Samples/5_Domain_Specific/simpleD3D12/Win32Application.h
Executable file → Normal file
@@ -56,15 +56,15 @@ The MIT License (MIT)
|
||||
|
||||
class DX12CudaSample;
|
||||
|
||||
class Win32Application {
|
||||
public:
|
||||
static int Run(DX12CudaSample* pSample, HINSTANCE hInstance, int nCmdShow);
|
||||
static HWND GetHwnd() { return m_hwnd; }
|
||||
class Win32Application
|
||||
{
|
||||
public:
|
||||
static int Run(DX12CudaSample *pSample, HINSTANCE hInstance, int nCmdShow);
|
||||
static HWND GetHwnd() { return m_hwnd; }
|
||||
|
||||
protected:
|
||||
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
protected:
|
||||
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
private:
|
||||
static HWND m_hwnd;
|
||||
private:
|
||||
static HWND m_hwnd;
|
||||
};
|
||||
|
||||
1865
Samples/5_Domain_Specific/simpleD3D12/d3dx12.h
Executable file → Normal file
1865
Samples/5_Domain_Specific/simpleD3D12/d3dx12.h
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
869
Samples/5_Domain_Specific/simpleD3D12/simpleD3D12.cpp
Executable file → Normal file
869
Samples/5_Domain_Specific/simpleD3D12/simpleD3D12.cpp
Executable file → Normal file
@@ -25,543 +25,514 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "d3dx12.h"
|
||||
|
||||
#include <string>
|
||||
#include <wrl.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include "ShaderStructs.h"
|
||||
#include "simpleD3D12.h"
|
||||
|
||||
#include <aclapi.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <shellapi.h>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include "ShaderStructs.h"
|
||||
#include "d3dx12.h"
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// WindowsSecurityAttributes implementation //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
class WindowsSecurityAttributes {
|
||||
protected:
|
||||
SECURITY_ATTRIBUTES m_winSecurityAttributes;
|
||||
PSECURITY_DESCRIPTOR m_winPSecurityDescriptor;
|
||||
class WindowsSecurityAttributes
|
||||
{
|
||||
protected:
|
||||
SECURITY_ATTRIBUTES m_winSecurityAttributes;
|
||||
PSECURITY_DESCRIPTOR m_winPSecurityDescriptor;
|
||||
|
||||
public:
|
||||
WindowsSecurityAttributes();
|
||||
~WindowsSecurityAttributes();
|
||||
SECURITY_ATTRIBUTES *operator&();
|
||||
public:
|
||||
WindowsSecurityAttributes();
|
||||
~WindowsSecurityAttributes();
|
||||
SECURITY_ATTRIBUTES *operator&();
|
||||
};
|
||||
|
||||
WindowsSecurityAttributes::WindowsSecurityAttributes() {
|
||||
m_winPSecurityDescriptor = (PSECURITY_DESCRIPTOR)calloc(
|
||||
1, SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof(void **));
|
||||
assert(m_winPSecurityDescriptor != (PSECURITY_DESCRIPTOR)NULL);
|
||||
WindowsSecurityAttributes::WindowsSecurityAttributes()
|
||||
{
|
||||
m_winPSecurityDescriptor = (PSECURITY_DESCRIPTOR)calloc(1, SECURITY_DESCRIPTOR_MIN_LENGTH + 2 * sizeof(void **));
|
||||
assert(m_winPSecurityDescriptor != (PSECURITY_DESCRIPTOR)NULL);
|
||||
|
||||
PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor +
|
||||
SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
|
||||
PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
|
||||
|
||||
InitializeSecurityDescriptor(m_winPSecurityDescriptor,
|
||||
SECURITY_DESCRIPTOR_REVISION);
|
||||
InitializeSecurityDescriptor(m_winPSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
|
||||
|
||||
SID_IDENTIFIER_AUTHORITY sidIdentifierAuthority =
|
||||
SECURITY_WORLD_SID_AUTHORITY;
|
||||
AllocateAndInitializeSid(&sidIdentifierAuthority, 1, SECURITY_WORLD_RID, 0, 0,
|
||||
0, 0, 0, 0, 0, ppSID);
|
||||
SID_IDENTIFIER_AUTHORITY sidIdentifierAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
||||
AllocateAndInitializeSid(&sidIdentifierAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, ppSID);
|
||||
|
||||
EXPLICIT_ACCESS explicitAccess;
|
||||
ZeroMemory(&explicitAccess, sizeof(EXPLICIT_ACCESS));
|
||||
explicitAccess.grfAccessPermissions =
|
||||
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
|
||||
explicitAccess.grfAccessMode = SET_ACCESS;
|
||||
explicitAccess.grfInheritance = INHERIT_ONLY;
|
||||
explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
|
||||
explicitAccess.Trustee.ptstrName = (LPTSTR)*ppSID;
|
||||
EXPLICIT_ACCESS explicitAccess;
|
||||
ZeroMemory(&explicitAccess, sizeof(EXPLICIT_ACCESS));
|
||||
explicitAccess.grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
|
||||
explicitAccess.grfAccessMode = SET_ACCESS;
|
||||
explicitAccess.grfInheritance = INHERIT_ONLY;
|
||||
explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
|
||||
explicitAccess.Trustee.ptstrName = (LPTSTR)*ppSID;
|
||||
|
||||
SetEntriesInAcl(1, &explicitAccess, NULL, ppACL);
|
||||
SetEntriesInAcl(1, &explicitAccess, NULL, ppACL);
|
||||
|
||||
SetSecurityDescriptorDacl(m_winPSecurityDescriptor, TRUE, *ppACL, FALSE);
|
||||
SetSecurityDescriptorDacl(m_winPSecurityDescriptor, TRUE, *ppACL, FALSE);
|
||||
|
||||
m_winSecurityAttributes.nLength = sizeof(m_winSecurityAttributes);
|
||||
m_winSecurityAttributes.lpSecurityDescriptor = m_winPSecurityDescriptor;
|
||||
m_winSecurityAttributes.bInheritHandle = TRUE;
|
||||
m_winSecurityAttributes.nLength = sizeof(m_winSecurityAttributes);
|
||||
m_winSecurityAttributes.lpSecurityDescriptor = m_winPSecurityDescriptor;
|
||||
m_winSecurityAttributes.bInheritHandle = TRUE;
|
||||
}
|
||||
|
||||
WindowsSecurityAttributes::~WindowsSecurityAttributes() {
|
||||
PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor +
|
||||
SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
|
||||
WindowsSecurityAttributes::~WindowsSecurityAttributes()
|
||||
{
|
||||
PSID *ppSID = (PSID *)((PBYTE)m_winPSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
PACL *ppACL = (PACL *)((PBYTE)ppSID + sizeof(PSID *));
|
||||
|
||||
if (*ppSID) {
|
||||
FreeSid(*ppSID);
|
||||
}
|
||||
if (*ppACL) {
|
||||
LocalFree(*ppACL);
|
||||
}
|
||||
free(m_winPSecurityDescriptor);
|
||||
if (*ppSID) {
|
||||
FreeSid(*ppSID);
|
||||
}
|
||||
if (*ppACL) {
|
||||
LocalFree(*ppACL);
|
||||
}
|
||||
free(m_winPSecurityDescriptor);
|
||||
}
|
||||
|
||||
SECURITY_ATTRIBUTES *WindowsSecurityAttributes::operator&() {
|
||||
return &m_winSecurityAttributes;
|
||||
}
|
||||
SECURITY_ATTRIBUTES *WindowsSecurityAttributes::operator&() { return &m_winSecurityAttributes; }
|
||||
|
||||
DX12CudaInterop::DX12CudaInterop(UINT width, UINT height, std::string name)
|
||||
: DX12CudaSample(width, height, name),
|
||||
m_frameIndex(0),
|
||||
m_scissorRect(0, 0, static_cast<LONG>(width), static_cast<LONG>(height)),
|
||||
m_fenceValues{},
|
||||
m_rtvDescriptorSize(0) {
|
||||
m_viewport = {0.0f, 0.0f, static_cast<float>(width),
|
||||
static_cast<float>(height)};
|
||||
m_AnimTime = 1.0f;
|
||||
: DX12CudaSample(width, height, name)
|
||||
, m_frameIndex(0)
|
||||
, m_scissorRect(0, 0, static_cast<LONG>(width), static_cast<LONG>(height))
|
||||
, m_fenceValues{}
|
||||
, m_rtvDescriptorSize(0)
|
||||
{
|
||||
m_viewport = {0.0f, 0.0f, static_cast<float>(width), static_cast<float>(height)};
|
||||
m_AnimTime = 1.0f;
|
||||
}
|
||||
|
||||
void DX12CudaInterop::OnInit() {
|
||||
LoadPipeline();
|
||||
InitCuda();
|
||||
LoadAssets();
|
||||
void DX12CudaInterop::OnInit()
|
||||
{
|
||||
LoadPipeline();
|
||||
InitCuda();
|
||||
LoadAssets();
|
||||
}
|
||||
|
||||
// Load the rendering pipeline dependencies.
|
||||
void DX12CudaInterop::LoadPipeline() {
|
||||
UINT dxgiFactoryFlags = 0;
|
||||
void DX12CudaInterop::LoadPipeline()
|
||||
{
|
||||
UINT dxgiFactoryFlags = 0;
|
||||
|
||||
#if defined(_DEBUG)
|
||||
// Enable the debug layer (requires the Graphics Tools "optional feature").
|
||||
// NOTE: Enabling the debug layer after device creation will invalidate the
|
||||
// active device.
|
||||
{
|
||||
ComPtr<ID3D12Debug> debugController;
|
||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
||||
debugController->EnableDebugLayer();
|
||||
// Enable the debug layer (requires the Graphics Tools "optional feature").
|
||||
// NOTE: Enabling the debug layer after device creation will invalidate the
|
||||
// active device.
|
||||
{
|
||||
ComPtr<ID3D12Debug> debugController;
|
||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
||||
debugController->EnableDebugLayer();
|
||||
|
||||
// Enable additional debug layers.
|
||||
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
|
||||
// Enable additional debug layers.
|
||||
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ComPtr<IDXGIFactory4> factory;
|
||||
ThrowIfFailed(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)));
|
||||
ComPtr<IDXGIFactory4> factory;
|
||||
ThrowIfFailed(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)));
|
||||
|
||||
if (m_useWarpDevice) {
|
||||
ComPtr<IDXGIAdapter> warpAdapter;
|
||||
ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)));
|
||||
if (m_useWarpDevice) {
|
||||
ComPtr<IDXGIAdapter> warpAdapter;
|
||||
ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)));
|
||||
|
||||
ThrowIfFailed(D3D12CreateDevice(warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0,
|
||||
IID_PPV_ARGS(&m_device)));
|
||||
} else {
|
||||
ComPtr<IDXGIAdapter1> hardwareAdapter;
|
||||
GetHardwareAdapter(factory.Get(), &hardwareAdapter);
|
||||
|
||||
ThrowIfFailed(D3D12CreateDevice(hardwareAdapter.Get(),
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
IID_PPV_ARGS(&m_device)));
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
hardwareAdapter->GetDesc1(&desc);
|
||||
m_dx12deviceluid = desc.AdapterLuid;
|
||||
}
|
||||
|
||||
// Describe and create the command queue.
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
|
||||
ThrowIfFailed(
|
||||
m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)));
|
||||
|
||||
// Describe and create the swap chain.
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.BufferCount = FrameCount;
|
||||
swapChainDesc.Width = m_width;
|
||||
swapChainDesc.Height = m_height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
|
||||
ComPtr<IDXGISwapChain1> swapChain;
|
||||
ThrowIfFailed(factory->CreateSwapChainForHwnd(
|
||||
m_commandQueue.Get(), // Swap chain needs the queue so that it can force
|
||||
// a flush on it.
|
||||
Win32Application::GetHwnd(), &swapChainDesc, nullptr, nullptr,
|
||||
&swapChain));
|
||||
|
||||
// This sample does not support fullscreen transitions.
|
||||
ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(),
|
||||
DXGI_MWA_NO_ALT_ENTER));
|
||||
|
||||
ThrowIfFailed(swapChain.As(&m_swapChain));
|
||||
m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
|
||||
|
||||
// Create descriptor heaps.
|
||||
{
|
||||
// Describe and create a render target view (RTV) descriptor heap.
|
||||
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
|
||||
rtvHeapDesc.NumDescriptors = FrameCount;
|
||||
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
ThrowIfFailed(
|
||||
m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap)));
|
||||
|
||||
m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
}
|
||||
|
||||
// Create frame resources.
|
||||
{
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(
|
||||
m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
|
||||
// Create a RTV and a command allocator for each frame.
|
||||
for (UINT n = 0; n < FrameCount; n++) {
|
||||
ThrowIfFailed(
|
||||
m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n])));
|
||||
m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr,
|
||||
rtvHandle);
|
||||
rtvHandle.Offset(1, m_rtvDescriptorSize);
|
||||
|
||||
ThrowIfFailed(m_device->CreateCommandAllocator(
|
||||
D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
IID_PPV_ARGS(&m_commandAllocators[n])));
|
||||
ThrowIfFailed(D3D12CreateDevice(warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)));
|
||||
}
|
||||
else {
|
||||
ComPtr<IDXGIAdapter1> hardwareAdapter;
|
||||
GetHardwareAdapter(factory.Get(), &hardwareAdapter);
|
||||
|
||||
ThrowIfFailed(D3D12CreateDevice(hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)));
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
hardwareAdapter->GetDesc1(&desc);
|
||||
m_dx12deviceluid = desc.AdapterLuid;
|
||||
}
|
||||
|
||||
// Describe and create the command queue.
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
|
||||
ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)));
|
||||
|
||||
// Describe and create the swap chain.
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.BufferCount = FrameCount;
|
||||
swapChainDesc.Width = m_width;
|
||||
swapChainDesc.Height = m_height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
|
||||
ComPtr<IDXGISwapChain1> swapChain;
|
||||
ThrowIfFailed(factory->CreateSwapChainForHwnd(m_commandQueue.Get(), // Swap chain needs the queue so that it can
|
||||
// force a flush on it.
|
||||
Win32Application::GetHwnd(),
|
||||
&swapChainDesc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&swapChain));
|
||||
|
||||
// This sample does not support fullscreen transitions.
|
||||
ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), DXGI_MWA_NO_ALT_ENTER));
|
||||
|
||||
ThrowIfFailed(swapChain.As(&m_swapChain));
|
||||
m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
|
||||
|
||||
// Create descriptor heaps.
|
||||
{
|
||||
// Describe and create a render target view (RTV) descriptor heap.
|
||||
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
|
||||
rtvHeapDesc.NumDescriptors = FrameCount;
|
||||
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap)));
|
||||
|
||||
m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
}
|
||||
|
||||
// Create frame resources.
|
||||
{
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
|
||||
// Create a RTV and a command allocator for each frame.
|
||||
for (UINT n = 0; n < FrameCount; n++) {
|
||||
ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n])));
|
||||
m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle);
|
||||
rtvHandle.Offset(1, m_rtvDescriptorSize);
|
||||
|
||||
ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
IID_PPV_ARGS(&m_commandAllocators[n])));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DX12CudaInterop::InitCuda() {
|
||||
int num_cuda_devices = 0;
|
||||
checkCudaErrors(cudaGetDeviceCount(&num_cuda_devices));
|
||||
void DX12CudaInterop::InitCuda()
|
||||
{
|
||||
int num_cuda_devices = 0;
|
||||
checkCudaErrors(cudaGetDeviceCount(&num_cuda_devices));
|
||||
|
||||
if (!num_cuda_devices) {
|
||||
throw std::exception("No CUDA Devices found");
|
||||
}
|
||||
for (UINT devId = 0; devId < num_cuda_devices; devId++) {
|
||||
cudaDeviceProp devProp;
|
||||
checkCudaErrors(cudaGetDeviceProperties(&devProp, devId));
|
||||
|
||||
if ((memcmp(&m_dx12deviceluid.LowPart, devProp.luid,
|
||||
sizeof(m_dx12deviceluid.LowPart)) == 0) &&
|
||||
(memcmp(&m_dx12deviceluid.HighPart,
|
||||
devProp.luid + sizeof(m_dx12deviceluid.LowPart),
|
||||
sizeof(m_dx12deviceluid.HighPart)) == 0)) {
|
||||
checkCudaErrors(cudaSetDevice(devId));
|
||||
m_cudaDeviceID = devId;
|
||||
m_nodeMask = devProp.luidDeviceNodeMask;
|
||||
checkCudaErrors(cudaStreamCreate(&m_streamToRun));
|
||||
printf("CUDA Device Used [%d] %s\n", devId, devProp.name);
|
||||
break;
|
||||
if (!num_cuda_devices) {
|
||||
throw std::exception("No CUDA Devices found");
|
||||
}
|
||||
for (UINT devId = 0; devId < num_cuda_devices; devId++) {
|
||||
cudaDeviceProp devProp;
|
||||
checkCudaErrors(cudaGetDeviceProperties(&devProp, devId));
|
||||
|
||||
if ((memcmp(&m_dx12deviceluid.LowPart, devProp.luid, sizeof(m_dx12deviceluid.LowPart)) == 0)
|
||||
&& (memcmp(&m_dx12deviceluid.HighPart,
|
||||
devProp.luid + sizeof(m_dx12deviceluid.LowPart),
|
||||
sizeof(m_dx12deviceluid.HighPart))
|
||||
== 0)) {
|
||||
checkCudaErrors(cudaSetDevice(devId));
|
||||
m_cudaDeviceID = devId;
|
||||
m_nodeMask = devProp.luidDeviceNodeMask;
|
||||
checkCudaErrors(cudaStreamCreate(&m_streamToRun));
|
||||
printf("CUDA Device Used [%d] %s\n", devId, devProp.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Load the sample assets.
|
||||
void DX12CudaInterop::LoadAssets() {
|
||||
// Create a root signature.
|
||||
{
|
||||
CD3DX12_DESCRIPTOR_RANGE range;
|
||||
CD3DX12_ROOT_PARAMETER parameter;
|
||||
void DX12CudaInterop::LoadAssets()
|
||||
{
|
||||
// Create a root signature.
|
||||
{
|
||||
CD3DX12_DESCRIPTOR_RANGE range;
|
||||
CD3DX12_ROOT_PARAMETER parameter;
|
||||
|
||||
range.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
|
||||
parameter.InitAsDescriptorTable(1, &range, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
range.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
|
||||
parameter.InitAsDescriptorTable(1, &range, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
|
||||
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
|
||||
// Only the input assembler stage needs access to the constant buffer.
|
||||
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
|
||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
|
||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
|
||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
|
||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
|
||||
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
|
||||
// Only the input assembler stage needs access to the constant buffer.
|
||||
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT
|
||||
| D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS
|
||||
| D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS
|
||||
| D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS
|
||||
| D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
|
||||
|
||||
CD3DX12_ROOT_SIGNATURE_DESC descRootSignature;
|
||||
descRootSignature.Init(1, ¶meter, 0, nullptr, rootSignatureFlags);
|
||||
ComPtr<ID3DBlob> pSignature;
|
||||
ComPtr<ID3DBlob> pError;
|
||||
ThrowIfFailed(D3D12SerializeRootSignature(
|
||||
&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1,
|
||||
pSignature.GetAddressOf(), pError.GetAddressOf()));
|
||||
ThrowIfFailed(m_device->CreateRootSignature(
|
||||
0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(),
|
||||
IID_PPV_ARGS(&m_rootSignature)));
|
||||
}
|
||||
// Create the pipeline state, which includes compiling and loading shaders.
|
||||
{
|
||||
ComPtr<ID3DBlob> vertexShader;
|
||||
ComPtr<ID3DBlob> pixelShader;
|
||||
CD3DX12_ROOT_SIGNATURE_DESC descRootSignature;
|
||||
descRootSignature.Init(1, ¶meter, 0, nullptr, rootSignatureFlags);
|
||||
ComPtr<ID3DBlob> pSignature;
|
||||
ComPtr<ID3DBlob> pError;
|
||||
ThrowIfFailed(D3D12SerializeRootSignature(
|
||||
&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf()));
|
||||
ThrowIfFailed(m_device->CreateRootSignature(
|
||||
0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));
|
||||
}
|
||||
// Create the pipeline state, which includes compiling and loading shaders.
|
||||
{
|
||||
ComPtr<ID3DBlob> vertexShader;
|
||||
ComPtr<ID3DBlob> pixelShader;
|
||||
|
||||
#if defined(_DEBUG)
|
||||
// Enable better shader debugging with the graphics debugging tools.
|
||||
UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
// Enable better shader debugging with the graphics debugging tools.
|
||||
UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#else
|
||||
UINT compileFlags = 0;
|
||||
UINT compileFlags = 0;
|
||||
#endif
|
||||
std::wstring filePath = GetAssetFullPath("shaders.hlsl");
|
||||
LPCWSTR result = filePath.c_str();
|
||||
ThrowIfFailed(D3DCompileFromFile(result, nullptr, nullptr, "VSMain",
|
||||
"vs_5_0", compileFlags, 0, &vertexShader,
|
||||
nullptr));
|
||||
ThrowIfFailed(D3DCompileFromFile(result, nullptr, nullptr, "PSMain",
|
||||
"ps_5_0", compileFlags, 0, &pixelShader,
|
||||
nullptr));
|
||||
std::wstring filePath = GetAssetFullPath("shaders.hlsl");
|
||||
LPCWSTR result = filePath.c_str();
|
||||
ThrowIfFailed(
|
||||
D3DCompileFromFile(result, nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr));
|
||||
ThrowIfFailed(
|
||||
D3DCompileFromFile(result, nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, nullptr));
|
||||
|
||||
// Define the vertex input layout.
|
||||
D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = {
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
|
||||
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12,
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}};
|
||||
// Define the vertex input layout.
|
||||
D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = {
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
|
||||
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}};
|
||||
|
||||
// Describe and create the graphics pipeline state object (PSO).
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
||||
psoDesc.InputLayout = {inputElementDescs, _countof(inputElementDescs)};
|
||||
psoDesc.pRootSignature = m_rootSignature.Get();
|
||||
psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader.Get());
|
||||
psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader.Get());
|
||||
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
|
||||
psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
|
||||
psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
|
||||
psoDesc.SampleMask = UINT_MAX;
|
||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
|
||||
psoDesc.NumRenderTargets = 1;
|
||||
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
psoDesc.SampleDesc.Count = 1;
|
||||
ThrowIfFailed(m_device->CreateGraphicsPipelineState(
|
||||
&psoDesc, IID_PPV_ARGS(&m_pipelineState)));
|
||||
}
|
||||
|
||||
// Create the command list.
|
||||
ThrowIfFailed(m_device->CreateCommandList(
|
||||
0, D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get(),
|
||||
IID_PPV_ARGS(&m_commandList)));
|
||||
|
||||
// Command lists are created in the recording state, but there is nothing
|
||||
// to record yet. The main loop expects it to be closed, so close it now.
|
||||
ThrowIfFailed(m_commandList->Close());
|
||||
|
||||
// Create the vertex buffer.
|
||||
{
|
||||
// Define the geometry for a triangle.
|
||||
vertBufWidth = m_width / 2;
|
||||
vertBufHeight = m_height / 2;
|
||||
const UINT vertexBufferSize = sizeof(Vertex) * vertBufWidth * vertBufHeight;
|
||||
|
||||
ThrowIfFailed(m_device->CreateCommittedResource(
|
||||
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
|
||||
D3D12_HEAP_FLAG_SHARED,
|
||||
&CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
|
||||
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, nullptr,
|
||||
IID_PPV_ARGS(&m_vertexBuffer)));
|
||||
|
||||
// Initialize the vertex buffer view.
|
||||
m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
|
||||
m_vertexBufferView.StrideInBytes = sizeof(Vertex);
|
||||
m_vertexBufferView.SizeInBytes = vertexBufferSize;
|
||||
|
||||
HANDLE sharedHandle;
|
||||
WindowsSecurityAttributes windowsSecurityAttributes;
|
||||
LPCWSTR name = NULL;
|
||||
ThrowIfFailed(m_device->CreateSharedHandle(
|
||||
m_vertexBuffer.Get(), &windowsSecurityAttributes, GENERIC_ALL, name,
|
||||
&sharedHandle));
|
||||
|
||||
D3D12_RESOURCE_ALLOCATION_INFO d3d12ResourceAllocationInfo;
|
||||
d3d12ResourceAllocationInfo = m_device->GetResourceAllocationInfo(
|
||||
m_nodeMask, 1, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize));
|
||||
size_t actualSize = d3d12ResourceAllocationInfo.SizeInBytes;
|
||||
size_t alignment = d3d12ResourceAllocationInfo.Alignment;
|
||||
|
||||
cudaExternalMemoryHandleDesc externalMemoryHandleDesc;
|
||||
memset(&externalMemoryHandleDesc, 0, sizeof(externalMemoryHandleDesc));
|
||||
|
||||
externalMemoryHandleDesc.type = cudaExternalMemoryHandleTypeD3D12Resource;
|
||||
externalMemoryHandleDesc.handle.win32.handle = sharedHandle;
|
||||
externalMemoryHandleDesc.size = actualSize;
|
||||
externalMemoryHandleDesc.flags = cudaExternalMemoryDedicated;
|
||||
|
||||
checkCudaErrors(
|
||||
cudaImportExternalMemory(&m_externalMemory, &externalMemoryHandleDesc));
|
||||
CloseHandle(sharedHandle);
|
||||
|
||||
cudaExternalMemoryBufferDesc externalMemoryBufferDesc;
|
||||
memset(&externalMemoryBufferDesc, 0, sizeof(externalMemoryBufferDesc));
|
||||
externalMemoryBufferDesc.offset = 0;
|
||||
externalMemoryBufferDesc.size = vertexBufferSize;
|
||||
externalMemoryBufferDesc.flags = 0;
|
||||
|
||||
checkCudaErrors(cudaExternalMemoryGetMappedBuffer(
|
||||
&m_cudaDevVertptr, m_externalMemory, &externalMemoryBufferDesc));
|
||||
RunSineWaveKernel(vertBufWidth, vertBufHeight, (Vertex *)m_cudaDevVertptr,
|
||||
m_streamToRun, 1.0f);
|
||||
checkCudaErrors(cudaStreamSynchronize(m_streamToRun));
|
||||
|
||||
}
|
||||
|
||||
// Create synchronization objects and wait until assets have been uploaded to
|
||||
// the GPU.
|
||||
{
|
||||
ThrowIfFailed(m_device->CreateFence(m_fenceValues[m_frameIndex],
|
||||
D3D12_FENCE_FLAG_SHARED,
|
||||
IID_PPV_ARGS(&m_fence)));
|
||||
|
||||
cudaExternalSemaphoreHandleDesc externalSemaphoreHandleDesc;
|
||||
|
||||
memset(&externalSemaphoreHandleDesc, 0,
|
||||
sizeof(externalSemaphoreHandleDesc));
|
||||
WindowsSecurityAttributes windowsSecurityAttributes;
|
||||
LPCWSTR name = NULL;
|
||||
HANDLE sharedHandle;
|
||||
externalSemaphoreHandleDesc.type =
|
||||
cudaExternalSemaphoreHandleTypeD3D12Fence;
|
||||
m_device->CreateSharedHandle(m_fence.Get(), &windowsSecurityAttributes,
|
||||
GENERIC_ALL, name, &sharedHandle);
|
||||
externalSemaphoreHandleDesc.handle.win32.handle = (void *)sharedHandle;
|
||||
externalSemaphoreHandleDesc.flags = 0;
|
||||
|
||||
checkCudaErrors(cudaImportExternalSemaphore(&m_externalSemaphore,
|
||||
&externalSemaphoreHandleDesc));
|
||||
|
||||
m_fenceValues[m_frameIndex]++;
|
||||
|
||||
// Create an event handle to use for frame synchronization.
|
||||
m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
if (m_fenceEvent == nullptr) {
|
||||
ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
|
||||
// Describe and create the graphics pipeline state object (PSO).
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
||||
psoDesc.InputLayout = {inputElementDescs, _countof(inputElementDescs)};
|
||||
psoDesc.pRootSignature = m_rootSignature.Get();
|
||||
psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader.Get());
|
||||
psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader.Get());
|
||||
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
|
||||
psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
|
||||
psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
|
||||
psoDesc.SampleMask = UINT_MAX;
|
||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
|
||||
psoDesc.NumRenderTargets = 1;
|
||||
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
psoDesc.SampleDesc.Count = 1;
|
||||
ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)));
|
||||
}
|
||||
|
||||
// Wait for the command list to execute; we are reusing the same command
|
||||
// list in our main loop but for now, we just want to wait for setup to
|
||||
// complete before continuing.
|
||||
WaitForGpu();
|
||||
}
|
||||
// Create the command list.
|
||||
ThrowIfFailed(m_device->CreateCommandList(0,
|
||||
D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
m_commandAllocators[m_frameIndex].Get(),
|
||||
m_pipelineState.Get(),
|
||||
IID_PPV_ARGS(&m_commandList)));
|
||||
|
||||
// Command lists are created in the recording state, but there is nothing
|
||||
// to record yet. The main loop expects it to be closed, so close it now.
|
||||
ThrowIfFailed(m_commandList->Close());
|
||||
|
||||
// Create the vertex buffer.
|
||||
{
|
||||
// Define the geometry for a triangle.
|
||||
vertBufWidth = m_width / 2;
|
||||
vertBufHeight = m_height / 2;
|
||||
const UINT vertexBufferSize = sizeof(Vertex) * vertBufWidth * vertBufHeight;
|
||||
|
||||
ThrowIfFailed(m_device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
|
||||
D3D12_HEAP_FLAG_SHARED,
|
||||
&CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
|
||||
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&m_vertexBuffer)));
|
||||
|
||||
// Initialize the vertex buffer view.
|
||||
m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
|
||||
m_vertexBufferView.StrideInBytes = sizeof(Vertex);
|
||||
m_vertexBufferView.SizeInBytes = vertexBufferSize;
|
||||
|
||||
HANDLE sharedHandle;
|
||||
WindowsSecurityAttributes windowsSecurityAttributes;
|
||||
LPCWSTR name = NULL;
|
||||
ThrowIfFailed(m_device->CreateSharedHandle(
|
||||
m_vertexBuffer.Get(), &windowsSecurityAttributes, GENERIC_ALL, name, &sharedHandle));
|
||||
|
||||
D3D12_RESOURCE_ALLOCATION_INFO d3d12ResourceAllocationInfo;
|
||||
d3d12ResourceAllocationInfo =
|
||||
m_device->GetResourceAllocationInfo(m_nodeMask, 1, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize));
|
||||
size_t actualSize = d3d12ResourceAllocationInfo.SizeInBytes;
|
||||
size_t alignment = d3d12ResourceAllocationInfo.Alignment;
|
||||
|
||||
cudaExternalMemoryHandleDesc externalMemoryHandleDesc;
|
||||
memset(&externalMemoryHandleDesc, 0, sizeof(externalMemoryHandleDesc));
|
||||
|
||||
externalMemoryHandleDesc.type = cudaExternalMemoryHandleTypeD3D12Resource;
|
||||
externalMemoryHandleDesc.handle.win32.handle = sharedHandle;
|
||||
externalMemoryHandleDesc.size = actualSize;
|
||||
externalMemoryHandleDesc.flags = cudaExternalMemoryDedicated;
|
||||
|
||||
checkCudaErrors(cudaImportExternalMemory(&m_externalMemory, &externalMemoryHandleDesc));
|
||||
CloseHandle(sharedHandle);
|
||||
|
||||
cudaExternalMemoryBufferDesc externalMemoryBufferDesc;
|
||||
memset(&externalMemoryBufferDesc, 0, sizeof(externalMemoryBufferDesc));
|
||||
externalMemoryBufferDesc.offset = 0;
|
||||
externalMemoryBufferDesc.size = vertexBufferSize;
|
||||
externalMemoryBufferDesc.flags = 0;
|
||||
|
||||
checkCudaErrors(
|
||||
cudaExternalMemoryGetMappedBuffer(&m_cudaDevVertptr, m_externalMemory, &externalMemoryBufferDesc));
|
||||
RunSineWaveKernel(vertBufWidth, vertBufHeight, (Vertex *)m_cudaDevVertptr, m_streamToRun, 1.0f);
|
||||
checkCudaErrors(cudaStreamSynchronize(m_streamToRun));
|
||||
}
|
||||
|
||||
// Create synchronization objects and wait until assets have been uploaded to
|
||||
// the GPU.
|
||||
{
|
||||
ThrowIfFailed(
|
||||
m_device->CreateFence(m_fenceValues[m_frameIndex], D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&m_fence)));
|
||||
|
||||
cudaExternalSemaphoreHandleDesc externalSemaphoreHandleDesc;
|
||||
|
||||
memset(&externalSemaphoreHandleDesc, 0, sizeof(externalSemaphoreHandleDesc));
|
||||
WindowsSecurityAttributes windowsSecurityAttributes;
|
||||
LPCWSTR name = NULL;
|
||||
HANDLE sharedHandle;
|
||||
externalSemaphoreHandleDesc.type = cudaExternalSemaphoreHandleTypeD3D12Fence;
|
||||
m_device->CreateSharedHandle(m_fence.Get(), &windowsSecurityAttributes, GENERIC_ALL, name, &sharedHandle);
|
||||
externalSemaphoreHandleDesc.handle.win32.handle = (void *)sharedHandle;
|
||||
externalSemaphoreHandleDesc.flags = 0;
|
||||
|
||||
checkCudaErrors(cudaImportExternalSemaphore(&m_externalSemaphore, &externalSemaphoreHandleDesc));
|
||||
|
||||
m_fenceValues[m_frameIndex]++;
|
||||
|
||||
// Create an event handle to use for frame synchronization.
|
||||
m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
if (m_fenceEvent == nullptr) {
|
||||
ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
|
||||
// Wait for the command list to execute; we are reusing the same command
|
||||
// list in our main loop but for now, we just want to wait for setup to
|
||||
// complete before continuing.
|
||||
WaitForGpu();
|
||||
}
|
||||
}
|
||||
|
||||
// Render the scene.
|
||||
void DX12CudaInterop::OnRender() {
|
||||
// Record all the commands we need to render the scene into the command list.
|
||||
PopulateCommandList();
|
||||
void DX12CudaInterop::OnRender()
|
||||
{
|
||||
// Record all the commands we need to render the scene into the command list.
|
||||
PopulateCommandList();
|
||||
|
||||
// Execute the command list.
|
||||
ID3D12CommandList *ppCommandLists[] = {m_commandList.Get()};
|
||||
m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
|
||||
// Execute the command list.
|
||||
ID3D12CommandList *ppCommandLists[] = {m_commandList.Get()};
|
||||
m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
|
||||
|
||||
// Present the frame.
|
||||
ThrowIfFailed(m_swapChain->Present(1, 0));
|
||||
// Present the frame.
|
||||
ThrowIfFailed(m_swapChain->Present(1, 0));
|
||||
|
||||
// Schedule a Signal command in the queue.
|
||||
const UINT64 currentFenceValue = m_fenceValues[m_frameIndex];
|
||||
ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue));
|
||||
// Schedule a Signal command in the queue.
|
||||
const UINT64 currentFenceValue = m_fenceValues[m_frameIndex];
|
||||
ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue));
|
||||
|
||||
MoveToNextFrame();
|
||||
MoveToNextFrame();
|
||||
}
|
||||
|
||||
void DX12CudaInterop::OnDestroy() {
|
||||
// Ensure that the GPU is no longer referencing resources that are about to be
|
||||
// cleaned up by the destructor.
|
||||
WaitForGpu();
|
||||
checkCudaErrors(cudaDestroyExternalSemaphore(m_externalSemaphore));
|
||||
checkCudaErrors(cudaDestroyExternalMemory(m_externalMemory));
|
||||
checkCudaErrors(cudaFree(m_cudaDevVertptr));
|
||||
CloseHandle(m_fenceEvent);
|
||||
void DX12CudaInterop::OnDestroy()
|
||||
{
|
||||
// Ensure that the GPU is no longer referencing resources that are about to be
|
||||
// cleaned up by the destructor.
|
||||
WaitForGpu();
|
||||
checkCudaErrors(cudaDestroyExternalSemaphore(m_externalSemaphore));
|
||||
checkCudaErrors(cudaDestroyExternalMemory(m_externalMemory));
|
||||
checkCudaErrors(cudaFree(m_cudaDevVertptr));
|
||||
CloseHandle(m_fenceEvent);
|
||||
}
|
||||
|
||||
void DX12CudaInterop::PopulateCommandList() {
|
||||
// Command list allocators can only be reset when the associated
|
||||
// command lists have finished execution on the GPU; apps should use
|
||||
// fences to determine GPU execution progress.
|
||||
ThrowIfFailed(m_commandAllocators[m_frameIndex]->Reset());
|
||||
void DX12CudaInterop::PopulateCommandList()
|
||||
{
|
||||
// Command list allocators can only be reset when the associated
|
||||
// command lists have finished execution on the GPU; apps should use
|
||||
// fences to determine GPU execution progress.
|
||||
ThrowIfFailed(m_commandAllocators[m_frameIndex]->Reset());
|
||||
|
||||
// However, when ExecuteCommandList() is called on a particular command
|
||||
// list, that command list can then be reset at any time and must be before
|
||||
// re-recording.
|
||||
ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_frameIndex].Get(),
|
||||
m_pipelineState.Get()));
|
||||
// However, when ExecuteCommandList() is called on a particular command
|
||||
// list, that command list can then be reset at any time and must be before
|
||||
// re-recording.
|
||||
ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get()));
|
||||
|
||||
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
|
||||
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
|
||||
|
||||
// Set necessary state.
|
||||
m_commandList->RSSetViewports(1, &m_viewport);
|
||||
m_commandList->RSSetScissorRects(1, &m_scissorRect);
|
||||
// Set necessary state.
|
||||
m_commandList->RSSetViewports(1, &m_viewport);
|
||||
m_commandList->RSSetScissorRects(1, &m_scissorRect);
|
||||
|
||||
// Indicate that the back buffer will be used as a render target.
|
||||
m_commandList->ResourceBarrier(
|
||||
1, &CD3DX12_RESOURCE_BARRIER::Transition(
|
||||
m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET));
|
||||
// Indicate that the back buffer will be used as a render target.
|
||||
m_commandList->ResourceBarrier(1,
|
||||
&CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(),
|
||||
D3D12_RESOURCE_STATE_PRESENT,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET));
|
||||
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(
|
||||
m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex,
|
||||
m_rtvDescriptorSize);
|
||||
m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(
|
||||
m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
|
||||
m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
|
||||
|
||||
// Record commands.
|
||||
const float clearColor[] = {0.0f, 0.2f, 0.4f, 1.0f};
|
||||
m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
|
||||
m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
|
||||
m_commandList->DrawInstanced(vertBufHeight * vertBufWidth, 1, 0, 0);
|
||||
// Record commands.
|
||||
const float clearColor[] = {0.0f, 0.2f, 0.4f, 1.0f};
|
||||
m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
|
||||
m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
|
||||
m_commandList->DrawInstanced(vertBufHeight * vertBufWidth, 1, 0, 0);
|
||||
|
||||
// Indicate that the back buffer will now be used to present.
|
||||
m_commandList->ResourceBarrier(
|
||||
1, &CD3DX12_RESOURCE_BARRIER::Transition(
|
||||
m_renderTargets[m_frameIndex].Get(),
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
|
||||
// Indicate that the back buffer will now be used to present.
|
||||
m_commandList->ResourceBarrier(1,
|
||||
&CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(),
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
D3D12_RESOURCE_STATE_PRESENT));
|
||||
|
||||
ThrowIfFailed(m_commandList->Close());
|
||||
ThrowIfFailed(m_commandList->Close());
|
||||
}
|
||||
|
||||
// Wait for pending GPU work to complete.
|
||||
void DX12CudaInterop::WaitForGpu() {
|
||||
// Schedule a Signal command in the queue.
|
||||
ThrowIfFailed(
|
||||
m_commandQueue->Signal(m_fence.Get(), m_fenceValues[m_frameIndex]));
|
||||
void DX12CudaInterop::WaitForGpu()
|
||||
{
|
||||
// Schedule a Signal command in the queue.
|
||||
ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), m_fenceValues[m_frameIndex]));
|
||||
|
||||
// Wait until the fence has been processed.
|
||||
ThrowIfFailed(
|
||||
m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent));
|
||||
WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
|
||||
// Wait until the fence has been processed.
|
||||
ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent));
|
||||
WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
|
||||
|
||||
// Increment the fence value for the current frame.
|
||||
m_fenceValues[m_frameIndex]++;
|
||||
// Increment the fence value for the current frame.
|
||||
m_fenceValues[m_frameIndex]++;
|
||||
}
|
||||
|
||||
// Prepare to render the next frame.
|
||||
void DX12CudaInterop::MoveToNextFrame() {
|
||||
const UINT64 currentFenceValue = m_fenceValues[m_frameIndex];
|
||||
cudaExternalSemaphoreWaitParams externalSemaphoreWaitParams;
|
||||
memset(&externalSemaphoreWaitParams, 0, sizeof(externalSemaphoreWaitParams));
|
||||
void DX12CudaInterop::MoveToNextFrame()
|
||||
{
|
||||
const UINT64 currentFenceValue = m_fenceValues[m_frameIndex];
|
||||
cudaExternalSemaphoreWaitParams externalSemaphoreWaitParams;
|
||||
memset(&externalSemaphoreWaitParams, 0, sizeof(externalSemaphoreWaitParams));
|
||||
|
||||
externalSemaphoreWaitParams.params.fence.value = currentFenceValue;
|
||||
externalSemaphoreWaitParams.flags = 0;
|
||||
externalSemaphoreWaitParams.params.fence.value = currentFenceValue;
|
||||
externalSemaphoreWaitParams.flags = 0;
|
||||
|
||||
checkCudaErrors(cudaWaitExternalSemaphoresAsync(
|
||||
&m_externalSemaphore, &externalSemaphoreWaitParams, 1, m_streamToRun));
|
||||
checkCudaErrors(
|
||||
cudaWaitExternalSemaphoresAsync(&m_externalSemaphore, &externalSemaphoreWaitParams, 1, m_streamToRun));
|
||||
|
||||
m_AnimTime += 0.01f;
|
||||
RunSineWaveKernel(vertBufWidth, vertBufHeight, (Vertex *)m_cudaDevVertptr,
|
||||
m_streamToRun, m_AnimTime);
|
||||
m_AnimTime += 0.01f;
|
||||
RunSineWaveKernel(vertBufWidth, vertBufHeight, (Vertex *)m_cudaDevVertptr, m_streamToRun, m_AnimTime);
|
||||
|
||||
cudaExternalSemaphoreSignalParams externalSemaphoreSignalParams;
|
||||
memset(&externalSemaphoreSignalParams, 0,
|
||||
sizeof(externalSemaphoreSignalParams));
|
||||
m_fenceValues[m_frameIndex] = currentFenceValue + 1;
|
||||
externalSemaphoreSignalParams.params.fence.value =
|
||||
m_fenceValues[m_frameIndex];
|
||||
externalSemaphoreSignalParams.flags = 0;
|
||||
cudaExternalSemaphoreSignalParams externalSemaphoreSignalParams;
|
||||
memset(&externalSemaphoreSignalParams, 0, sizeof(externalSemaphoreSignalParams));
|
||||
m_fenceValues[m_frameIndex] = currentFenceValue + 1;
|
||||
externalSemaphoreSignalParams.params.fence.value = m_fenceValues[m_frameIndex];
|
||||
externalSemaphoreSignalParams.flags = 0;
|
||||
|
||||
checkCudaErrors(cudaSignalExternalSemaphoresAsync(
|
||||
&m_externalSemaphore, &externalSemaphoreSignalParams, 1, m_streamToRun));
|
||||
checkCudaErrors(
|
||||
cudaSignalExternalSemaphoresAsync(&m_externalSemaphore, &externalSemaphoreSignalParams, 1, m_streamToRun));
|
||||
|
||||
// Update the frame index.
|
||||
m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
|
||||
// Update the frame index.
|
||||
m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
|
||||
|
||||
// If the next frame is not ready to be rendered yet, wait until it is ready.
|
||||
if (m_fence->GetCompletedValue() < m_fenceValues[m_frameIndex]) {
|
||||
ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex],
|
||||
m_fenceEvent));
|
||||
WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
|
||||
}
|
||||
// If the next frame is not ready to be rendered yet, wait until it is ready.
|
||||
if (m_fence->GetCompletedValue() < m_fenceValues[m_frameIndex]) {
|
||||
ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent));
|
||||
WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
|
||||
}
|
||||
|
||||
// Set the fence value for the next frame.
|
||||
m_fenceValues[m_frameIndex] = currentFenceValue + 2;
|
||||
// Set the fence value for the next frame.
|
||||
m_fenceValues[m_frameIndex] = currentFenceValue + 2;
|
||||
}
|
||||
|
||||
146
Samples/5_Domain_Specific/simpleD3D12/simpleD3D12.h
Executable file → Normal file
146
Samples/5_Domain_Specific/simpleD3D12/simpleD3D12.h
Executable file → Normal file
@@ -39,43 +39,43 @@ using namespace DirectX;
|
||||
// the class method: OnDestroy().
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
static const char *shaderstr =
|
||||
" struct PSInput \n"
|
||||
" { \n"
|
||||
" float4 position : SV_POSITION; \n"
|
||||
" float4 color : COLOR; \n"
|
||||
" } \n"
|
||||
" PSInput VSMain(float3 position : POSITION, float4 color : COLOR) \n"
|
||||
" { \n"
|
||||
" PSInput result;\n"
|
||||
" result.position = float4(position, 1.0f);\n"
|
||||
" result.color = color;\n"
|
||||
" return result; \n"
|
||||
" } \n"
|
||||
" float4 PSMain(PSInput input) : SV_TARGET \n"
|
||||
" { \n"
|
||||
" return input.color;\n"
|
||||
" } \n";
|
||||
static const char *shaderstr = " struct PSInput \n"
|
||||
" { \n"
|
||||
" float4 position : SV_POSITION; \n"
|
||||
" float4 color : COLOR; \n"
|
||||
" } \n"
|
||||
" PSInput VSMain(float3 position : POSITION, float4 color : COLOR) \n"
|
||||
" { \n"
|
||||
" PSInput result;\n"
|
||||
" result.position = float4(position, 1.0f);\n"
|
||||
" result.color = color;\n"
|
||||
" return result; \n"
|
||||
" } \n"
|
||||
" float4 PSMain(PSInput input) : SV_TARGET \n"
|
||||
" { \n"
|
||||
" return input.color;\n"
|
||||
" } \n";
|
||||
|
||||
class DX12CudaInterop : public DX12CudaSample {
|
||||
public:
|
||||
DX12CudaInterop(UINT width, UINT height, std::string name);
|
||||
class DX12CudaInterop : public DX12CudaSample
|
||||
{
|
||||
public:
|
||||
DX12CudaInterop(UINT width, UINT height, std::string name);
|
||||
|
||||
virtual void OnInit();
|
||||
virtual void OnRender();
|
||||
virtual void OnDestroy();
|
||||
virtual void OnInit();
|
||||
virtual void OnRender();
|
||||
virtual void OnDestroy();
|
||||
|
||||
private:
|
||||
// In this sample we overload the meaning of FrameCount to mean both the
|
||||
// maximum number of frames that will be queued to the GPU at a time, as well
|
||||
// as the number of back buffers in the DXGI swap chain. For the majority of
|
||||
// applications, this is convenient and works well. However, there will be
|
||||
// certain cases where an application may want to queue up more frames than
|
||||
// there are back buffers available. It should be noted that excessive
|
||||
// buffering of frames dependent on user input may result in noticeable
|
||||
// latency in your app.
|
||||
static const UINT FrameCount = 2;
|
||||
std::string shadersSrc = shaderstr;
|
||||
private:
|
||||
// In this sample we overload the meaning of FrameCount to mean both the
|
||||
// maximum number of frames that will be queued to the GPU at a time, as well
|
||||
// as the number of back buffers in the DXGI swap chain. For the majority of
|
||||
// applications, this is convenient and works well. However, there will be
|
||||
// certain cases where an application may want to queue up more frames than
|
||||
// there are back buffers available. It should be noted that excessive
|
||||
// buffering of frames dependent on user input may result in noticeable
|
||||
// latency in your app.
|
||||
static const UINT FrameCount = 2;
|
||||
std::string shadersSrc = shaderstr;
|
||||
#if 0
|
||||
" struct PSInput \n" \
|
||||
" { \n" \
|
||||
@@ -95,48 +95,48 @@ class DX12CudaInterop : public DX12CudaSample {
|
||||
" } \n";
|
||||
#endif
|
||||
|
||||
// Vertex Buffer dimension
|
||||
size_t vertBufHeight, vertBufWidth;
|
||||
// Vertex Buffer dimension
|
||||
size_t vertBufHeight, vertBufWidth;
|
||||
|
||||
// Pipeline objects.
|
||||
D3D12_VIEWPORT m_viewport;
|
||||
CD3DX12_RECT m_scissorRect;
|
||||
ComPtr<IDXGISwapChain3> m_swapChain;
|
||||
ComPtr<ID3D12Device> m_device;
|
||||
ComPtr<ID3D12Resource> m_renderTargets[FrameCount];
|
||||
ComPtr<ID3D12CommandAllocator> m_commandAllocators[FrameCount];
|
||||
ComPtr<ID3D12CommandQueue> m_commandQueue;
|
||||
ComPtr<ID3D12RootSignature> m_rootSignature;
|
||||
ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
|
||||
ComPtr<ID3D12PipelineState> m_pipelineState;
|
||||
ComPtr<ID3D12GraphicsCommandList> m_commandList;
|
||||
UINT m_rtvDescriptorSize;
|
||||
// Pipeline objects.
|
||||
D3D12_VIEWPORT m_viewport;
|
||||
CD3DX12_RECT m_scissorRect;
|
||||
ComPtr<IDXGISwapChain3> m_swapChain;
|
||||
ComPtr<ID3D12Device> m_device;
|
||||
ComPtr<ID3D12Resource> m_renderTargets[FrameCount];
|
||||
ComPtr<ID3D12CommandAllocator> m_commandAllocators[FrameCount];
|
||||
ComPtr<ID3D12CommandQueue> m_commandQueue;
|
||||
ComPtr<ID3D12RootSignature> m_rootSignature;
|
||||
ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
|
||||
ComPtr<ID3D12PipelineState> m_pipelineState;
|
||||
ComPtr<ID3D12GraphicsCommandList> m_commandList;
|
||||
UINT m_rtvDescriptorSize;
|
||||
|
||||
// App resources.
|
||||
ComPtr<ID3D12Resource> m_vertexBuffer;
|
||||
D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView;
|
||||
// App resources.
|
||||
ComPtr<ID3D12Resource> m_vertexBuffer;
|
||||
D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView;
|
||||
|
||||
// Synchronization objects.
|
||||
UINT m_frameIndex;
|
||||
HANDLE m_fenceEvent;
|
||||
ComPtr<ID3D12Fence> m_fence;
|
||||
UINT64 m_fenceValues[FrameCount];
|
||||
// Synchronization objects.
|
||||
UINT m_frameIndex;
|
||||
HANDLE m_fenceEvent;
|
||||
ComPtr<ID3D12Fence> m_fence;
|
||||
UINT64 m_fenceValues[FrameCount];
|
||||
|
||||
// CUDA objects
|
||||
cudaExternalMemoryHandleType m_externalMemoryHandleType;
|
||||
cudaExternalMemory_t m_externalMemory;
|
||||
cudaExternalSemaphore_t m_externalSemaphore;
|
||||
cudaStream_t m_streamToRun;
|
||||
LUID m_dx12deviceluid;
|
||||
UINT m_cudaDeviceID;
|
||||
UINT m_nodeMask;
|
||||
float m_AnimTime;
|
||||
void *m_cudaDevVertptr = NULL;
|
||||
// CUDA objects
|
||||
cudaExternalMemoryHandleType m_externalMemoryHandleType;
|
||||
cudaExternalMemory_t m_externalMemory;
|
||||
cudaExternalSemaphore_t m_externalSemaphore;
|
||||
cudaStream_t m_streamToRun;
|
||||
LUID m_dx12deviceluid;
|
||||
UINT m_cudaDeviceID;
|
||||
UINT m_nodeMask;
|
||||
float m_AnimTime;
|
||||
void *m_cudaDevVertptr = NULL;
|
||||
|
||||
void LoadPipeline();
|
||||
void InitCuda();
|
||||
void LoadAssets();
|
||||
void PopulateCommandList();
|
||||
void MoveToNextFrame();
|
||||
void WaitForGpu();
|
||||
void LoadPipeline();
|
||||
void InitCuda();
|
||||
void LoadAssets();
|
||||
void PopulateCommandList();
|
||||
void MoveToNextFrame();
|
||||
void WaitForGpu();
|
||||
};
|
||||
|
||||
66
Samples/5_Domain_Specific/simpleD3D12/sinewave_cuda.cu
Executable file → Normal file
66
Samples/5_Domain_Specific/simpleD3D12/sinewave_cuda.cu
Executable file → Normal file
@@ -27,43 +27,45 @@
|
||||
|
||||
#include "ShaderStructs.h"
|
||||
|
||||
__global__ void sinewave_gen_kernel(Vertex *vertices, unsigned int width,
|
||||
unsigned int height, float time) {
|
||||
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
__global__ void sinewave_gen_kernel(Vertex *vertices, unsigned int width, unsigned int height, float time)
|
||||
{
|
||||
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
|
||||
// calculate uv coordinates
|
||||
float u = x / (float)width;
|
||||
float v = y / (float)height;
|
||||
u = u * 2.0f - 1.0f;
|
||||
v = v * 2.0f - 1.0f;
|
||||
// calculate uv coordinates
|
||||
float u = x / (float)width;
|
||||
float v = y / (float)height;
|
||||
u = u * 2.0f - 1.0f;
|
||||
v = v * 2.0f - 1.0f;
|
||||
|
||||
// calculate simple sine wave pattern
|
||||
float freq = 4.0f;
|
||||
float w = sinf(u * freq + time) * cosf(v * freq + time) * 0.5f;
|
||||
// calculate simple sine wave pattern
|
||||
float freq = 4.0f;
|
||||
float w = sinf(u * freq + time) * cosf(v * freq + time) * 0.5f;
|
||||
|
||||
if (y < height && x < width) {
|
||||
// write output vertex
|
||||
vertices[y * width + x].position.x = u;
|
||||
vertices[y * width + x].position.y = w;
|
||||
vertices[y * width + x].position.z = v;
|
||||
// vertices[y*width+x].position[3] = 1.0f;
|
||||
vertices[y * width + x].color.x = 1.0f;
|
||||
vertices[y * width + x].color.y = 0.0f;
|
||||
vertices[y * width + x].color.z = 0.0f;
|
||||
vertices[y * width + x].color.w = 0.0f;
|
||||
}
|
||||
if (y < height && x < width) {
|
||||
// write output vertex
|
||||
vertices[y * width + x].position.x = u;
|
||||
vertices[y * width + x].position.y = w;
|
||||
vertices[y * width + x].position.z = v;
|
||||
// vertices[y*width+x].position[3] = 1.0f;
|
||||
vertices[y * width + x].color.x = 1.0f;
|
||||
vertices[y * width + x].color.y = 0.0f;
|
||||
vertices[y * width + x].color.z = 0.0f;
|
||||
vertices[y * width + x].color.w = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// The host CPU Sinewave thread spawner
|
||||
void RunSineWaveKernel(size_t mesh_width, size_t mesh_height,
|
||||
Vertex *cudaDevVertptr, cudaStream_t streamToRun,
|
||||
float AnimTime) {
|
||||
dim3 block(16, 16, 1);
|
||||
dim3 grid(mesh_width / 16, mesh_height / 16, 1);
|
||||
Vertex *vertices = (Vertex *)cudaDevVertptr;
|
||||
sinewave_gen_kernel<<<grid, block, 0, streamToRun>>>(vertices, mesh_width,
|
||||
mesh_height, AnimTime);
|
||||
void RunSineWaveKernel(size_t mesh_width,
|
||||
size_t mesh_height,
|
||||
Vertex *cudaDevVertptr,
|
||||
cudaStream_t streamToRun,
|
||||
float AnimTime)
|
||||
{
|
||||
dim3 block(16, 16, 1);
|
||||
dim3 grid(mesh_width / 16, mesh_height / 16, 1);
|
||||
Vertex *vertices = (Vertex *)cudaDevVertptr;
|
||||
sinewave_gen_kernel<<<grid, block, 0, streamToRun>>>(vertices, mesh_width, mesh_height, AnimTime);
|
||||
|
||||
getLastCudaError("sinewave_gen_kernel execution failed.\n");
|
||||
getLastCudaError("sinewave_gen_kernel execution failed.\n");
|
||||
}
|
||||
|
||||
11
Samples/5_Domain_Specific/simpleD3D12/stdafx.h
Executable file → Normal file
11
Samples/5_Domain_Specific/simpleD3D12/stdafx.h
Executable file → Normal file
@@ -32,17 +32,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers.
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers.
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <D3Dcompiler.h>
|
||||
#include <DirectXMath.h>
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include "d3dx12.h"
|
||||
|
||||
#include <shellapi.h>
|
||||
#include <wrl.h>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include "d3dx12.h"
|
||||
|
||||
Reference in New Issue
Block a user