aboutsummaryrefslogtreecommitdiff
path: root/samples/VolumetricLightingTest/d3d11
diff options
context:
space:
mode:
authorNathan Hoobler <[email protected]>2016-03-22 11:40:34 -0400
committerNathan Hoobler <[email protected]>2016-03-22 11:40:34 -0400
commitb4ab266c9010aaff5404f6a508a2e592eb367d36 (patch)
tree1e9eefa78e90485397b50ce5e780a1d0cb38b493 /samples/VolumetricLightingTest/d3d11
downloadvolumetriclighting-b4ab266c9010aaff5404f6a508a2e592eb367d36.tar.xz
volumetriclighting-b4ab266c9010aaff5404f6a508a2e592eb367d36.zip
initial commit
Diffstat (limited to 'samples/VolumetricLightingTest/d3d11')
-rw-r--r--samples/VolumetricLightingTest/d3d11/DeviceManager.cpp609
-rw-r--r--samples/VolumetricLightingTest/d3d11/DeviceManager.h148
-rw-r--r--samples/VolumetricLightingTest/d3d11/compiled_shaders_d3d11.cpp36
-rw-r--r--samples/VolumetricLightingTest/d3d11/compiled_shaders_d3d11.h45
-rw-r--r--samples/VolumetricLightingTest/d3d11/d3d11_main.cpp478
-rw-r--r--samples/VolumetricLightingTest/d3d11/d3d11_util.cpp347
-rw-r--r--samples/VolumetricLightingTest/d3d11/d3d11_util.h234
7 files changed, 1897 insertions, 0 deletions
diff --git a/samples/VolumetricLightingTest/d3d11/DeviceManager.cpp b/samples/VolumetricLightingTest/d3d11/DeviceManager.cpp
new file mode 100644
index 0000000..122da86
--- /dev/null
+++ b/samples/VolumetricLightingTest/d3d11/DeviceManager.cpp
@@ -0,0 +1,609 @@
+// TAGRELEASE: PUBLIC
+#include "common.h"
+
+#include "DeviceManager.h"
+#include <WinUser.h>
+#include <Windows.h>
+
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
+#endif
+
+#define WINDOW_CLASS_NAME L"NvDX11"
+
+#define WINDOW_STYLE_NORMAL (WS_OVERLAPPEDWINDOW | WS_VISIBLE)
+#define WINDOW_STYLE_FULLSCREEN (WS_POPUP | WS_SYSMENU | WS_VISIBLE)
+
+// A singleton, sort of... To pass the events from WindowProc to the object.
+DeviceManager* g_DeviceManagerInstance = NULL;
+
+LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if(g_DeviceManagerInstance)
+ return g_DeviceManagerInstance->MsgProc(hWnd, uMsg, wParam, lParam);
+ else
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+HRESULT
+DeviceManager::CreateWindowDeviceAndSwapChain(const DeviceCreationParameters& params, LPWSTR title)
+{
+ g_DeviceManagerInstance = this;
+ m_WindowTitle = title;
+
+ HINSTANCE hInstance = GetModuleHandle(NULL);
+ WNDCLASSEX windowClass = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WindowProc,
+ 0L, 0L, hInstance, NULL, NULL, NULL, NULL, WINDOW_CLASS_NAME, NULL };
+
+ RegisterClassEx(&windowClass);
+
+ UINT windowStyle = params.startFullscreen
+ ? WINDOW_STYLE_FULLSCREEN
+ : params.startMaximized
+ ? (WINDOW_STYLE_NORMAL | WS_MAXIMIZE)
+ : WINDOW_STYLE_NORMAL;
+
+ RECT rect = { 0, 0, params.backBufferWidth, params.backBufferHeight };
+ AdjustWindowRect(&rect, windowStyle, FALSE);
+
+ m_hWnd = CreateWindowEx(
+ 0,
+ WINDOW_CLASS_NAME,
+ title,
+ windowStyle,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ GetDesktopWindow(),
+ NULL,
+ hInstance,
+ NULL
+ );
+
+ if(!m_hWnd)
+ {
+#ifdef DEBUG
+ DWORD errorCode = GetLastError();
+ printf("CreateWindowEx error code = 0x%x\n", errorCode);
+#endif
+
+ MessageBox(NULL, L"Cannot create window", m_WindowTitle.c_str(), MB_OK | MB_ICONERROR);
+ return E_FAIL;
+ }
+
+ UpdateWindow(m_hWnd);
+
+ HRESULT hr = E_FAIL;
+
+ RECT clientRect;
+ GetClientRect(m_hWnd, &clientRect);
+ UINT width = clientRect.right - clientRect.left;
+ UINT height = clientRect.bottom - clientRect.top;
+
+ ZeroMemory(&m_SwapChainDesc, sizeof(m_SwapChainDesc));
+ m_SwapChainDesc.BufferCount = params.swapChainBufferCount;
+ m_SwapChainDesc.BufferDesc.Width = width;
+ m_SwapChainDesc.BufferDesc.Height = height;
+ m_SwapChainDesc.BufferDesc.Format = params.swapChainFormat;
+ m_SwapChainDesc.BufferDesc.RefreshRate.Numerator = params.refreshRate;
+ m_SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
+ m_SwapChainDesc.BufferUsage = params.swapChainUsage;
+ m_SwapChainDesc.OutputWindow = m_hWnd;
+ m_SwapChainDesc.SampleDesc.Count = params.swapChainSampleCount;
+ m_SwapChainDesc.SampleDesc.Quality = 0;
+ m_SwapChainDesc.Windowed = !params.startFullscreen;
+ m_SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+
+ hr = D3D11CreateDeviceAndSwapChain(
+ NULL, // pAdapter
+ params.driverType, // DriverType
+ NULL, // Software
+ params.createDeviceFlags, // Flags
+ &params.featureLevel, // pFeatureLevels
+ 1, // FeatureLevels
+ D3D11_SDK_VERSION, // SDKVersion
+ &m_SwapChainDesc, // pSwapChainDesc
+ &m_SwapChain, // ppSwapChain
+ &m_Device, // ppDevice
+ NULL, // pFeatureLevel
+ &m_ImmediateContext // ppImmediateContext
+ );
+
+ if(FAILED(hr))
+ return hr;
+
+ m_DepthStencilDesc.ArraySize = 1;
+ m_DepthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+ m_DepthStencilDesc.CPUAccessFlags = 0;
+ m_DepthStencilDesc.Format = params.depthStencilFormat;
+ m_DepthStencilDesc.Width = width;
+ m_DepthStencilDesc.Height = height;
+ m_DepthStencilDesc.MipLevels = 1;
+ m_DepthStencilDesc.MiscFlags = 0;
+ m_DepthStencilDesc.SampleDesc.Count = params.swapChainSampleCount;
+ m_DepthStencilDesc.SampleDesc.Quality = 0;
+ m_DepthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
+
+ hr = CreateRenderTargetAndDepthStencil();
+
+ if(FAILED(hr))
+ return hr;
+
+ DeviceCreated();
+ BackBufferResized();
+
+ return S_OK;
+}
+
+void
+DeviceManager::Shutdown()
+{
+ if(m_SwapChain && GetWindowState() == kWindowFullscreen)
+ m_SwapChain->SetFullscreenState(false, NULL);
+
+ DeviceDestroyed();
+
+ SAFE_RELEASE(m_BackBufferRTV);
+ SAFE_RELEASE(m_DepthStencilDSV);
+ SAFE_RELEASE(m_DepthStencilBuffer);
+
+ g_DeviceManagerInstance = NULL;
+ SAFE_RELEASE(m_SwapChain);
+ SAFE_RELEASE(m_Device);
+
+ if(m_hWnd)
+ {
+ DestroyWindow(m_hWnd);
+ m_hWnd = NULL;
+ }
+}
+
+HRESULT
+DeviceManager::CreateRenderTargetAndDepthStencil()
+{
+ HRESULT hr;
+
+ ID3D11Texture2D *backBuffer = NULL;
+ hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ hr = m_Device->CreateRenderTargetView(backBuffer, NULL, &m_BackBufferRTV);
+ backBuffer->Release();
+ if (FAILED(hr))
+ return hr;
+
+ if(m_DepthStencilDesc.Format != DXGI_FORMAT_UNKNOWN)
+ {
+ hr = m_Device->CreateTexture2D(&m_DepthStencilDesc, NULL, &m_DepthStencilBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ hr = m_Device->CreateDepthStencilView(m_DepthStencilBuffer, NULL, &m_DepthStencilDSV);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ return S_OK;
+}
+
+void
+DeviceManager::MessageLoop()
+{
+ MSG msg = {0};
+
+ LARGE_INTEGER perfFreq, previousTime;
+ QueryPerformanceFrequency(&perfFreq);
+ QueryPerformanceCounter(&previousTime);
+
+ while (WM_QUIT != msg.message)
+ {
+ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ else
+ {
+ LARGE_INTEGER newTime;
+ QueryPerformanceCounter(&newTime);
+
+ double elapsedSeconds = (m_FixedFrameInterval >= 0)
+ ? m_FixedFrameInterval
+ : (double)(newTime.QuadPart - previousTime.QuadPart) / (double)perfFreq.QuadPart;
+
+ if(m_SwapChain && GetWindowState() != kWindowMinimized)
+ {
+ Animate(elapsedSeconds);
+ Render();
+ m_SwapChain->Present(m_SyncInterval, 0);
+ Sleep(0);
+ }
+ else
+ {
+ // Release CPU resources when idle
+ Sleep(1);
+ }
+
+ {
+ m_vFrameTimes.push_back(elapsedSeconds);
+ double timeSum = 0;
+ for(auto it = m_vFrameTimes.begin(); it != m_vFrameTimes.end(); it++)
+ timeSum += *it;
+
+ if(timeSum > m_AverageTimeUpdateInterval)
+ {
+ m_AverageFrameTime = timeSum / (double)m_vFrameTimes.size();
+ m_vFrameTimes.clear();
+ }
+ }
+
+ previousTime = newTime;
+ }
+ }
+}
+
+LRESULT
+DeviceManager::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_DESTROY:
+ case WM_CLOSE:
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_SYSKEYDOWN:
+ if(wParam == VK_F4)
+ {
+ PostQuitMessage(0);
+ return 0;
+ }
+ break;
+
+ case WM_SIZE:
+ // Ignore the WM_SIZE event if there is no device,
+ // or if the window has been minimized (size == 0),
+ // or if it has been restored to the previous size
+ if (m_Device
+ && (lParam != 0)
+ && (LOWORD(lParam) != m_SwapChainDesc.BufferDesc.Width || HIWORD(lParam) != m_SwapChainDesc.BufferDesc.Height))
+ {
+ ID3D11RenderTargetView *nullRTV = NULL;
+ m_ImmediateContext->OMSetRenderTargets(1, &nullRTV, NULL);
+ SAFE_RELEASE(m_BackBufferRTV);
+ SAFE_RELEASE(m_DepthStencilDSV);
+ SAFE_RELEASE(m_DepthStencilBuffer);
+
+ if (m_SwapChain)
+ {
+ // Resize the swap chain
+ m_SwapChainDesc.BufferDesc.Width = LOWORD(lParam);
+ m_SwapChainDesc.BufferDesc.Height = HIWORD(lParam);
+ m_SwapChain->ResizeBuffers(m_SwapChainDesc.BufferCount, m_SwapChainDesc.BufferDesc.Width,
+ m_SwapChainDesc.BufferDesc.Height, m_SwapChainDesc.BufferDesc.Format,
+ m_SwapChainDesc.Flags);
+
+ m_DepthStencilDesc.Width = LOWORD(lParam);
+ m_DepthStencilDesc.Height = HIWORD(lParam);
+
+ CreateRenderTargetAndDepthStencil();
+
+ BackBufferResized();
+ }
+ }
+ }
+
+ if( uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST ||
+ uMsg >= WM_KEYFIRST && uMsg <= WM_KEYLAST )
+ {
+ // processing messages front-to-back
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ // for kb/mouse messages, 0 means the message has been handled
+ if(0 == (*it)->MsgProc(hWnd, uMsg, wParam, lParam))
+ return 0;
+ }
+ }
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+void
+DeviceManager::Render()
+{
+ D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (float)m_SwapChainDesc.BufferDesc.Width, (float)m_SwapChainDesc.BufferDesc.Height, 0.0f, 1.0f };
+
+ // rendering back-to-front
+ for(auto it = m_vControllers.rbegin(); it != m_vControllers.rend(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ m_ImmediateContext->OMSetRenderTargets(1, &m_BackBufferRTV, m_DepthStencilDSV);
+ m_ImmediateContext->RSSetViewports(1, &viewport);
+
+ (*it)->Render(m_Device, m_ImmediateContext, m_BackBufferRTV, m_DepthStencilDSV);
+ }
+ }
+
+ m_ImmediateContext->OMSetRenderTargets(0, NULL, NULL);
+}
+
+void
+DeviceManager::Animate(double fElapsedTimeSeconds)
+{
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ if((*it)->IsEnabled())
+ {
+ (*it)->Animate(fElapsedTimeSeconds);
+ }
+ }
+}
+
+void
+DeviceManager::DeviceCreated()
+{
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ (*it)->DeviceCreated(m_Device);
+ }
+}
+
+void
+DeviceManager::DeviceDestroyed()
+{
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ (*it)->DeviceDestroyed();
+ }
+}
+
+void
+DeviceManager::BackBufferResized()
+{
+ if(m_SwapChain == NULL)
+ return;
+
+ DXGI_SURFACE_DESC backSD;
+ backSD.Format = m_SwapChainDesc.BufferDesc.Format;
+ backSD.Width = m_SwapChainDesc.BufferDesc.Width;
+ backSD.Height = m_SwapChainDesc.BufferDesc.Height;
+ backSD.SampleDesc = m_SwapChainDesc.SampleDesc;
+
+ for(auto it = m_vControllers.begin(); it != m_vControllers.end(); it++)
+ {
+ (*it)->BackBufferResized(m_Device, &backSD);
+ }
+}
+
+HRESULT
+DeviceManager::ChangeBackBufferFormat(DXGI_FORMAT format, UINT sampleCount)
+{
+ HRESULT hr = E_FAIL;
+
+ if((format == DXGI_FORMAT_UNKNOWN || format == m_SwapChainDesc.BufferDesc.Format) &&
+ (sampleCount == 0 || sampleCount == m_SwapChainDesc.SampleDesc.Count))
+ return S_FALSE;
+
+ if(m_Device)
+ {
+ bool fullscreen = (GetWindowState() == kWindowFullscreen);
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(false, NULL);
+
+ IDXGISwapChain* newSwapChain = NULL;
+ DXGI_SWAP_CHAIN_DESC newSwapChainDesc = m_SwapChainDesc;
+
+ if(format != DXGI_FORMAT_UNKNOWN)
+ newSwapChainDesc.BufferDesc.Format = format;
+ if(sampleCount != 0)
+ newSwapChainDesc.SampleDesc.Count = sampleCount;
+
+ IDXGIAdapter* pDXGIAdapter = GetDXGIAdapter();
+
+ IDXGIFactory* pDXGIFactory = NULL;
+ pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pDXGIFactory));
+
+ hr = pDXGIFactory->CreateSwapChain(m_Device, &newSwapChainDesc, &newSwapChain);
+
+ pDXGIFactory->Release();
+ pDXGIAdapter->Release();
+
+ if (FAILED(hr))
+ {
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(true, NULL);
+
+ return hr;
+ }
+
+ SAFE_RELEASE(m_BackBufferRTV);
+ SAFE_RELEASE(m_SwapChain);
+ SAFE_RELEASE(m_DepthStencilBuffer);
+ SAFE_RELEASE(m_DepthStencilDSV);
+
+ m_SwapChain = newSwapChain;
+ m_SwapChainDesc = newSwapChainDesc;
+
+ m_DepthStencilDesc.SampleDesc.Count = sampleCount;
+
+ if(fullscreen)
+ m_SwapChain->SetFullscreenState(true, NULL);
+
+ CreateRenderTargetAndDepthStencil();
+ BackBufferResized();
+ }
+
+ return S_OK;
+}
+
+void
+DeviceManager::AddControllerToFront(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+ m_vControllers.push_front(pController);
+}
+
+void
+DeviceManager::AddControllerToBack(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+ m_vControllers.push_back(pController);
+}
+
+void
+DeviceManager::RemoveController(IVisualController* pController)
+{
+ m_vControllers.remove(pController);
+}
+
+HRESULT
+DeviceManager::ResizeWindow(int width, int height)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ RECT rect;
+ GetWindowRect(m_hWnd, &rect);
+
+ ShowWindow(m_hWnd, SW_RESTORE);
+
+ if(!MoveWindow(m_hWnd, rect.left, rect.top, width, height, true))
+ return E_FAIL;
+
+ // No need to call m_SwapChain->ResizeBackBuffer because MoveWindow will send WM_SIZE, which calls that function.
+
+ return S_OK;
+}
+
+HRESULT
+DeviceManager::EnterFullscreenMode(int width, int height)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ if(GetWindowState() == kWindowFullscreen)
+ return S_FALSE;
+
+ if(width <= 0 || height <= 0)
+ {
+ width = m_SwapChainDesc.BufferDesc.Width;
+ height = m_SwapChainDesc.BufferDesc.Height;
+ }
+
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_FULLSCREEN);
+ MoveWindow(m_hWnd, 0, 0, width, height, true);
+
+ HRESULT hr = m_SwapChain->SetFullscreenState(true, NULL);
+
+ if(FAILED(hr))
+ {
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_NORMAL);
+ return hr;
+ }
+
+ UpdateWindow(m_hWnd);
+ m_SwapChain->GetDesc(&m_SwapChainDesc);
+
+ return S_OK;
+}
+
+HRESULT
+DeviceManager::LeaveFullscreenMode(int windowWidth, int windowHeight)
+{
+ if(m_SwapChain == NULL)
+ return E_FAIL;
+
+ if(GetWindowState() != kWindowFullscreen)
+ return S_FALSE;
+
+ HRESULT hr = m_SwapChain->SetFullscreenState(false, NULL);
+ if(FAILED(hr)) return hr;
+
+ SetWindowLong(m_hWnd, GWL_STYLE, WINDOW_STYLE_NORMAL);
+
+ if(windowWidth <= 0 || windowHeight <= 0)
+ {
+ windowWidth = m_SwapChainDesc.BufferDesc.Width;
+ windowHeight = m_SwapChainDesc.BufferDesc.Height;
+ }
+
+ RECT rect = { 0, 0, windowWidth, windowHeight };
+ AdjustWindowRect(&rect, WINDOW_STYLE_NORMAL, FALSE);
+ MoveWindow(m_hWnd, 0, 0, rect.right - rect.left, rect.bottom - rect.top, true);
+ UpdateWindow(m_hWnd);
+
+ m_SwapChain->GetDesc(&m_SwapChainDesc);
+
+ return S_OK;
+}
+
+HRESULT
+DeviceManager::ToggleFullscreen()
+{
+ if(GetWindowState() == kWindowFullscreen)
+ return LeaveFullscreenMode();
+ else
+ return EnterFullscreenMode();
+}
+
+DeviceManager::WindowState
+DeviceManager::GetWindowState()
+{
+ if(m_SwapChain && !m_SwapChainDesc.Windowed)
+ return kWindowFullscreen;
+
+ if(m_hWnd == INVALID_HANDLE_VALUE)
+ return kWindowNone;
+
+ if(IsZoomed(m_hWnd))
+ return kWindowMaximized;
+
+ if(IsIconic(m_hWnd))
+ return kWindowMinimized;
+
+ return kWindowNormal;
+}
+
+HRESULT
+DeviceManager::GetDisplayResolution(int& width, int& height)
+{
+ if(m_hWnd != INVALID_HANDLE_VALUE)
+ {
+ HMONITOR monitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTOPRIMARY);
+ MONITORINFO info;
+ info.cbSize = sizeof(MONITORINFO);
+
+ if(GetMonitorInfo(monitor, &info))
+ {
+ width = info.rcMonitor.right - info.rcMonitor.left;
+ height = info.rcMonitor.bottom - info.rcMonitor.top;
+ return S_OK;
+ }
+ }
+
+ return E_FAIL;
+}
+
+IDXGIAdapter*
+DeviceManager::GetDXGIAdapter()
+{
+ if(!m_Device)
+ return NULL;
+
+ IDXGIDevice* pDXGIDevice = NULL;
+ m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDXGIDevice));
+
+ IDXGIAdapter* pDXGIAdapter = NULL;
+ pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDXGIAdapter));
+
+ pDXGIDevice->Release();
+
+ return pDXGIAdapter;
+}
diff --git a/samples/VolumetricLightingTest/d3d11/DeviceManager.h b/samples/VolumetricLightingTest/d3d11/DeviceManager.h
new file mode 100644
index 0000000..4bd164a
--- /dev/null
+++ b/samples/VolumetricLightingTest/d3d11/DeviceManager.h
@@ -0,0 +1,148 @@
+// TAGRELEASE: PUBLIC
+
+#pragma once
+#include <Windows.h>
+#include <DXGI.h>
+#include <D3D11.h>
+#include <list>
+
+
+struct DeviceCreationParameters
+{
+ bool startMaximized;
+ bool startFullscreen;
+ int backBufferWidth;
+ int backBufferHeight;
+ int refreshRate;
+ int swapChainBufferCount;
+ DXGI_FORMAT swapChainFormat;
+ DXGI_FORMAT depthStencilFormat;
+ DXGI_USAGE swapChainUsage;
+ int swapChainSampleCount;
+ UINT createDeviceFlags;
+ D3D_DRIVER_TYPE driverType;
+ D3D_FEATURE_LEVEL featureLevel;
+
+ DeviceCreationParameters()
+ : startMaximized(false)
+ , startFullscreen(false)
+ , backBufferWidth(1280)
+ , backBufferHeight(720)
+ , refreshRate(0)
+ , swapChainBufferCount(1)
+ , swapChainFormat(DXGI_FORMAT_R8G8B8A8_UNORM)
+ , depthStencilFormat(DXGI_FORMAT_D24_UNORM_S8_UINT)
+ , swapChainUsage(DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT)
+ , swapChainSampleCount(1)
+ , createDeviceFlags(0)
+ , driverType(D3D_DRIVER_TYPE_HARDWARE)
+ , featureLevel(D3D_FEATURE_LEVEL_11_0)
+ { }
+};
+
+#pragma warning(push)
+#pragma warning(disable: 4100) // unreferenced formal parameter
+class IVisualController
+{
+private:
+ bool m_Enabled;
+public:
+ IVisualController() : m_Enabled(true) { }
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return 1; }
+ virtual void Render(ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext, ID3D11RenderTargetView* pRTV, ID3D11DepthStencilView* pDSV) { }
+ virtual void Animate(double fElapsedTimeSeconds) { }
+ virtual HRESULT DeviceCreated(ID3D11Device* pDevice) { return S_OK; }
+ virtual void DeviceDestroyed() { }
+ virtual void BackBufferResized(ID3D11Device* pDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc) { }
+
+ virtual void EnableController() { m_Enabled = true; }
+ virtual void DisableController() { m_Enabled = false; }
+ virtual bool IsEnabled() { return m_Enabled; }
+};
+#pragma warning(pop)
+
+class DeviceManager
+{
+public:
+ enum WindowState
+ {
+ kWindowNone,
+ kWindowNormal,
+ kWindowMinimized,
+ kWindowMaximized,
+ kWindowFullscreen
+ };
+
+protected:
+ ID3D11Device* m_Device;
+ ID3D11DeviceContext* m_ImmediateContext;
+ IDXGISwapChain* m_SwapChain;
+ ID3D11RenderTargetView* m_BackBufferRTV;
+ ID3D11Texture2D* m_DepthStencilBuffer;
+ ID3D11DepthStencilView* m_DepthStencilDSV;
+ DXGI_SWAP_CHAIN_DESC m_SwapChainDesc;
+ D3D11_TEXTURE2D_DESC m_DepthStencilDesc;
+ HWND m_hWnd;
+ std::list<IVisualController*> m_vControllers;
+ std::wstring m_WindowTitle;
+ double m_FixedFrameInterval;
+ UINT m_SyncInterval;
+ std::list<double> m_vFrameTimes;
+ double m_AverageFrameTime;
+ double m_AverageTimeUpdateInterval;
+private:
+ HRESULT CreateRenderTargetAndDepthStencil();
+public:
+
+ DeviceManager()
+ : m_Device(NULL)
+ , m_ImmediateContext(NULL)
+ , m_SwapChain(NULL)
+ , m_BackBufferRTV(NULL)
+ , m_DepthStencilBuffer(NULL)
+ , m_DepthStencilDSV(NULL)
+ , m_hWnd(NULL)
+ , m_WindowTitle(L"")
+ , m_FixedFrameInterval(-1)
+ , m_SyncInterval(0)
+ , m_AverageFrameTime(0)
+ , m_AverageTimeUpdateInterval(0.5)
+ { }
+
+ virtual ~DeviceManager()
+ { Shutdown(); }
+
+ virtual HRESULT CreateWindowDeviceAndSwapChain(const DeviceCreationParameters& params, LPWSTR windowTitle);
+ virtual HRESULT ChangeBackBufferFormat(DXGI_FORMAT format, UINT sampleCount);
+ virtual HRESULT ResizeWindow(int width, int height);
+ virtual HRESULT EnterFullscreenMode(int width = 0, int height = 0);
+ virtual HRESULT LeaveFullscreenMode(int windowWidth = 0, int windowHeight = 0);
+ virtual HRESULT ToggleFullscreen();
+
+ virtual void Shutdown();
+ virtual void MessageLoop();
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Render();
+ virtual void Animate(double fElapsedTimeSeconds);
+ virtual void DeviceCreated();
+ virtual void DeviceDestroyed();
+ virtual void BackBufferResized();
+
+ void AddControllerToFront(IVisualController* pController);
+ void AddControllerToBack(IVisualController* pController);
+ void RemoveController(IVisualController* pController);
+
+ void SetFixedFrameInterval(double seconds) { m_FixedFrameInterval = seconds; }
+ void DisableFixedFrameInterval() { m_FixedFrameInterval = -1; }
+
+ HWND GetHWND() { return m_hWnd; }
+ ID3D11Device* GetDevice() { return m_Device; }
+ WindowState GetWindowState();
+ bool GetVsyncEnabled() { return m_SyncInterval > 0; }
+ void SetVsyncEnabled(bool enabled) { m_SyncInterval = enabled ? 1 : 0; }
+ HRESULT GetDisplayResolution(int& width, int& height);
+ IDXGIAdapter* GetDXGIAdapter();
+ double GetAverageFrameTime() { return m_AverageFrameTime; }
+ void SetAverageTimeUpdateInterval(double value) { m_AverageTimeUpdateInterval = value; }
+};
diff --git a/samples/VolumetricLightingTest/d3d11/compiled_shaders_d3d11.cpp b/samples/VolumetricLightingTest/d3d11/compiled_shaders_d3d11.cpp
new file mode 100644
index 0000000..43f2e5d
--- /dev/null
+++ b/samples/VolumetricLightingTest/d3d11/compiled_shaders_d3d11.cpp
@@ -0,0 +1,36 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#include <stdint.h>
+namespace d3d11 { namespace shaders {
+ #include <shaders/post_PS.mux.bytecode>
+ #include <shaders/quad_VS.mux.bytecode>
+ #include <shaders/scene_VS.mux.bytecode>
+ #include <shaders/scene_GS.mux.bytecode>
+ #include <shaders/scene_PS.mux.bytecode>
+}; /* namespace shaders */ }; /* namespace d3d11 */
diff --git a/samples/VolumetricLightingTest/d3d11/compiled_shaders_d3d11.h b/samples/VolumetricLightingTest/d3d11/compiled_shaders_d3d11.h
new file mode 100644
index 0000000..2488d61
--- /dev/null
+++ b/samples/VolumetricLightingTest/d3d11/compiled_shaders_d3d11.h
@@ -0,0 +1,45 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#ifndef COMPILED_SHADERS_D3D11_H
+#define COMPILED_SHADERS_D3D11_H
+////////////////////////////////////////////////////////////////////////////////
+#include <stdint.h>
+namespace d3d11 { namespace shaders {
+ #include <shaders/post_PS.mux.h>
+ #include <shaders/quad_VS.mux.h>
+ #include <shaders/scene_VS.mux.h>
+ #include <shaders/scene_GS.mux.h>
+ #include <shaders/scene_PS.mux.h>
+}; /* namespace shaders */ }; /* namespace d3d11 */
+// We use the namespaces to avoid conflicts if supporting multiple APIs
+// but they aren't needed wherever these would be included.
+using namespace d3d11;
+using namespace shaders;
+////////////////////////////////////////////////////////////////////////////////
+#endif // COMPILED_SHADERS_D3D11_H
diff --git a/samples/VolumetricLightingTest/d3d11/d3d11_main.cpp b/samples/VolumetricLightingTest/d3d11/d3d11_main.cpp
new file mode 100644
index 0000000..308d025
--- /dev/null
+++ b/samples/VolumetricLightingTest/d3d11/d3d11_main.cpp
@@ -0,0 +1,478 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+#include "common.h"
+
+#include "compiled_shaders_d3d11.h"
+#include "DeviceManager.h"
+#include "d3d11_util.h"
+#include "scene.h"
+
+#include <Nv/VolumetricLighting/NvVolumetricLighting.h>
+#include <d3d11.h>
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Control rendering of the scene
+#define LOAD_SHADERS(x) LoadShaders(device, ##x##::permutation_code, ##x##::permutation_length, shaders::##x##::PERMUTATION_ENTRY_COUNT, shaders.##x)
+
+class SceneController : public IVisualController
+{
+private:
+ Scene * pScene_;
+ DeviceManager * pManager_;
+
+ uint32_t framebufferWidth_;
+ uint32_t framebufferHeight_;
+
+ // Resources used by the scene
+
+ ConstantBuffer <Scene::ViewCB> * pViewCB_;
+ ConstantBuffer <Scene::ObjectCB> * pObjectCB_;
+ ConstantBuffer <Scene::LightCB> * pLightCB_;
+
+ RenderTarget * pSceneRT_;
+ DepthTarget * pSceneDepth_;
+ DepthTarget * pShadowMap_;
+ DepthTarget * pParaboloidShadowMap_;
+
+ ID3D11SamplerState * ss_shadowmap_;
+ ID3D11RasterizerState * rs_render_;
+ ID3D11BlendState * bs_no_color_;
+ ID3D11DepthStencilState * ds_shadowmap_;
+
+ struct
+ {
+ ID3D11PixelShader ** post_PS;
+ ID3D11VertexShader ** quad_VS;
+ ID3D11VertexShader ** scene_VS;
+ ID3D11GeometryShader ** scene_GS;
+ ID3D11PixelShader ** scene_PS;
+ } shaders;
+
+ // GWVL Platform-specific info
+ Nv::Vl::PlatformDesc platformDesc_;
+
+public:
+
+ SceneController(Scene * pScene, DeviceManager * pManager)
+ {
+ pScene_ = pScene;
+ pManager_ = pManager;
+ }
+
+ virtual HRESULT DeviceCreated(ID3D11Device* device)
+ {
+ Nv::Vl::OpenLibrary();
+
+ // Shaders
+ LOAD_SHADERS(post_PS);
+ LOAD_SHADERS(quad_VS);
+ LOAD_SHADERS(scene_VS);
+ LOAD_SHADERS(scene_GS);
+ LOAD_SHADERS(scene_PS);
+
+ // Constant Buffers
+ pViewCB_ = ConstantBuffer<Scene::ViewCB>::Create(device);
+ pObjectCB_ = ConstantBuffer<Scene::ObjectCB>::Create(device);
+ pLightCB_ = ConstantBuffer<Scene::LightCB>::Create(device);
+
+ // Textures
+ pSceneRT_ = nullptr;
+ pSceneDepth_ = nullptr;
+ pShadowMap_ = DepthTarget::Create(device, Scene::SHADOWMAP_RESOLUTION, Scene::SHADOWMAP_RESOLUTION, 1, DXGI_FORMAT_D16_UNORM, 1, "Simple Shadow Map");
+ pParaboloidShadowMap_ = DepthTarget::Create(device, Scene::SHADOWMAP_RESOLUTION, Scene::SHADOWMAP_RESOLUTION, 1, DXGI_FORMAT_D16_UNORM, 2, "Dual-Paraboloid Shadow Map");
+
+ // Shadowmap Sampler
+ {
+ CD3D11_SAMPLER_DESC desc((CD3D11_DEFAULT()));
+ desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
+ desc.ComparisonFunc = D3D11_COMPARISON_LESS;
+ device->CreateSamplerState(&desc, &ss_shadowmap_);
+ }
+ // No color output blend-state
+ {
+ CD3D11_BLEND_DESC desc((CD3D11_DEFAULT()));
+ desc.RenderTarget[0].RenderTargetWriteMask = 0x00000000;
+ device->CreateBlendState(&desc, &bs_no_color_);
+ }
+ {
+ CD3D11_RASTERIZER_DESC rsDesc((CD3D11_DEFAULT()));
+ rsDesc.CullMode = D3D11_CULL_NONE;
+ device->CreateRasterizerState(&rsDesc, &rs_render_);
+ }
+ {
+ CD3D11_DEPTH_STENCIL_DESC dsDesc((CD3D11_DEFAULT()));
+ device->CreateDepthStencilState(&dsDesc, &ds_shadowmap_);
+ }
+ // Initialize GWVL settings info
+ {
+ platformDesc_.platform = Nv::Vl::PlatformName::D3D11;
+ platformDesc_.d3d11.pDevice = device;
+ }
+
+ return S_OK;
+ }
+
+ virtual void DeviceDestroyed()
+ {
+ // Release resources
+ SAFE_RELEASE(ss_shadowmap_);
+ SAFE_RELEASE(bs_no_color_);
+ SAFE_RELEASE(rs_render_);
+ SAFE_RELEASE(ds_shadowmap_);
+ SAFE_DELETE(pViewCB_);
+ SAFE_DELETE(pObjectCB_);
+ SAFE_DELETE(pLightCB_);
+ SAFE_DELETE(pSceneRT_);
+ SAFE_DELETE(pSceneDepth_);
+ SAFE_DELETE(pShadowMap_);
+ SAFE_DELETE(pParaboloidShadowMap_);
+ SAFE_DELETE_ARRAY(shaders.post_PS);
+ SAFE_DELETE_ARRAY(shaders.quad_VS);
+ SAFE_DELETE_ARRAY(shaders.scene_VS);
+ SAFE_DELETE_ARRAY(shaders.scene_GS);
+ SAFE_DELETE_ARRAY(shaders.scene_PS);
+
+ pScene_->Release();
+ Nv::Vl::CloseLibrary();
+ }
+
+ virtual void BackBufferResized(ID3D11Device* device, const DXGI_SURFACE_DESC* surface_desc)
+ {
+ framebufferWidth_ = surface_desc->Width;
+ framebufferHeight_ = surface_desc->Height;
+
+ // Create back-buffer sized resources
+ SAFE_DELETE(pSceneRT_);
+ SAFE_DELETE(pSceneDepth_);
+ pSceneRT_ = RenderTarget::Create(device, framebufferWidth_, framebufferHeight_, surface_desc->SampleDesc.Count, DXGI_FORMAT_R16G16B16A16_FLOAT, "Scene Render Target");
+ pSceneDepth_ = DepthTarget::Create(device, framebufferWidth_, framebufferHeight_, surface_desc->SampleDesc.Count, DXGI_FORMAT_D24_UNORM_S8_UINT, 1, "Scene Depth");
+
+ // Update the context desc and (re-)create the context
+ pScene_->updateFramebuffer(framebufferWidth_, framebufferHeight_, surface_desc->SampleDesc.Count);
+ }
+
+ virtual void Render(ID3D11Device*, ID3D11DeviceContext* ctx, ID3D11RenderTargetView* pFramebuffer_RTV, ID3D11DepthStencilView*)
+ {
+ NV_PERFEVENT(ctx, "Render Frame");
+ if (!pScene_->isCtxValid())
+ {
+ pScene_->createCtx(&platformDesc_);
+ }
+
+ float clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ ctx->ClearRenderTargetView( pSceneRT_->getRTV(), clear_color);
+ ctx->ClearDepthStencilView(pSceneDepth_->getDSV(), D3D11_CLEAR_DEPTH, 1.0, 0);
+
+ ID3D11Buffer * CBs[] = {
+ pViewCB_->getCB(),
+ pObjectCB_->getCB(),
+ pLightCB_->getCB()
+ };
+
+ auto RenderScene = [=]()
+ {
+ NV_PERFEVENT(ctx, "Draw Scene Geometry");
+ const float scene_range[] = { -6, -3, 3, 6 };
+ for (auto x : scene_range)
+ {
+ for (auto y : scene_range)
+ {
+ for (auto z : scene_range)
+ {
+ Scene::ObjectCB * pObject = this->pObjectCB_->Map(ctx);
+ pScene_->setupObjectCB(pObject, Nv::NvVec3(x, y, z));
+ this->pObjectCB_->Unmap(ctx);
+
+ ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ctx->IASetVertexBuffers(0,0,nullptr, nullptr,nullptr);
+ ctx->IASetInputLayout(nullptr);
+ ctx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0);
+ ctx->Draw(36, 0);
+ }
+ }
+ }
+ };
+
+ //----------------------------------------------------------------------
+ // Render the light's shadow map
+ {
+ NV_PERFEVENT(ctx, "Render Shadow Map");
+ {
+ Scene::ViewCB * pView = pViewCB_->Map(ctx);
+ pScene_->setupLightViewCB(pView);
+ pViewCB_->Unmap(ctx);
+ }
+
+ ctx->ClearState();
+ CD3D11_VIEWPORT shadowmap_viewport;
+ shadowmap_viewport.TopLeftX = 0;
+ shadowmap_viewport.TopLeftY = 0;
+ shadowmap_viewport.Width = static_cast<float>(Scene::SHADOWMAP_RESOLUTION);
+ shadowmap_viewport.Height = static_cast<float>(Scene::SHADOWMAP_RESOLUTION);
+ shadowmap_viewport.MinDepth = 0.0f;
+ shadowmap_viewport.MaxDepth = 1.0f;
+ ctx->RSSetState(rs_render_);
+ ctx->VSSetShader(shaders.scene_VS[scene_VS::SINGLE], nullptr, 0);
+ ctx->VSSetConstantBuffers(0, 3, CBs);
+ if (pScene_->getLightMode() == Scene::eLightMode::OMNI)
+ {
+ ctx->ClearDepthStencilView(pParaboloidShadowMap_->getDSV(), D3D11_CLEAR_DEPTH, 1.0, 0);
+ ctx->OMSetRenderTargets(0, nullptr, pParaboloidShadowMap_->getDSV());
+ CD3D11_VIEWPORT dual_viewports[] = { shadowmap_viewport, shadowmap_viewport };
+ ctx->RSSetViewports(2, dual_viewports);
+ ctx->GSSetShader(shaders.scene_GS[scene_GS::SINGLE], nullptr, 0);
+ ctx->GSSetConstantBuffers(0, 3, CBs);
+ }
+ else
+ {
+ ctx->ClearDepthStencilView(pShadowMap_->getDSV(), D3D11_CLEAR_DEPTH, 1.0, 0);
+ ctx->OMSetRenderTargets(0, nullptr, pShadowMap_->getDSV());
+ ctx->RSSetViewports(1, &shadowmap_viewport);
+ }
+ ctx->PSSetShader(nullptr, nullptr, 0);
+ ctx->OMSetBlendState(bs_no_color_, nullptr, 0xFFFFFFFF);
+ ctx->OMSetDepthStencilState(ds_shadowmap_, 0xFF);
+ RenderScene();
+ }
+ ID3D11ShaderResourceView * shadowmap_srv = (pScene_->getLightMode() == Scene::eLightMode::OMNI) ? pParaboloidShadowMap_->getSRV() : pShadowMap_->getSRV();
+
+ //----------------------------------------------------------------------
+ // Render the scene
+ {
+ NV_PERFEVENT(ctx, "Render Main Scene");
+ {
+ Scene::ViewCB * pView = pViewCB_->Map(ctx);
+ Scene::LightCB * pLight = pLightCB_->Map(ctx);
+ pScene_->setupSceneCBs(pView, pLight);
+ pViewCB_->Unmap(ctx);
+ pLightCB_->Unmap(ctx);
+ }
+
+ ctx->ClearState();
+ CD3D11_VIEWPORT scene_viewport;
+ scene_viewport.TopLeftX = 0.0f;
+ scene_viewport.TopLeftY = 0.f;
+ scene_viewport.Width = static_cast<float>(framebufferWidth_);
+ scene_viewport.Height = static_cast<float>(framebufferHeight_);
+ scene_viewport.MinDepth = 0.0f;
+ scene_viewport.MaxDepth = 1.0f;
+ ctx->RSSetViewports(1, &scene_viewport);
+ ctx->RSSetState(rs_render_);
+ ctx->VSSetShader(shaders.scene_VS[scene_VS::SINGLE], nullptr, 0);
+ ctx->VSSetConstantBuffers(0, 3, CBs);
+ ctx->GSSetShader(nullptr, nullptr, 0);
+ scene_PS::Desc ps_desc;
+ switch (pScene_->getLightMode())
+ {
+ default:
+ case Scene::eLightMode::DIRECTIONAL:
+ ps_desc.flags.LIGHTMODE = scene_PS::LIGHTMODE_DIRECTIONAL;
+ break;
+
+ case Scene::eLightMode::SPOTLIGHT:
+ ps_desc.flags.LIGHTMODE = scene_PS::LIGHTMODE_SPOTLIGHT;
+ break;
+
+ case Scene::eLightMode::OMNI:
+ ps_desc.flags.LIGHTMODE = scene_PS::LIGHTMODE_OMNI;
+ break;
+ }
+ ctx->PSSetShader(shaders.scene_PS[ps_desc], nullptr, 0);
+ ctx->PSSetConstantBuffers(0, 3, CBs);
+ ID3D11ShaderResourceView * SRVs[] = { shadowmap_srv };
+ ctx->PSSetShaderResources(0, 1, SRVs);
+ ctx->PSSetSamplers(0, 1, &ss_shadowmap_);
+ ID3D11RenderTargetView * RTVs[] = { pSceneRT_->getRTV() };
+ ctx->OMSetRenderTargets(1, RTVs, pSceneDepth_->getDSV());
+ RenderScene();
+ }
+
+ //----------------------------------------------------------------------
+ // Render the volumetric lighting
+ {
+ NV_PERFEVENT(ctx, "Volumetric Lighting");
+ ctx->ClearState();
+ pScene_->beginAccumulation(ctx, pSceneDepth_->getSRV());
+ pScene_->renderVolume(ctx, shadowmap_srv);
+ pScene_->endAccumulation(ctx);
+ pScene_->applyLighting(ctx, pSceneRT_->getRTV(), pSceneDepth_->getSRV());
+ }
+
+ //----------------------------------------------------------------------
+ // Tonemap to output
+ {
+ NV_PERFEVENT(ctx, "Postprocess");
+ ctx->ClearState();
+ CD3D11_VIEWPORT scene_viewport;
+ scene_viewport.TopLeftX = 0.0f;
+ scene_viewport.TopLeftY = 0.f;
+ scene_viewport.Width = static_cast<float>(framebufferWidth_);
+ scene_viewport.Height = static_cast<float>(framebufferHeight_);
+ scene_viewport.MinDepth = 0.0f;
+ scene_viewport.MaxDepth = 1.0f;
+ ctx->RSSetViewports(1, &scene_viewport);
+ ctx->RSSetState(rs_render_);
+ ID3D11RenderTargetView * RTVs[] = { pFramebuffer_RTV };
+ ctx->OMSetRenderTargets(1, RTVs, nullptr);
+ ctx->VSSetShader(shaders.quad_VS[quad_VS::SINGLE], nullptr, 0);
+ ctx->PSSetShader(shaders.post_PS[post_PS::SINGLE], nullptr, 0);
+ ID3D11ShaderResourceView * SRVs[] = { pSceneRT_->getSRV() };
+ ctx->PSSetShaderResources(0, 1, SRVs);
+ ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ctx->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr);
+ ctx->IASetInputLayout(nullptr);
+ ctx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0);
+ ctx->Draw(3, 0);
+ }
+ }
+
+ virtual void Animate(double fElapsedTimeSeconds)
+ {
+ pScene_->animate((float)fElapsedTimeSeconds);
+ }
+
+ virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ hWnd; uMsg; wParam; lParam;
+ switch (uMsg)
+ {
+ case WM_KEYDOWN:
+ switch (wParam)
+ {
+ case VK_ESCAPE:
+ PostQuitMessage(0);
+ break;
+
+ case VK_F1:
+ pScene_->setDebugMode(Nv::Vl::DebugFlags::NONE);
+ break;
+
+ case VK_F2:
+ pScene_->setDebugMode(Nv::Vl::DebugFlags::NO_BLENDING);
+ break;
+
+ case VK_F3:
+ pScene_->setDebugMode(Nv::Vl::DebugFlags::WIREFRAME);
+ break;
+
+ case VK_F4:
+ pManager_->ToggleFullscreen();
+ break;
+
+ case VK_SPACE:
+ pScene_->togglePause();
+ break;
+
+ case 0x44: // D key - toggle downsample mode
+ pScene_->toggleDownsampleMode();
+ break;
+
+ case 0x46: // F key - toggle fog
+ pScene_->toggleFog();
+ break;
+
+ case 0x4C: // L key - toggle light type
+ pScene_->toggleLightMode();
+ break;
+
+ case 0x4D: // M key - toggle MSAA mode
+ pScene_->toggleMsaaMode();
+ break;
+
+ case 0x4F: // O key - toggle light intensity
+ pScene_->toggleMediumType();
+ break;
+
+ case 0x50: // P key - toggle light intensity
+ pScene_->toggleIntensity();
+ break;
+
+ case 0x54: // T key - toggle temporal filtering
+ pScene_->toggleFiltering();
+ break;
+
+ case 0x55: // U key - toggle upsample mode
+ pScene_->toggleUpsampleMode();
+ break;
+
+ case 0x56: // V key - toggle view mode
+ pScene_->toggleViewpoint();
+ break;
+ }
+ return 0;
+ }
+ return 1;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Entry point to the program. Initializes everything and goes into a message processing
+// loop. Idle time is used to render the scene.
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int main_D3D11(Scene * pScene)
+{
+ // Enable run-time memory check for debug builds.
+#if (NV_CHECKED)
+ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+
+ AllocConsole();
+ freopen("CONIN$", "r",stdin);
+ freopen("CONOUT$", "w",stdout);
+ freopen("CONOUT$", "w",stderr);
+#endif
+
+ DeviceManager * device_manager = new DeviceManager();
+
+ auto scene_controller = SceneController(pScene, device_manager);
+ device_manager->AddControllerToFront(&scene_controller);
+
+ DeviceCreationParameters deviceParams;
+ deviceParams.swapChainFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ deviceParams.swapChainSampleCount = 4;
+ deviceParams.startFullscreen = false;
+ deviceParams.backBufferWidth = 1920;
+ deviceParams.backBufferHeight = 1080;
+#if (NV_CHECKED)
+ deviceParams.createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ if(FAILED(device_manager->CreateWindowDeviceAndSwapChain(deviceParams, L"Gameworks Volumetric Lighting Unit Test")))
+ {
+ MessageBox(nullptr, L"Cannot initialize the D3D11 device with the requested parameters", L"Error", MB_OK | MB_ICONERROR);
+ return 1;
+ }
+ // Loop
+ device_manager->MessageLoop();
+ // Shutdown and exit
+ device_manager->Shutdown();
+ delete device_manager;
+
+ return 0;
+}
diff --git a/samples/VolumetricLightingTest/d3d11/d3d11_util.cpp b/samples/VolumetricLightingTest/d3d11/d3d11_util.cpp
new file mode 100644
index 0000000..4226fdb
--- /dev/null
+++ b/samples/VolumetricLightingTest/d3d11/d3d11_util.cpp
@@ -0,0 +1,347 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#include "common.h"
+#include "d3d11_util.h"
+#include <d3d11.h>
+
+/*==============================================================================
+ Overloaded functions to make shader compilation simpler
+==============================================================================*/
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11VertexShader ** out_shader)
+ { return device->CreateVertexShader(data, length, nullptr, out_shader); }
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11HullShader ** out_shader)
+ { return device->CreateHullShader(data, length, nullptr, out_shader); }
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11DomainShader ** out_shader)
+ { return device->CreateDomainShader(data, length, nullptr, out_shader); }
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11GeometryShader ** out_shader)
+ { return device->CreateGeometryShader(data, length, nullptr, out_shader); }
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11PixelShader ** out_shader)
+ { return device->CreatePixelShader(data, length, nullptr, out_shader); }
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11ComputeShader ** out_shader)
+ { return device->CreateComputeShader(data, length, nullptr, out_shader); }
+/*==============================================================================
+ Texture resource management helpers
+==============================================================================*/
+
+//------------------------------------------------------------------------------
+ShaderResource::ShaderResource(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11UnorderedAccessView * uav)
+{
+ resource_ = resource;
+ srv_ = srv;
+ uav_ = uav;
+}
+
+ShaderResource::~ShaderResource()
+{
+ SAFE_RELEASE(resource_);
+ SAFE_RELEASE(srv_);
+ SAFE_RELEASE(uav_);
+}
+
+//------------------------------------------------------------------------------
+RenderTarget * RenderTarget::Create(ID3D11Device * device, UINT width, UINT height, UINT samples, DXGI_FORMAT format, const char * debug_name)
+{
+ ID3D11Texture2D * tex = nullptr;
+ ID3D11ShaderResourceView * srv = nullptr;
+ ID3D11RenderTargetView * rtv = nullptr;
+ ID3D11UnorderedAccessView * uav = nullptr;
+
+ CD3D11_TEXTURE2D_DESC texDesc;
+ texDesc.ArraySize = 1;
+ texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ if (samples == 1)
+ texDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+ texDesc.CPUAccessFlags = 0;
+ texDesc.Format = format;
+ texDesc.Width = width;
+ texDesc.Height = height;
+ texDesc.MipLevels = 1;
+ texDesc.MiscFlags = 0;
+ if (samples > 1)
+ {
+ texDesc.SampleDesc.Count = samples;
+ texDesc.SampleDesc.Quality = 0;//static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN);
+ }
+ else
+ {
+ texDesc.SampleDesc.Count = 1;
+ texDesc.SampleDesc.Quality = 0;
+ }
+ texDesc.Usage = D3D11_USAGE_DEFAULT;
+ device->CreateTexture2D(&texDesc, nullptr, &tex);
+ if (tex == nullptr)
+ {
+ return nullptr;
+ }
+
+ CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = texDesc.Format;
+ if (samples > 1)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ srvDesc.Texture2D.MipLevels = 1;
+ }
+ device->CreateShaderResourceView(tex, &srvDesc, &srv);
+ if (srv == nullptr)
+ {
+ tex->Release();
+ return nullptr;
+ }
+
+ CD3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = texDesc.Format;
+ if (samples > 1)
+ {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+ }
+ else
+ {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = 0;
+ }
+ device->CreateRenderTargetView(tex, &rtvDesc, &rtv);
+ if (rtv == nullptr)
+ {
+ tex->Release();
+ srv->Release();
+ return nullptr;
+ }
+
+ if (samples == 1)
+ {
+ CD3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+ uavDesc.Format = texDesc.Format;
+ uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+ uavDesc.Texture2D.MipSlice = 0;
+ device->CreateUnorderedAccessView(tex, &uavDesc, &uav);
+ if (uav == nullptr)
+ {
+ tex->Release();
+ srv->Release();
+ rtv->Release();
+ return nullptr;
+ }
+ }
+#if (NV_DEBUG || NV_PROFILE)
+ if (debug_name)
+ {
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT)strlen(debug_name), debug_name);
+ }
+#else
+ debug_name;
+#endif
+ return new RenderTarget(tex, srv, rtv, uav);
+}
+
+RenderTarget::RenderTarget(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11RenderTargetView * rtv, ID3D11UnorderedAccessView * uav)
+ : ShaderResource(resource, srv, uav)
+{
+ rtv_ = rtv;
+}
+
+RenderTarget::~RenderTarget()
+{
+ SAFE_RELEASE(rtv_);
+}
+
+//------------------------------------------------------------------------------
+DepthTarget * DepthTarget::Create(ID3D11Device * device, UINT width, UINT height, UINT samples, DXGI_FORMAT format, uint32_t slices, char * debug_name)
+{
+ ID3D11Texture2D * tex = nullptr;
+ ID3D11ShaderResourceView * srv = nullptr;
+ ID3D11DepthStencilView * dsv = nullptr;
+ ID3D11DepthStencilView * dsv_ro = nullptr;
+
+ DXGI_FORMAT tex_format;
+ DXGI_FORMAT srv_format;
+ DXGI_FORMAT dsv_format;
+ switch (format)
+ {
+ case DXGI_FORMAT_D32_FLOAT:
+ tex_format = DXGI_FORMAT_R32_TYPELESS;
+ srv_format = DXGI_FORMAT_R32_FLOAT;
+ dsv_format = DXGI_FORMAT_D32_FLOAT;
+ break;
+
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ tex_format = DXGI_FORMAT_R24G8_TYPELESS;
+ srv_format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
+ dsv_format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ break;
+
+ case DXGI_FORMAT_D16_UNORM:
+ tex_format = DXGI_FORMAT_R16_TYPELESS;
+ srv_format = DXGI_FORMAT_R16_UNORM;
+ dsv_format = DXGI_FORMAT_D16_UNORM;
+ break;
+
+ default:
+ return nullptr;
+ }
+
+ CD3D11_TEXTURE2D_DESC texDesc;
+ texDesc.ArraySize = slices;
+ texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+ texDesc.CPUAccessFlags = 0;
+ texDesc.Format = tex_format;
+ texDesc.Width = width;
+ texDesc.Height = height;
+ texDesc.MipLevels = 1;
+ texDesc.MiscFlags = 0;
+ if (samples > 1)
+ {
+ texDesc.SampleDesc.Count = samples;
+ texDesc.SampleDesc.Quality = 0;//static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN);
+ }
+ else
+ {
+ texDesc.SampleDesc.Count = 1;
+ texDesc.SampleDesc.Quality = 0;
+ }
+ texDesc.Usage = D3D11_USAGE_DEFAULT;
+ device->CreateTexture2D(&texDesc, nullptr, &tex);
+ if (tex == nullptr)
+ {
+ return nullptr;
+ }
+
+ CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = srv_format;
+ if (slices == 1)
+ {
+ if (samples > 1)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ srvDesc.Texture2D.MipLevels = 1;
+ }
+ }
+ else
+ {
+ if (samples > 1)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
+ srvDesc.Texture2DMSArray.FirstArraySlice = 0;
+ srvDesc.Texture2DMSArray.ArraySize = slices;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = 0;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = 0;
+ srvDesc.Texture2DArray.ArraySize = slices;
+ }
+ }
+ device->CreateShaderResourceView(tex, &srvDesc, &srv);
+
+ if (srv == nullptr)
+ {
+ tex->Release();
+ return nullptr;
+ }
+
+ CD3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Flags = 0;
+ dsvDesc.Format = dsv_format;
+ if (slices == 1)
+ {
+ if (samples > 1)
+ {
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ }
+ else
+ {
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ dsvDesc.Texture2D.MipSlice = 0;
+ }
+ }
+ else
+ {
+ if (samples > 1)
+ {
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
+ dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
+ dsvDesc.Texture2DMSArray.ArraySize = slices;
+ }
+ else
+ {
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ dsvDesc.Texture2DArray.MipSlice = 0;
+ dsvDesc.Texture2DArray.FirstArraySlice = 0;
+ dsvDesc.Texture2DArray.ArraySize = slices;
+ }
+ }
+
+ device->CreateDepthStencilView(tex, &dsvDesc, &dsv);
+ dsvDesc.Flags |= D3D11_DSV_READ_ONLY_DEPTH;
+ if (dsv_format == DXGI_FORMAT_D24_UNORM_S8_UINT)
+ dsvDesc.Flags |= D3D11_DSV_READ_ONLY_STENCIL;
+ device->CreateDepthStencilView(tex, &dsvDesc, &dsv_ro);
+ if (dsv == nullptr || dsv_ro == nullptr)
+ {
+ tex->Release();
+ srv->Release();
+ return nullptr;
+ }
+
+#if (NV_DEBUG || NV_PROFILE)
+ if (debug_name)
+ {
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT)strlen(debug_name), debug_name);
+ }
+#else
+ debug_name;
+#endif
+
+ return new DepthTarget(tex, srv, dsv, dsv_ro, nullptr);
+}
+
+DepthTarget::DepthTarget(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11DepthStencilView * dsv, ID3D11DepthStencilView * readonly_dsv, ID3D11UnorderedAccessView * uav)
+ : ShaderResource(resource, srv, uav)
+{
+ dsv_ = dsv;
+ readonly_dsv_ = readonly_dsv;
+}
+
+DepthTarget::~DepthTarget()
+{
+ SAFE_RELEASE(dsv_);
+ SAFE_RELEASE(readonly_dsv_);
+}
+
diff --git a/samples/VolumetricLightingTest/d3d11/d3d11_util.h b/samples/VolumetricLightingTest/d3d11/d3d11_util.h
new file mode 100644
index 0000000..e9322cf
--- /dev/null
+++ b/samples/VolumetricLightingTest/d3d11/d3d11_util.h
@@ -0,0 +1,234 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2003 - 2016 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#ifndef D3D11_UTIL_H
+#define D3D11_UTIL_H
+////////////////////////////////////////////////////////////////////////////////
+#include "common.h"
+
+#include <d3d11.h>
+#include <d3d11_1.h>
+
+#pragma warning( disable: 4127 )
+
+////////////////////////////////////////////////////////////////////////////////
+/*==============================================================================
+ Overloaded functions to make shader compilation simpler
+==============================================================================*/
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11VertexShader ** out_shader);
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11HullShader ** out_shader);
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11DomainShader ** out_shader);
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11GeometryShader ** out_shader);
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11PixelShader ** out_shader);
+HRESULT CompileShader(ID3D11Device * device, const void * data, UINT length, ID3D11ComputeShader ** out_shader);
+
+
+template <class T>
+NV_FORCE_INLINE HRESULT LoadShaders(ID3D11Device * device, const void ** shader_codes, const uint32_t * shader_lengths, UINT count, T ** &out_shaders)
+{
+ HRESULT hr = S_OK;
+ out_shaders = new T*[count];
+ for (UINT i = 0; i < count; ++i)
+ {
+ const void * code = shader_codes[i];
+ uint32_t length = shader_lengths[i];
+ if (code == nullptr)
+ {
+ out_shaders[i] = nullptr;
+ continue;
+ }
+ hr = CompileShader(device, code, length, &out_shaders[i]);
+ ASSERT_LOG(hr == S_OK, "Failure loading shader");
+ if (FAILED(hr))
+ break;
+ }
+ return hr;
+}
+
+/*==============================================================================
+ Perf Events
+==============================================================================*/
+
+class ScopedPerfEvent
+{
+public:
+ ScopedPerfEvent(ID3D11DeviceContext * ctx, const wchar_t * msg)
+ {
+ ctx->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&pPerf));
+ if (pPerf)
+ {
+ pPerf->BeginEvent(msg);
+ }
+ }
+
+ ~ScopedPerfEvent()
+ {
+ if (pPerf)
+ {
+ pPerf->EndEvent();
+ SAFE_RELEASE(pPerf);
+ }
+ };
+
+private:
+ ScopedPerfEvent() : pPerf(nullptr) {};
+ ID3DUserDefinedAnnotation * pPerf;
+};
+
+#if (NV_PROFILE)
+# define NV_PERFEVENT(c, t) ScopedPerfEvent perfevent_##__COUNTER__##(c, L##t)
+# define NV_PERFEVENT_BEGIN(c, t) { \
+ ID3DUserDefinedAnnotation * pPerf_##__COUNTER__ ; \
+ c->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&pPerf_##__COUNTER__##)); \
+ if (pPerf_##__COUNTER__##) { pPerf_##__COUNTER__##->BeginEvent(L##t); pPerf_##__COUNTER__##->Release(); } }
+# define NV_PERFEVENT_END(c) { \
+ ID3DUserDefinedAnnotation * pPerf_##__COUNTER__ ; \
+ c->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&pPerf_##__COUNTER__##)); \
+ if (pPerf_##__COUNTER__##) { pPerf_##__COUNTER__##->EndEvent(); pPerf_##__COUNTER__##->Release(); } }
+#else
+# define NV_PERFEVENT(c, t)
+# define NV_PERFEVENT_BEGIN(c, t)
+# define NV_PERFEVENT_END(c)
+#endif
+
+/*==============================================================================
+ Constant buffer management
+==============================================================================*/
+
+template <class T>
+class ConstantBuffer
+{
+public:
+ static ConstantBuffer<T> * Create(ID3D11Device * device)
+ {
+ HRESULT hr;
+ ID3D11Buffer * cb = nullptr;
+
+ static_assert((sizeof(T) % 16) == 0, "Constant buffer size must be 16-byte aligned");
+
+ CD3D11_BUFFER_DESC cbDesc;
+ cbDesc.ByteWidth = sizeof(T);
+ cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ cbDesc.Usage = D3D11_USAGE_DYNAMIC;
+ cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ cbDesc.MiscFlags = 0;
+ cbDesc.StructureByteStride = 1;
+ hr = device->CreateBuffer(&cbDesc, nullptr, &cb);
+ if (cb == nullptr)
+ return nullptr;
+ return new ConstantBuffer<T>(cb);
+ }
+
+ ConstantBuffer(ID3D11Buffer * b)
+ {
+ buffer_ = b;
+ }
+
+ ~ConstantBuffer()
+ {
+ SAFE_RELEASE(buffer_);
+ }
+
+ T * Map(ID3D11DeviceContext * ctx)
+ {
+ HRESULT hr;
+ D3D11_MAPPED_SUBRESOURCE data;
+ hr = ctx->Map(buffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &data);
+ return static_cast<T*>(data.pData);
+ }
+
+ void Unmap(ID3D11DeviceContext * ctx)
+ {
+ ctx->Unmap(buffer_, 0);
+ }
+
+ ID3D11Buffer * getCB() { return buffer_; }
+
+private:
+ ConstantBuffer() {};
+
+ ID3D11Buffer *buffer_;
+};
+
+/*==============================================================================
+ Texture resource management helpers
+==============================================================================*/
+
+//------------------------------------------------------------------------------
+class ShaderResource
+{
+public:
+ ShaderResource(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11UnorderedAccessView * uav);
+ ~ShaderResource();
+
+ ID3D11Resource * getResource() { return resource_; }
+ ID3D11ShaderResourceView * getSRV() { return srv_; }
+ ID3D11UnorderedAccessView * getUAV() { return uav_; }
+
+protected:
+ ShaderResource() {};
+
+ ID3D11Resource * resource_;
+ ID3D11ShaderResourceView * srv_;
+ ID3D11UnorderedAccessView * uav_;
+};
+
+//------------------------------------------------------------------------------
+class RenderTarget : public ShaderResource
+{
+public:
+ static RenderTarget * Create(ID3D11Device * device, UINT width, UINT height, UINT samples, DXGI_FORMAT format, const char * debug_name=nullptr);
+ RenderTarget(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11RenderTargetView * rtv, ID3D11UnorderedAccessView * uav);
+ ~RenderTarget();
+
+ ID3D11RenderTargetView * getRTV() { return rtv_; }
+
+protected:
+ RenderTarget() {};
+ ID3D11RenderTargetView * rtv_;
+};
+
+//------------------------------------------------------------------------------
+class DepthTarget : public ShaderResource
+{
+public:
+ static DepthTarget * Create(ID3D11Device * device, UINT width, UINT height, UINT samples, DXGI_FORMAT format, uint32_t slices=1, char * debug_name=nullptr);
+ DepthTarget(ID3D11Resource * resource, ID3D11ShaderResourceView * srv, ID3D11DepthStencilView * dsv, ID3D11DepthStencilView * readonly_dsv, ID3D11UnorderedAccessView * uav);
+ ~DepthTarget();
+
+ ID3D11DepthStencilView * getDSV() { return dsv_; }
+ ID3D11DepthStencilView * getReadOnlyDSV() { return readonly_dsv_; }
+
+protected:
+ DepthTarget() {};
+ ID3D11DepthStencilView * dsv_;
+ ID3D11DepthStencilView * readonly_dsv_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+#endif // D3D11_UTIL_H \ No newline at end of file