Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.

This commit is contained in:
Rob Armstrong
2025-03-27 10:30:07 -07:00
parent 2cd58fbc9a
commit ceab6e8bcc
782 changed files with 107230 additions and 106548 deletions

126
Samples/5_Domain_Specific/simpleD3D12/DX12CudaSample.cpp Executable file → Normal file
View 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
View 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
View 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
View 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);
}

View File

@@ -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
View 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);

View 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);
}

View 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

File diff suppressed because it is too large Load Diff

869
Samples/5_Domain_Specific/simpleD3D12/simpleD3D12.cpp Executable file → Normal file
View 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, &parameter, 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, &parameter, 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
View 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
View 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
View 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"