More DX12 initialization code,

This commit is contained in:
Artem Kharytoniuk 2017-10-21 21:08:25 +02:00
parent 22d5bdd053
commit 5434627172
6 changed files with 2658 additions and 6 deletions

View File

@ -431,7 +431,7 @@ static HWND create_main_window(int width, int height, qboolean fullscreen)
return hwnd;
}
static HWND create_twin_window(int width, int height)
static HWND create_twin_window(int width, int height, bool dx_window)
{
//
// register the window class if necessary
@ -502,7 +502,7 @@ static HWND create_twin_window(int width, int height)
// If r_renderAPI = 0 (OpenGL) then twin window uses Vulkan API.
// If r_renderAPI = 1 (Vulkan) then twin window uses OpenGL API.
char window_name[1024];
sprintf(window_name, "%s [%s]", MAIN_WINDOW_CLASS_NAME, r_renderAPI->integer == 0 ? "Vulkan" : "OpenGL");
sprintf(window_name, "%s [%s]", MAIN_WINDOW_CLASS_NAME, dx_window ? "DX12" : (r_renderAPI->integer == 0 ? "Vulkan" : "OpenGL"));
HWND hwnd = CreateWindowEx(
0,
@ -726,7 +726,7 @@ void GLimp_Init( void )
SetFocus(g_wv.hWnd);
WG_CheckHardwareGamma();
} else {
g_wv.hWnd_opengl = create_twin_window(glConfig.vidWidth, glConfig.vidHeight);
g_wv.hWnd_opengl = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, false);
}
if (!GLW_InitDriver(g_wv.hWnd_opengl)) {
@ -837,8 +837,10 @@ void vk_imp_init() {
SetForegroundWindow(g_wv.hWnd);
SetFocus(g_wv.hWnd);
WG_CheckHardwareGamma();
g_wv.hWnd_dx = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, true);
} else {
g_wv.hWnd_vulkan = create_twin_window(glConfig.vidWidth, glConfig.vidHeight);
g_wv.hWnd_vulkan = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, false);
}
}
@ -862,6 +864,16 @@ void vk_imp_shutdown() {
}
vkGetInstanceProcAddr = nullptr;
if (g_wv.hWnd_dx) {
ri.Printf(PRINT_ALL, "...destroying DX12 window\n");
DestroyWindow(g_wv.hWnd_dx);
if (g_wv.hWnd == g_wv.hWnd_dx) {
g_wv.hWnd_dx = NULL;
}
g_wv.hWnd_dx = NULL;
}
// For vulkan mode we still have qgl pointers initialized with placeholder values.
// Reset them the same way as we do in opengl mode.
QGL_Shutdown();

View File

@ -21,6 +21,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// win_local.h: Win32-specific Quake3 header file
#pragma once
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning(disable : 4201)
#pragma warning( push )
@ -77,6 +79,7 @@ typedef struct
HWND hWnd_opengl;
HWND hWnd_vulkan;
HWND hWnd_dx;
HINSTANCE hInstance;
qboolean activeApp;

2540
src/engine/renderer/d3dx12.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -201,6 +201,7 @@ static void InitRenderAPI( void )
if (r_renderAPI->integer != 0 || r_twinMode->integer) {
vk_imp_init();
vk_initialize();
dx_initialize();
}
}
@ -1117,6 +1118,8 @@ void RE_Shutdown( qboolean destroyWindow ) {
if (vk.active) {
vk_release_resources();
if (destroyWindow) {
dx_shutdown();
vk_shutdown();
vk_imp_shutdown();
}

View File

@ -822,7 +822,7 @@ void get_hardware_adapter(IDXGIFactory4* p_factory, IDXGIAdapter1** pp_adapter)
*pp_adapter = adapter.Detach();
}
void vk_initialize() {
void dx_initialize() {
#if defined(_DEBUG)
// Enable the D3D12 debug layer
{
@ -840,6 +840,66 @@ void vk_initialize() {
get_hardware_adapter(factory.Get(), &hardware_adapter);
DX_CHECK(D3D12CreateDevice(hardware_adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&vk.dx_device)));
// 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;
DX_CHECK(vk.dx_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&vk.dx_command_queue)));
// Describe and create the swap chain.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
swapChainDesc.BufferCount = D3D_FRAME_COUNT;
swapChainDesc.Width = glConfig.vidWidth;
swapChainDesc.Height = glConfig.vidHeight;
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;
DX_CHECK(factory->CreateSwapChainForHwnd(
vk.dx_command_queue, // Swap chain needs the queue so that it can force a flush on it.
g_wv.hWnd_dx,
&swapChainDesc,
nullptr,
nullptr,
&swapchain
));
// This sample does not support fullscreen transitions.
DX_CHECK(factory->MakeWindowAssociation(g_wv.hWnd_dx, DXGI_MWA_NO_ALT_ENTER));
DX_CHECK(swapchain.As(&vk.dx_swapchain));
// Create descriptor heaps.
{
// Describe and create a render target view (RTV) descriptor heap.
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
rtvHeapDesc.NumDescriptors = D3D_FRAME_COUNT;
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
DX_CHECK(vk.dx_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&vk.dx_rtv_heap)));
vk.dx_rtv_descriptor_size = vk.dx_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
}
// Create frame resources.
{
CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(vk.dx_rtv_heap->GetCPUDescriptorHandleForHeapStart());
// Create a RTV for each frame.
for (UINT n = 0; n < D3D_FRAME_COUNT; n++)
{
DX_CHECK(vk.dx_swapchain->GetBuffer(n, IID_PPV_ARGS(&vk.render_targets[n])));
vk.dx_device->CreateRenderTargetView(vk.render_targets[n].Get(), nullptr, rtv_handle);
rtv_handle.Offset(1, vk.dx_rtv_descriptor_size);
}
}
DX_CHECK(vk.dx_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&vk.dx_command_allocator)));
}
void vk_initialize() {
init_vulkan_library();
VkPhysicalDeviceFeatures features;
@ -1319,6 +1379,26 @@ void vk_initialize() {
vk.active = true;
}
void dx_shutdown() {
vk.dx_swapchain.Reset();
vk.dx_command_allocator->Release();
vk.dx_command_allocator = nullptr;
for (int i = 0; i < D3D_FRAME_COUNT; i++) {
vk.render_targets[i].Reset();
}
vk.dx_rtv_heap->Release();
vk.dx_rtv_heap = nullptr;
vk.dx_command_queue->Release();
vk.dx_command_queue = nullptr;
vk.dx_device->Release();
vk.dx_device = nullptr;
}
void vk_shutdown() {
vkDestroyImage(vk.device, vk.depth_image, nullptr);
vkFreeMemory(vk.device, vk.depth_image_memory, nullptr);

View File

@ -12,6 +12,8 @@
#include "D3d12SDKLayers.h"
#include "DXGI1_4.h"
#include "wrl.h"
#include "d3dx12.h"
#include "../../engine/platform/win_local.h"
using Microsoft::WRL::ComPtr;
@ -23,6 +25,8 @@ const int MAX_VK_IMAGES = 2048; // should be the same as MAX_DRAWIMAGES
const int IMAGE_CHUNK_SIZE = 32 * 1024 * 1024;
const int MAX_IMAGE_CHUNKS = 16;
const int D3D_FRAME_COUNT = 2;
#define VK_CHECK(function_call) { \
VkResult result = function_call; \
if (result < 0) \
@ -89,9 +93,13 @@ struct Vk_Image {
// After calling this function we get fully functional vulkan subsystem.
void vk_initialize();
void dx_initialize();
// Shutdown vulkan subsystem by releasing resources acquired by Vk_Instance.
void vk_shutdown();
void dx_shutdown();
// Releases vulkan resources allocated during program execution.
// This effectively puts vulkan subsystem into initial state (the state we have after vk_initialize call).
void vk_release_resources();
@ -121,7 +129,13 @@ void vk_read_pixels(byte* buffer); // screenshots
struct Vk_Instance {
bool active = false;
ComPtr<ID3D12Device> dx_device;
ID3D12Device* dx_device = nullptr;
ID3D12CommandQueue* dx_command_queue = nullptr;
ComPtr<IDXGISwapChain3> dx_swapchain;
ID3D12DescriptorHeap* dx_rtv_heap = nullptr;
UINT dx_rtv_descriptor_size = 0;
ComPtr<ID3D12Resource> render_targets[D3D_FRAME_COUNT];
ID3D12CommandAllocator* dx_command_allocator = nullptr;
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physical_device = VK_NULL_HANDLE;