Added D3D12 backend and demo
This commit is contained in:
parent
3e834293ad
commit
703d73aebf
9
demo/d3d12/build.bat
Normal file
9
demo/d3d12/build.bat
Normal file
@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
|
||||
rem This will use VS2015 for compiler... if you have vs 2015 and it is installed at this / the default path
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
|
||||
|
||||
fxc.exe /nologo /T vs_5_1 /E vs /O3 /Zpc /Ges /Fh nuklear_d3d12_vertex_shader.h /Vn nk_d3d12_vertex_shader /Qstrip_reflect /Qstrip_debug /Qstrip_priv nuklear_d3d12.hlsl
|
||||
fxc.exe /nologo /T ps_5_1 /E ps /O3 /Zpc /Ges /Fh nuklear_d3d12_pixel_shader.h /Vn nk_d3d12_pixel_shader /Qstrip_reflect /Qstrip_debug /Qstrip_priv /enable_unbounded_descriptor_tables nuklear_d3d12.hlsl
|
||||
|
||||
cl /D_CRT_SECURE_NO_DEPRECATE /nologo /W3 /O2 /fp:fast /Gm- /Fedemo.exe main.c user32.lib dxguid.lib dxgi.lib d3d12.lib /link /incremental:no
|
439
demo/d3d12/main.c
Normal file
439
demo/d3d12/main.c
Normal file
@ -0,0 +1,439 @@
|
||||
/* nuklear - 1.32.0 - public domain */
|
||||
#define COBJMACROS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <combaseapi.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3d12.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
|
||||
#define WINDOW_WIDTH 800
|
||||
#define WINDOW_HEIGHT 600
|
||||
#define USER_TEXTURES 6
|
||||
|
||||
#define MAX_VERTEX_BUFFER 512 * 1024
|
||||
#define MAX_INDEX_BUFFER 128 * 1024
|
||||
|
||||
#define NK_INCLUDE_FIXED_TYPES
|
||||
#define NK_INCLUDE_STANDARD_IO
|
||||
#define NK_INCLUDE_STANDARD_VARARGS
|
||||
#define NK_INCLUDE_DEFAULT_ALLOCATOR
|
||||
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
|
||||
#define NK_INCLUDE_FONT_BAKING
|
||||
#define NK_INCLUDE_DEFAULT_FONT
|
||||
#define NK_IMPLEMENTATION
|
||||
#define NK_D3D12_IMPLEMENTATION
|
||||
#include "../../nuklear.h"
|
||||
#include "nuklear_d3d12.h"
|
||||
|
||||
/* ===============================================================
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* ===============================================================*/
|
||||
/* This are some code examples to provide a small overview of what can be
|
||||
* done with this library. To try out an example uncomment the defines */
|
||||
/*#define INCLUDE_ALL */
|
||||
/*#define INCLUDE_STYLE */
|
||||
/*#define INCLUDE_CALCULATOR */
|
||||
/*#define INCLUDE_CANVAS */
|
||||
/*#define INCLUDE_OVERVIEW */
|
||||
/*#define INCLUDE_NODE_EDITOR */
|
||||
|
||||
#ifdef INCLUDE_ALL
|
||||
#define INCLUDE_STYLE
|
||||
#define INCLUDE_CALCULATOR
|
||||
#define INCLUDE_CANVAS
|
||||
#define INCLUDE_OVERVIEW
|
||||
#define INCLUDE_NODE_EDITOR
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_STYLE
|
||||
#include "../style.c"
|
||||
#endif
|
||||
#ifdef INCLUDE_CALCULATOR
|
||||
#include "../calculator.c"
|
||||
#endif
|
||||
#ifdef INCLUDE_CANVAS
|
||||
#include "../canvas.c"
|
||||
#endif
|
||||
#ifdef INCLUDE_OVERVIEW
|
||||
#include "../overview.c"
|
||||
#endif
|
||||
#ifdef INCLUDE_NODE_EDITOR
|
||||
#include "../node_editor.c"
|
||||
#endif
|
||||
|
||||
/* ===============================================================
|
||||
*
|
||||
* DEMO
|
||||
*
|
||||
* ===============================================================*/
|
||||
/* DXGI & Window related device objects */
|
||||
static IDXGIFactory2 *dxgi_factory;
|
||||
static IDXGISwapChain1 *swap_chain;
|
||||
static ID3D12DescriptorHeap *rtv_descriptor_heap;
|
||||
static D3D12_CPU_DESCRIPTOR_HANDLE rtv_handles[2];
|
||||
static ID3D12Resource *rtv_buffers[2];
|
||||
static UINT rtv_desc_increment;
|
||||
static UINT rtv_index;
|
||||
/* DirectX common device objects */
|
||||
static ID3D12Device *device;
|
||||
static ID3D12CommandQueue *command_queue;
|
||||
static ID3D12Fence *queue_fence;
|
||||
static UINT64 fence_value;
|
||||
static ID3D12CommandAllocator *command_allocator;
|
||||
static ID3D12GraphicsCommandList *command_list;
|
||||
|
||||
static void signal_and_wait()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
/* Signal fence when execution finishes */
|
||||
hr = ID3D12CommandQueue_Signal(command_queue, queue_fence, ++fence_value);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
/* Wait for queue to finish */
|
||||
while(ID3D12Fence_GetCompletedValue(queue_fence) != fence_value)
|
||||
{
|
||||
SwitchToThread(); /* Allow windows to do other work */
|
||||
}
|
||||
}
|
||||
|
||||
static void execute_commands()
|
||||
{
|
||||
/* Prepare command list for execution */
|
||||
ID3D12GraphicsCommandList_Close(command_list);
|
||||
|
||||
/* Execute on command queue */
|
||||
ID3D12CommandList* cmd_lists[] = { (ID3D12CommandList*)command_list};
|
||||
ID3D12CommandQueue_ExecuteCommandLists(command_queue, 1, cmd_lists);
|
||||
|
||||
/* Wait for execution */
|
||||
signal_and_wait();
|
||||
|
||||
/* Reset command allocator and list */
|
||||
ID3D12CommandAllocator_Reset(command_allocator);
|
||||
ID3D12GraphicsCommandList_Reset(command_list, command_allocator, NULL);
|
||||
}
|
||||
|
||||
static void get_swap_chain_buffers()
|
||||
{
|
||||
HRESULT hr;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_handle;
|
||||
|
||||
/* Get resource objects from swap chain */
|
||||
hr = IDXGISwapChain1_GetBuffer(swap_chain, 0, &IID_ID3D12Resource, &rtv_buffers[0]);
|
||||
assert(SUCCEEDED(hr));
|
||||
hr = IDXGISwapChain1_GetBuffer(swap_chain, 1, &IID_ID3D12Resource, &rtv_buffers[1]);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
/* Recreate render target views */
|
||||
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(rtv_descriptor_heap, &descriptor_handle);
|
||||
ID3D12Device_CreateRenderTargetView(device, rtv_buffers[0], NULL, descriptor_handle);
|
||||
rtv_handles[0] = descriptor_handle;
|
||||
descriptor_handle.ptr += rtv_desc_increment;
|
||||
ID3D12Device_CreateRenderTargetView(device, rtv_buffers[1], NULL, descriptor_handle);
|
||||
rtv_handles[1] = descriptor_handle;
|
||||
}
|
||||
|
||||
static void
|
||||
set_swap_chain_size(int width, int height)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
/* Wait for pending work */
|
||||
signal_and_wait();
|
||||
signal_and_wait(); /* Two times because we have two buffers in flight */
|
||||
|
||||
/* Release all open refereces to the buffers */
|
||||
ID3D12Resource_Release(rtv_buffers[0]);
|
||||
ID3D12Resource_Release(rtv_buffers[1]);
|
||||
|
||||
/* DXGI can now perform resizing */
|
||||
hr = IDXGISwapChain1_ResizeBuffers(swap_chain, 2, width, height, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
/* Get references for the new resized buffers */
|
||||
get_swap_chain_buffers();
|
||||
|
||||
/* Reset RTV index */
|
||||
rtv_index = 0;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
|
||||
case WM_SIZE:
|
||||
if (swap_chain)
|
||||
{
|
||||
int width = LOWORD(lparam);
|
||||
int height = HIWORD(lparam);
|
||||
set_swap_chain_size(width, height);
|
||||
nk_d3d12_resize(width, height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (nk_d3d12_handle_event(wnd, msg, wparam, lparam))
|
||||
return 0;
|
||||
|
||||
return DefWindowProcW(wnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct nk_context *ctx;
|
||||
struct nk_colorf bg;
|
||||
|
||||
WNDCLASSW wc;
|
||||
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
|
||||
DWORD style = WS_OVERLAPPEDWINDOW;
|
||||
DWORD exstyle = WS_EX_APPWINDOW;
|
||||
HWND wnd;
|
||||
int running = 1;
|
||||
HRESULT hr;
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC command_queue_desc;
|
||||
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc;
|
||||
D3D12_DESCRIPTOR_HEAP_DESC rtv_desc_heap_desc;
|
||||
|
||||
/* Win32 */
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
wc.style = CS_DBLCLKS;
|
||||
wc.lpfnWndProc = WindowProc;
|
||||
wc.hInstance = GetModuleHandleW(0);
|
||||
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.lpszClassName = L"NuklearWindowClass";
|
||||
RegisterClassW(&wc);
|
||||
|
||||
AdjustWindowRectEx(&rect, style, FALSE, exstyle);
|
||||
|
||||
wnd = CreateWindowExW(exstyle, wc.lpszClassName, L"Nuklear Demo",
|
||||
style | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
NULL, NULL, wc.hInstance, NULL);
|
||||
|
||||
/* D3D12 setup */
|
||||
/* Create default Device */
|
||||
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, &device);
|
||||
assert(SUCCEEDED(hr));
|
||||
/* Create a command queue */
|
||||
command_queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
command_queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
|
||||
command_queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
command_queue_desc.NodeMask = 0;
|
||||
hr = ID3D12Device_CreateCommandQueue(device, &command_queue_desc, &IID_ID3D12CommandQueue, &command_queue);
|
||||
assert(SUCCEEDED(hr));
|
||||
/* Create a fence for command queue executions */
|
||||
fence_value = 0;
|
||||
hr = ID3D12Device_CreateFence(device, fence_value, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, &queue_fence);
|
||||
assert(SUCCEEDED(hr));
|
||||
/* Create a command allocator */
|
||||
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, &command_allocator);
|
||||
assert(SUCCEEDED(hr));
|
||||
/* Create a command list that will use our allocator */
|
||||
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, command_allocator, NULL, &IID_ID3D12GraphicsCommandList1, &command_list);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
/* DXGI Setup (Swap chain & resources) */
|
||||
/* Create a descriptor heap for the back buffers */
|
||||
rtv_desc_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
rtv_desc_heap_desc.NumDescriptors = 2;
|
||||
rtv_desc_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
rtv_desc_heap_desc.NodeMask = 0;
|
||||
hr = ID3D12Device_CreateDescriptorHeap(device, &rtv_desc_heap_desc, &IID_ID3D12DescriptorHeap, &rtv_descriptor_heap);
|
||||
assert(SUCCEEDED(hr));
|
||||
/* Get descriptor increment */
|
||||
rtv_desc_increment = ID3D12Device_GetDescriptorHandleIncrementSize(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
/* Get the DXGI factory */
|
||||
hr = CreateDXGIFactory1(&IID_IDXGIFactory2, &dxgi_factory);
|
||||
assert(SUCCEEDED(hr));
|
||||
/* Create the swap chain */
|
||||
swap_chain_desc.Width = WINDOW_WIDTH;
|
||||
swap_chain_desc.Height = WINDOW_HEIGHT;
|
||||
swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swap_chain_desc.Stereo = 0;
|
||||
swap_chain_desc.SampleDesc.Count = 1;
|
||||
swap_chain_desc.SampleDesc.Quality = 0;
|
||||
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swap_chain_desc.BufferCount = 2;
|
||||
swap_chain_desc.Scaling = DXGI_SCALING_STRETCH;
|
||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ;
|
||||
swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||
swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgi_factory, (IUnknown*)command_queue, wnd, &swap_chain_desc, NULL, NULL, &swap_chain);
|
||||
assert(SUCCEEDED(hr));
|
||||
get_swap_chain_buffers();
|
||||
|
||||
/* GUI */
|
||||
ctx = nk_d3d12_init(device, WINDOW_WIDTH, WINDOW_HEIGHT, MAX_VERTEX_BUFFER, MAX_INDEX_BUFFER, USER_TEXTURES);
|
||||
|
||||
/* Load Fonts: if none of these are loaded a default font will be used */
|
||||
/* Load Cursor: if you uncomment cursor loading please hide the cursor */
|
||||
{
|
||||
struct nk_font_atlas *atlas;
|
||||
nk_d3d12_font_stash_begin(&atlas);
|
||||
/*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../extra_font/DroidSans.ttf", 14, 0);*/
|
||||
/*struct nk_font *robot = nk_font_atlas_add_from_file(atlas, "../../extra_font/Roboto-Regular.ttf", 14, 0);*/
|
||||
/*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../extra_font/kenvector_future_thin.ttf", 13, 0);*/
|
||||
/*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../extra_font/ProggyClean.ttf", 12, 0);*/
|
||||
/*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../extra_font/ProggyTiny.ttf", 10, 0);*/
|
||||
/*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../extra_font/Cousine-Regular.ttf", 13, 0);*/
|
||||
nk_d3d12_font_stash_end(command_list);
|
||||
/*nk_style_load_all_cursors(ctx, atlas->cursors);*/
|
||||
/*nk_style_set_font(ctx, &droid->handle)*/;
|
||||
}
|
||||
|
||||
/* Execute the command list to make sure all texture (font) data has been uploaded */
|
||||
execute_commands();
|
||||
/* Now we can cleanup all resources consumed by font stashing that are no longer used */
|
||||
nk_d3d12_font_stash_cleanup();
|
||||
|
||||
/* style.c */
|
||||
#ifdef INCLUDE_STYLE
|
||||
/*set_style(ctx, THEME_WHITE);*/
|
||||
/*set_style(ctx, THEME_RED);*/
|
||||
/*set_style(ctx, THEME_BLUE);*/
|
||||
/*set_style(ctx, THEME_DARK);*/
|
||||
#endif
|
||||
|
||||
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
|
||||
while (running)
|
||||
{
|
||||
/* Input */
|
||||
MSG msg;
|
||||
nk_input_begin(ctx);
|
||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
running = 0;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
nk_input_end(ctx);
|
||||
|
||||
/* GUI */
|
||||
if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
|
||||
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
|
||||
NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
|
||||
{
|
||||
enum {EASY, HARD};
|
||||
static int op = EASY;
|
||||
static int property = 20;
|
||||
|
||||
nk_layout_row_static(ctx, 30, 80, 1);
|
||||
if (nk_button_label(ctx, "button"))
|
||||
fprintf(stdout, "button pressed\n");
|
||||
nk_layout_row_dynamic(ctx, 30, 2);
|
||||
if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
|
||||
if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
|
||||
nk_layout_row_dynamic(ctx, 22, 1);
|
||||
nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
|
||||
|
||||
nk_layout_row_dynamic(ctx, 20, 1);
|
||||
nk_label(ctx, "background:", NK_TEXT_LEFT);
|
||||
nk_layout_row_dynamic(ctx, 25, 1);
|
||||
if (nk_combo_begin_color(ctx, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) {
|
||||
nk_layout_row_dynamic(ctx, 120, 1);
|
||||
bg = nk_color_picker(ctx, bg, NK_RGBA);
|
||||
nk_layout_row_dynamic(ctx, 25, 1);
|
||||
bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f);
|
||||
bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f);
|
||||
bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f);
|
||||
bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f);
|
||||
nk_combo_end(ctx);
|
||||
}
|
||||
}
|
||||
nk_end(ctx);
|
||||
|
||||
/* -------------- EXAMPLES ---------------- */
|
||||
#ifdef INCLUDE_CALCULATOR
|
||||
calculator(ctx);
|
||||
#endif
|
||||
#ifdef INCLUDE_CANVAS
|
||||
canvas(ctx);
|
||||
#endif
|
||||
#ifdef INCLUDE_OVERVIEW
|
||||
overview(ctx);
|
||||
#endif
|
||||
#ifdef INCLUDE_NODE_EDITOR
|
||||
node_editor(ctx);
|
||||
#endif
|
||||
/* ----------------------------------------- */
|
||||
|
||||
/* Set rtv resource state */
|
||||
D3D12_RESOURCE_BARRIER resource_barrier;
|
||||
resource_barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barrier.Transition.pResource = rtv_buffers[rtv_index];
|
||||
resource_barrier.Transition.Subresource = 0;
|
||||
resource_barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
resource_barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
resource_barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &resource_barrier);
|
||||
|
||||
/* Clear and set the rtv */
|
||||
ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv_handles[rtv_index], &bg.r, 0, NULL);
|
||||
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv_handles[rtv_index], FALSE, NULL);
|
||||
|
||||
/* Draw */
|
||||
nk_d3d12_render(command_list, NK_ANTI_ALIASING_ON);
|
||||
|
||||
/* Bring the rtv resource back to present state */
|
||||
resource_barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barrier.Transition.pResource = rtv_buffers[rtv_index];
|
||||
resource_barrier.Transition.Subresource = 0;
|
||||
resource_barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
resource_barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
resource_barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &resource_barrier);
|
||||
|
||||
/* Execute command list and wait */
|
||||
execute_commands();
|
||||
|
||||
/* Present frame */
|
||||
hr = IDXGISwapChain2_Present(swap_chain, 1, 0);
|
||||
rtv_index = (rtv_index + 1) % 2;
|
||||
if (hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DEVICE_REMOVED) {
|
||||
/* to recover from this, you'll need to recreate device and all the resources */
|
||||
MessageBoxW(NULL, L"D3D12 device is lost or removed!", L"Error", 0);
|
||||
break;
|
||||
} else if (hr == DXGI_STATUS_OCCLUDED) {
|
||||
/* window is not visible, so vsync won't work. Let's sleep a bit to reduce CPU usage */
|
||||
Sleep(10);
|
||||
}
|
||||
assert(SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
/* Nuklear shutdown */
|
||||
nk_d3d12_shutdown();
|
||||
|
||||
/* D3D12 and DXGI shutdown */
|
||||
signal_and_wait();
|
||||
signal_and_wait(); /* Two times because we have two buffers in flight */
|
||||
ID3D12Resource_Release(rtv_buffers[0]);
|
||||
ID3D12Resource_Release(rtv_buffers[1]);
|
||||
ID3D12DescriptorHeap_Release(rtv_descriptor_heap);
|
||||
IDXGISwapChain1_Release(swap_chain);
|
||||
IDXGIFactory2_Release(dxgi_factory);
|
||||
ID3D12GraphicsCommandList_Release(command_list);
|
||||
ID3D12CommandAllocator_Release(command_allocator);
|
||||
ID3D12CommandQueue_Release(command_queue);
|
||||
ID3D12Fence_Release(queue_fence);
|
||||
ID3D12Device_Release(device);
|
||||
|
||||
/* win32 shutdown */
|
||||
UnregisterClassW(wc.lpszClassName, wc.hInstance);
|
||||
|
||||
return 0;
|
||||
}
|
882
demo/d3d12/nuklear_d3d12.h
Normal file
882
demo/d3d12/nuklear_d3d12.h
Normal file
@ -0,0 +1,882 @@
|
||||
/*
|
||||
* Nuklear - 1.32.0 - public domain
|
||||
* no warrenty implied; use at your own risk.
|
||||
* authored from 2015-2016 by Micha Mettke
|
||||
*
|
||||
* D3D12 backend created by Ludwig Fuechsl (2022)
|
||||
*/
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* API
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#ifndef NK_D3D12_H_
|
||||
#define NK_D3D12_H_
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
NK_API struct nk_context *nk_d3d12_init(ID3D12Device *device, int width, int height, unsigned int max_vertex_buffer, unsigned int max_index_buffer, unsigned int max_user_textures);
|
||||
NK_API void nk_d3d12_font_stash_begin(struct nk_font_atlas **atlas);
|
||||
NK_API void nk_d3d12_font_stash_end(ID3D12GraphicsCommandList *command_list);
|
||||
NK_API void nk_d3d12_font_stash_cleanup();
|
||||
NK_API nk_bool nk_d3d12_set_user_texture(unsigned int index, ID3D12Resource* texture, const D3D12_SHADER_RESOURCE_VIEW_DESC* description, nk_handle* handle_out);
|
||||
NK_API int nk_d3d12_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
NK_API void nk_d3d12_render(ID3D12GraphicsCommandList *command_list, enum nk_anti_aliasing AA);
|
||||
NK_API void nk_d3d12_resize(int width, int height);
|
||||
NK_API void nk_d3d12_shutdown(void);
|
||||
|
||||
#endif
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* IMPLEMENTATION
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#ifdef NK_D3D12_IMPLEMENTATION
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define COBJMACROS
|
||||
#include <d3d12.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nuklear_d3d12_vertex_shader.h"
|
||||
#include "nuklear_d3d12_pixel_shader.h"
|
||||
|
||||
struct nk_d3d12_vertex
|
||||
{
|
||||
float position[2];
|
||||
float uv[2];
|
||||
nk_byte col[4];
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
struct nk_context ctx;
|
||||
struct nk_font_atlas atlas;
|
||||
struct nk_buffer cmds;
|
||||
|
||||
struct nk_draw_null_texture null;
|
||||
unsigned int max_vertex_buffer;
|
||||
unsigned int max_index_buffer;
|
||||
unsigned int max_user_textures;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heap_prop_default;
|
||||
D3D12_HEAP_PROPERTIES heap_prop_upload;
|
||||
|
||||
UINT cbv_srv_uav_desc_increment;
|
||||
|
||||
D3D12_VIEWPORT viewport;
|
||||
ID3D12Device *device;
|
||||
ID3D12RootSignature *root_signature;
|
||||
ID3D12PipelineState *pipeline_state;
|
||||
ID3D12DescriptorHeap *desc_heap;
|
||||
ID3D12Resource *font_texture;
|
||||
ID3D12Resource *font_upload_buffer;
|
||||
ID3D12Resource *upload_buffer;
|
||||
ID3D12Resource *const_buffer;
|
||||
ID3D12Resource *index_buffer;
|
||||
ID3D12Resource *vertex_buffer;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cpu_descriptor_handle;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_descriptor_handle;
|
||||
D3D12_GPU_VIRTUAL_ADDRESS gpu_vertex_buffer_address;
|
||||
D3D12_GPU_VIRTUAL_ADDRESS gpu_index_buffer_address;
|
||||
} d3d12;
|
||||
|
||||
NK_API void
|
||||
nk_d3d12_render(ID3D12GraphicsCommandList *command_list, enum nk_anti_aliasing AA)
|
||||
{
|
||||
HRESULT hr;
|
||||
#ifdef NK_UINT_DRAW_INDEX
|
||||
DXGI_FORMAT index_buffer_format = DXGI_FORMAT_R32_UINT;
|
||||
#else
|
||||
DXGI_FORMAT index_buffer_format = DXGI_FORMAT_R16_UINT;
|
||||
#endif
|
||||
const UINT stride = sizeof(struct nk_d3d12_vertex);
|
||||
const struct nk_draw_command *cmd;
|
||||
UINT offset = 0;
|
||||
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view;
|
||||
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
|
||||
unsigned char* ptr_data;
|
||||
D3D12_RANGE map_range;
|
||||
D3D12_RESOURCE_BARRIER resource_barriers[3];
|
||||
|
||||
/* Activate D3D12 pipeline state and config root signature */
|
||||
ID3D12GraphicsCommandList_SetPipelineState(command_list, d3d12.pipeline_state);
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, d3d12.root_signature);
|
||||
ID3D12GraphicsCommandList_SetDescriptorHeaps(command_list, 1, &d3d12.desc_heap);
|
||||
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, 0, d3d12.gpu_descriptor_handle);
|
||||
|
||||
/* Configure rendering pipeline */
|
||||
ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
vertex_buffer_view.BufferLocation = d3d12.gpu_vertex_buffer_address;
|
||||
vertex_buffer_view.SizeInBytes = d3d12.max_vertex_buffer;
|
||||
vertex_buffer_view.StrideInBytes = stride;
|
||||
ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vertex_buffer_view);
|
||||
index_buffer_view.BufferLocation = d3d12.gpu_index_buffer_address;
|
||||
index_buffer_view.Format = index_buffer_format;
|
||||
index_buffer_view.SizeInBytes = d3d12.max_index_buffer;
|
||||
ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, &index_buffer_view);
|
||||
ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &d3d12.viewport);
|
||||
|
||||
/* Map upload buffer to cpu accessible pointer */
|
||||
map_range.Begin = sizeof(float) * 4 * 4;
|
||||
map_range.End = map_range.Begin + d3d12.max_vertex_buffer + d3d12.max_index_buffer;
|
||||
hr = ID3D12Resource_Map(d3d12.upload_buffer, 0, &map_range, &ptr_data);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
/* Nuklear convert and copy to upload buffer */
|
||||
{
|
||||
struct nk_convert_config config;
|
||||
NK_STORAGE const struct nk_draw_vertex_layout_element vertex_layout[] = {
|
||||
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d12_vertex, position)},
|
||||
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d12_vertex, uv)},
|
||||
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_d3d12_vertex, col)},
|
||||
{NK_VERTEX_LAYOUT_END}
|
||||
};
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.vertex_layout = vertex_layout;
|
||||
config.vertex_size = sizeof(struct nk_d3d12_vertex);
|
||||
config.vertex_alignment = NK_ALIGNOF(struct nk_d3d12_vertex);
|
||||
config.global_alpha = 1.0f;
|
||||
config.shape_AA = AA;
|
||||
config.line_AA = AA;
|
||||
config.circle_segment_count = 22;
|
||||
config.curve_segment_count = 22;
|
||||
config.arc_segment_count = 22;
|
||||
config.null = d3d12.null;
|
||||
|
||||
struct nk_buffer vbuf, ibuf;
|
||||
nk_buffer_init_fixed(&vbuf, &ptr_data[sizeof(float) * 4 * 4], (size_t)d3d12.max_vertex_buffer);
|
||||
nk_buffer_init_fixed(&ibuf, &ptr_data[sizeof(float) * 4 * 4 + d3d12.max_vertex_buffer], (size_t)d3d12.max_index_buffer);
|
||||
nk_convert(&d3d12.ctx, &d3d12.cmds, &vbuf, &ibuf, &config);
|
||||
}
|
||||
|
||||
/* Close mapping range */
|
||||
ID3D12Resource_Unmap(d3d12.upload_buffer, 0, &map_range);
|
||||
|
||||
/* Issue GPU resource change for copying */
|
||||
resource_barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barriers[0].Transition.pResource = d3d12.const_buffer;
|
||||
resource_barriers[0].Transition.Subresource = 0;
|
||||
resource_barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
||||
resource_barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
resource_barriers[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
resource_barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barriers[1].Transition.pResource = d3d12.vertex_buffer;
|
||||
resource_barriers[1].Transition.Subresource = 0;
|
||||
resource_barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
||||
resource_barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
resource_barriers[1].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
resource_barriers[2].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barriers[2].Transition.pResource = d3d12.index_buffer;
|
||||
resource_barriers[2].Transition.Subresource = 0;
|
||||
resource_barriers[2].Transition.StateBefore = D3D12_RESOURCE_STATE_INDEX_BUFFER;
|
||||
resource_barriers[2].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
resource_barriers[2].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 3, resource_barriers);
|
||||
|
||||
/* Copy from upload buffer to gpu buffers */
|
||||
ID3D12GraphicsCommandList_CopyBufferRegion(command_list, d3d12.const_buffer, 0, d3d12.upload_buffer, 0, sizeof(float) * 4 * 4);
|
||||
ID3D12GraphicsCommandList_CopyBufferRegion(command_list, d3d12.vertex_buffer, 0, d3d12.upload_buffer, sizeof(float) * 4 * 4, d3d12.max_vertex_buffer);
|
||||
ID3D12GraphicsCommandList_CopyBufferRegion(command_list, d3d12.index_buffer, 0, d3d12.upload_buffer, sizeof(float) * 4 * 4 + d3d12.max_vertex_buffer, d3d12.max_index_buffer);
|
||||
|
||||
/* Issue GPU resource change for rendering */
|
||||
resource_barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barriers[0].Transition.pResource = d3d12.const_buffer;
|
||||
resource_barriers[0].Transition.Subresource = 0;
|
||||
resource_barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
resource_barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
||||
resource_barriers[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
resource_barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barriers[1].Transition.pResource = d3d12.vertex_buffer;
|
||||
resource_barriers[1].Transition.Subresource = 0;
|
||||
resource_barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
resource_barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
||||
resource_barriers[1].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
resource_barriers[2].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barriers[2].Transition.pResource = d3d12.index_buffer;
|
||||
resource_barriers[2].Transition.Subresource = 0;
|
||||
resource_barriers[2].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
resource_barriers[2].Transition.StateAfter = D3D12_RESOURCE_STATE_INDEX_BUFFER;
|
||||
resource_barriers[2].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 3, resource_barriers);
|
||||
|
||||
/* Issue draw commands */
|
||||
nk_draw_foreach(cmd, &d3d12.ctx, &d3d12.cmds)
|
||||
{
|
||||
D3D12_RECT scissor;
|
||||
UINT32 texture_id;
|
||||
|
||||
/* Only place a drawcall in case the command contains drawable data */
|
||||
if(cmd->elem_count)
|
||||
{
|
||||
/* Setup scissor rect */
|
||||
scissor.left = (LONG)cmd->clip_rect.x;
|
||||
scissor.right = (LONG)(cmd->clip_rect.x + cmd->clip_rect.w);
|
||||
scissor.top = (LONG)cmd->clip_rect.y;
|
||||
scissor.bottom = (LONG)(cmd->clip_rect.y + cmd->clip_rect.h);
|
||||
ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &scissor);
|
||||
|
||||
/* Setup texture (index to descriptor heap table) to use for draw call */
|
||||
texture_id = (UINT32)cmd->texture.id;
|
||||
ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 1, 1, &texture_id, 0);
|
||||
|
||||
/* Dispatch draw call */
|
||||
ID3D12GraphicsCommandList_DrawIndexedInstanced(command_list, (UINT)cmd->elem_count, 1, offset, 0, 0);
|
||||
offset += cmd->elem_count;
|
||||
}
|
||||
}
|
||||
|
||||
/* Default nuklear context and command buffer clear */
|
||||
nk_clear(&d3d12.ctx);
|
||||
nk_buffer_clear(&d3d12.cmds);
|
||||
}
|
||||
|
||||
static void
|
||||
nk_d3d12_get_projection_matrix(int width, int height, float *result)
|
||||
{
|
||||
const float L = 0.0f;
|
||||
const float R = (float)width;
|
||||
const float T = 0.0f;
|
||||
const float B = (float)height;
|
||||
float matrix[4][4] =
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.5f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.5f, 1.0f },
|
||||
};
|
||||
matrix[0][0] = 2.0f / (R - L);
|
||||
matrix[1][1] = 2.0f / (T - B);
|
||||
matrix[3][0] = (R + L) / (L - R);
|
||||
matrix[3][1] = (T + B) / (B - T);
|
||||
memcpy(result, matrix, sizeof(matrix));
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_d3d12_resize(int width, int height)
|
||||
{
|
||||
D3D12_RANGE map_range;
|
||||
void* ptr_data;
|
||||
|
||||
/* Describe area to be mapped (the upload buffer region where the constant buffer / projection matrix) lives */
|
||||
map_range.Begin = 0;
|
||||
map_range.End = sizeof(float) * 4 * 4;
|
||||
|
||||
/* Map area to cpu accassible pointer (from upload buffer) */
|
||||
if (SUCCEEDED(ID3D12Resource_Map(d3d12.upload_buffer, 0, &map_range, &ptr_data)))
|
||||
{
|
||||
/* Compute projection matrix into upload buffer */
|
||||
nk_d3d12_get_projection_matrix(width, height, (float*)ptr_data);
|
||||
ID3D12Resource_Unmap(d3d12.upload_buffer, 0, &map_range);
|
||||
|
||||
/* Update internal viewport state to relect resize changes */
|
||||
d3d12.viewport.Width = (float)width;
|
||||
d3d12.viewport.Height = (float)height;
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE:
|
||||
When mapping and copying succeeds, the data will still be in CPU sided memory
|
||||
copying to the GPU is done in the nk_d3d12_render function
|
||||
*/
|
||||
}
|
||||
|
||||
NK_API int
|
||||
nk_d3d12_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
{
|
||||
int down = !((lparam >> 31) & 1);
|
||||
int ctrl = GetKeyState(VK_CONTROL) & (1 << 15);
|
||||
|
||||
switch (wparam)
|
||||
{
|
||||
case VK_SHIFT:
|
||||
case VK_LSHIFT:
|
||||
case VK_RSHIFT:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_SHIFT, down);
|
||||
return 1;
|
||||
|
||||
case VK_DELETE:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_DEL, down);
|
||||
return 1;
|
||||
|
||||
case VK_RETURN:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_ENTER, down);
|
||||
return 1;
|
||||
|
||||
case VK_TAB:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_TAB, down);
|
||||
return 1;
|
||||
|
||||
case VK_LEFT:
|
||||
if (ctrl)
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_WORD_LEFT, down);
|
||||
else
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_LEFT, down);
|
||||
return 1;
|
||||
|
||||
case VK_RIGHT:
|
||||
if (ctrl)
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_WORD_RIGHT, down);
|
||||
else
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_RIGHT, down);
|
||||
return 1;
|
||||
|
||||
case VK_BACK:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_BACKSPACE, down);
|
||||
return 1;
|
||||
|
||||
case VK_HOME:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_START, down);
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_SCROLL_START, down);
|
||||
return 1;
|
||||
|
||||
case VK_END:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_END, down);
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_SCROLL_END, down);
|
||||
return 1;
|
||||
|
||||
case VK_NEXT:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_SCROLL_DOWN, down);
|
||||
return 1;
|
||||
|
||||
case VK_PRIOR:
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_SCROLL_UP, down);
|
||||
return 1;
|
||||
|
||||
case 'C':
|
||||
if (ctrl) {
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_COPY, down);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
if (ctrl) {
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_PASTE, down);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
if (ctrl) {
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_CUT, down);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
if (ctrl) {
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_UNDO, down);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
if (ctrl) {
|
||||
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_REDO, down);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_CHAR:
|
||||
if (wparam >= 32)
|
||||
{
|
||||
nk_input_unicode(&d3d12.ctx, (nk_rune)wparam);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
nk_input_button(&d3d12.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
|
||||
SetCapture(wnd);
|
||||
return 1;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
nk_input_button(&d3d12.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
|
||||
nk_input_button(&d3d12.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
|
||||
ReleaseCapture();
|
||||
return 1;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
nk_input_button(&d3d12.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
|
||||
SetCapture(wnd);
|
||||
return 1;
|
||||
|
||||
case WM_RBUTTONUP:
|
||||
nk_input_button(&d3d12.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
|
||||
ReleaseCapture();
|
||||
return 1;
|
||||
|
||||
case WM_MBUTTONDOWN:
|
||||
nk_input_button(&d3d12.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
|
||||
SetCapture(wnd);
|
||||
return 1;
|
||||
|
||||
case WM_MBUTTONUP:
|
||||
nk_input_button(&d3d12.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
|
||||
ReleaseCapture();
|
||||
return 1;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
nk_input_scroll(&d3d12.ctx, nk_vec2(0,(float)(short)HIWORD(wparam) / WHEEL_DELTA));
|
||||
return 1;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
nk_input_motion(&d3d12.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam));
|
||||
return 1;
|
||||
|
||||
case WM_LBUTTONDBLCLK:
|
||||
nk_input_button(&d3d12.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nk_d3d12_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
|
||||
{
|
||||
(void)usr;
|
||||
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
|
||||
{
|
||||
HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
|
||||
if (mem)
|
||||
{
|
||||
SIZE_T size = GlobalSize(mem) - 1;
|
||||
if (size)
|
||||
{
|
||||
LPCWSTR wstr = (LPCWSTR)GlobalLock(mem);
|
||||
if (wstr)
|
||||
{
|
||||
int utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, size / sizeof(wchar_t), NULL, 0, NULL, NULL);
|
||||
if (utf8size)
|
||||
{
|
||||
char* utf8 = (char*)malloc(utf8size);
|
||||
if (utf8)
|
||||
{
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, size / sizeof(wchar_t), utf8, utf8size, NULL, NULL);
|
||||
nk_textedit_paste(edit, utf8, utf8size);
|
||||
free(utf8);
|
||||
}
|
||||
}
|
||||
GlobalUnlock(mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nk_d3d12_clipboard_copy(nk_handle usr, const char *text, int len)
|
||||
{
|
||||
(void)usr;
|
||||
if (OpenClipboard(NULL))
|
||||
{
|
||||
int wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
|
||||
if (wsize)
|
||||
{
|
||||
HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t));
|
||||
if (mem)
|
||||
{
|
||||
wchar_t* wstr = (wchar_t*)GlobalLock(mem);
|
||||
if (wstr)
|
||||
{
|
||||
MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
|
||||
wstr[wsize] = 0;
|
||||
GlobalUnlock(mem);
|
||||
SetClipboardData(CF_UNICODETEXT, mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
NK_API struct nk_context*
|
||||
nk_d3d12_init(ID3D12Device *device, int width, int height, unsigned int max_vertex_buffer, unsigned int max_index_buffer, unsigned int max_user_textures)
|
||||
{
|
||||
HRESULT hr;
|
||||
D3D12_CONSTANT_BUFFER_VIEW_DESC cbv;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cbv_handle;
|
||||
|
||||
/* Do plain object / ref copys */
|
||||
d3d12.max_vertex_buffer = max_vertex_buffer;
|
||||
d3d12.max_index_buffer = max_index_buffer;
|
||||
d3d12.max_user_textures = max_user_textures;
|
||||
d3d12.device = device;
|
||||
ID3D12Device_AddRef(device);
|
||||
d3d12.font_texture = NULL;
|
||||
d3d12.font_upload_buffer = NULL;
|
||||
|
||||
/* Init nuklear context */
|
||||
nk_init_default(&d3d12.ctx, 0);
|
||||
d3d12.ctx.clip.copy = nk_d3d12_clipboard_copy;
|
||||
d3d12.ctx.clip.paste = nk_d3d12_clipboard_paste;
|
||||
d3d12.ctx.clip.userdata = nk_handle_ptr(0);
|
||||
|
||||
/* Init nuklear buffer */
|
||||
nk_buffer_init_default(&d3d12.cmds);
|
||||
|
||||
/* Define Heap properties */
|
||||
d3d12.heap_prop_default.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
d3d12.heap_prop_default.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
d3d12.heap_prop_default.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
d3d12.heap_prop_default.CreationNodeMask = 0;
|
||||
d3d12.heap_prop_default.VisibleNodeMask = 0;
|
||||
d3d12.heap_prop_upload.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
d3d12.heap_prop_upload.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
d3d12.heap_prop_upload.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
d3d12.heap_prop_upload.CreationNodeMask = 0;
|
||||
d3d12.heap_prop_upload.VisibleNodeMask = 0;
|
||||
|
||||
/* Create data objects */
|
||||
/* Create upload buffer */
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Width = (sizeof(float) * 4 * 4) + max_vertex_buffer + max_index_buffer; /* Needs to hold matrix + vertices + indicies */
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
hr = ID3D12Device_CreateCommittedResource(device, &d3d12.heap_prop_upload, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_SOURCE, NULL, &IID_ID3D12Resource, &d3d12.upload_buffer);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
/* Create constant buffer */
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Width = 256; /* Should be sizeof(float) * 4 * 4 - but this does not match how d3d12 works (min CBV size of 256) */
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
hr = ID3D12Device_CreateCommittedResource(device, &d3d12.heap_prop_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, &d3d12.const_buffer);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
/* Create vertex buffer */
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Width = max_vertex_buffer;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
hr = ID3D12Device_CreateCommittedResource(device, &d3d12.heap_prop_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, &d3d12.vertex_buffer);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
/* Create index buffer */
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Width = max_index_buffer;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
hr = ID3D12Device_CreateCommittedResource(device, &d3d12.heap_prop_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, &d3d12.index_buffer);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
/* Create descriptor heap for shader root signature */
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc;
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
desc.NumDescriptors = 2 + max_user_textures;
|
||||
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
desc.NodeMask = 0;
|
||||
ID3D12Device_CreateDescriptorHeap(device, &desc, &IID_ID3D12DescriptorHeap, &d3d12.desc_heap);
|
||||
}
|
||||
|
||||
/* Get address of first handle (CPU and GPU) */
|
||||
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(d3d12.desc_heap, &d3d12.cpu_descriptor_handle);
|
||||
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(d3d12.desc_heap, &d3d12.gpu_descriptor_handle);
|
||||
|
||||
/* Get addresses of vertex & index buffers */
|
||||
d3d12.gpu_vertex_buffer_address = ID3D12Resource_GetGPUVirtualAddress(d3d12.vertex_buffer);
|
||||
d3d12.gpu_index_buffer_address = ID3D12Resource_GetGPUVirtualAddress(d3d12.index_buffer);
|
||||
|
||||
/* Get handle increment */
|
||||
d3d12.cbv_srv_uav_desc_increment = ID3D12Device_GetDescriptorHandleIncrementSize(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
|
||||
/* Create view to constant buffer */
|
||||
cbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(d3d12.const_buffer);
|
||||
cbv.SizeInBytes = 256;
|
||||
cbv_handle = d3d12.cpu_descriptor_handle;
|
||||
ID3D12Device_CreateConstantBufferView(device, &cbv, cbv_handle);
|
||||
|
||||
/* Create root signature */
|
||||
hr = ID3D12Device_CreateRootSignature(device, 0, nk_d3d12_vertex_shader, sizeof(nk_d3d12_vertex_shader), &IID_ID3D12RootSignature, &d3d12.root_signature);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
/* Create pipeline state */
|
||||
{
|
||||
/* Describe input layout */
|
||||
const D3D12_INPUT_ELEMENT_DESC layout[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, NK_OFFSETOF(struct nk_d3d12_vertex, position), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, NK_OFFSETOF(struct nk_d3d12_vertex, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, NK_OFFSETOF(struct nk_d3d12_vertex, col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
/* Describe pipeline state */
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.pRootSignature = d3d12.root_signature;
|
||||
desc.VS.pShaderBytecode = nk_d3d12_vertex_shader;
|
||||
desc.VS.BytecodeLength = sizeof(nk_d3d12_vertex_shader);
|
||||
desc.PS.pShaderBytecode = nk_d3d12_pixel_shader;
|
||||
desc.PS.BytecodeLength = sizeof(nk_d3d12_pixel_shader);
|
||||
desc.BlendState.RenderTarget[0].BlendEnable = TRUE;
|
||||
desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||
desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
desc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||
desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
|
||||
desc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
desc.SampleMask = UINT_MAX;
|
||||
desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
desc.RasterizerState.CullMode= D3D12_CULL_MODE_NONE;
|
||||
desc.RasterizerState.DepthClipEnable = TRUE;
|
||||
desc.InputLayout.NumElements = _countof(layout);
|
||||
desc.InputLayout.pInputElementDescs = layout;
|
||||
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
desc.NumRenderTargets = 1;
|
||||
desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; /* NOTE: When using HDR rendering you might have a different framebuffer format */
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.NodeMask = 0;
|
||||
|
||||
/* Create PSO */
|
||||
hr = ID3D12Device_CreateGraphicsPipelineState(device, &desc, &IID_ID3D12PipelineState, &d3d12.pipeline_state);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
/* First time const buffer init */
|
||||
nk_d3d12_resize(width, height);
|
||||
|
||||
/* viewport */
|
||||
d3d12.viewport.TopLeftX = 0.0f;
|
||||
d3d12.viewport.TopLeftY = 0.0f;
|
||||
d3d12.viewport.Width = (float)width;
|
||||
d3d12.viewport.Height = (float)height;
|
||||
d3d12.viewport.MinDepth = 0.0f;
|
||||
d3d12.viewport.MaxDepth = 1.0f;
|
||||
|
||||
return &d3d12.ctx;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_d3d12_font_stash_begin(struct nk_font_atlas **atlas)
|
||||
{
|
||||
/* Default nuklear font stash */
|
||||
nk_font_atlas_init_default(&d3d12.atlas);
|
||||
nk_font_atlas_begin(&d3d12.atlas);
|
||||
*atlas = &d3d12.atlas;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_d3d12_font_stash_end(ID3D12GraphicsCommandList *command_list)
|
||||
{
|
||||
HRESULT hr;
|
||||
D3D12_TEXTURE_COPY_LOCATION cpy_src, cpy_dest;
|
||||
D3D12_BOX cpy_box;
|
||||
D3D12_RESOURCE_BARRIER resource_barrier;
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srv_handle;
|
||||
const void *image;
|
||||
void* ptr_data;
|
||||
int w, h;
|
||||
|
||||
/* Bake nuklear font atlas */
|
||||
image = nk_font_atlas_bake(&d3d12.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
|
||||
NK_ASSERT(image);
|
||||
|
||||
/* Create font texture */
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Width = w;
|
||||
desc.Height = h;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
hr = ID3D12Device_CreateCommittedResource(d3d12.device, &d3d12.heap_prop_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, NULL, &IID_ID3D12Resource, &d3d12.font_texture);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
/* Create font upload buffer */
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||
desc.Width = w * h * 4;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
hr = ID3D12Device_CreateCommittedResource(d3d12.device, &d3d12.heap_prop_upload, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_SOURCE, NULL, &IID_ID3D12Resource, &d3d12.font_upload_buffer);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
/* Copy image data to upload buffer */
|
||||
hr = ID3D12Resource_Map(d3d12.font_upload_buffer, 0, NULL, &ptr_data);
|
||||
NK_ASSERT(SUCCEEDED(hr));
|
||||
memcpy(ptr_data, image, w * h * 4);
|
||||
ID3D12Resource_Unmap(d3d12.font_upload_buffer, 0, NULL);
|
||||
|
||||
/* Execute copy operation */
|
||||
cpy_src.pResource = d3d12.font_upload_buffer;
|
||||
cpy_src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
cpy_src.PlacedFootprint.Offset = 0;
|
||||
cpy_src.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
cpy_src.PlacedFootprint.Footprint.Width = w;
|
||||
cpy_src.PlacedFootprint.Footprint.Height = h;
|
||||
cpy_src.PlacedFootprint.Footprint.Depth = 1;
|
||||
cpy_src.PlacedFootprint.Footprint.RowPitch = w * 4;
|
||||
cpy_dest.pResource = d3d12.font_texture;
|
||||
cpy_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
cpy_dest.SubresourceIndex = 0;
|
||||
cpy_box.top = 0;
|
||||
cpy_box.left = 0;
|
||||
cpy_box.back = 1;
|
||||
cpy_box.bottom = h;
|
||||
cpy_box.right = w;
|
||||
cpy_box.front = 0;
|
||||
ID3D12GraphicsCommandList_CopyTextureRegion(command_list, &cpy_dest, 0, 0, 0, &cpy_src, &cpy_box);
|
||||
|
||||
/* Bring texture in the right state for rendering */
|
||||
resource_barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resource_barrier.Transition.pResource = d3d12.font_texture;
|
||||
resource_barrier.Transition.Subresource = 0;
|
||||
resource_barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
resource_barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
resource_barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &resource_barrier);
|
||||
|
||||
/* Create the SRV for the font texture */
|
||||
srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
srv_desc.Texture2D.MipLevels = 1;
|
||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
srv_desc.Texture2D.PlaneSlice = 0;
|
||||
srv_desc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
srv_handle.ptr = d3d12.cpu_descriptor_handle.ptr + d3d12.cbv_srv_uav_desc_increment;
|
||||
ID3D12Device_CreateShaderResourceView(d3d12.device, d3d12.font_texture, &srv_desc, srv_handle);
|
||||
|
||||
/* Done with nk atlas data. Atlas will be served with texture id 0 */
|
||||
nk_font_atlas_end(&d3d12.atlas, nk_handle_id(0), &d3d12.null);
|
||||
|
||||
/* Setup default font */
|
||||
if (d3d12.atlas.default_font)
|
||||
nk_style_set_font(&d3d12.ctx, &d3d12.atlas.default_font->handle);
|
||||
}
|
||||
|
||||
NK_API
|
||||
void nk_d3d12_font_stash_cleanup()
|
||||
{
|
||||
if(d3d12.font_upload_buffer)
|
||||
{
|
||||
ID3D12Resource_Release(d3d12.font_upload_buffer);
|
||||
d3d12.font_upload_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
NK_API
|
||||
nk_bool nk_d3d12_set_user_texture(unsigned int index, ID3D12Resource* texture, const D3D12_SHADER_RESOURCE_VIEW_DESC* description, nk_handle* handle_out)
|
||||
{
|
||||
nk_bool result = nk_false;
|
||||
if(index < d3d12.max_user_textures)
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srv_handle;
|
||||
|
||||
/* Get handle to texture (0 - Const Buffer; 1 - Font Texture; 2 - First user texture) */
|
||||
srv_handle.ptr = d3d12.cpu_descriptor_handle.ptr + ((2 + index) * d3d12.cbv_srv_uav_desc_increment);
|
||||
|
||||
/* Create SRV */
|
||||
ID3D12Device_CreateShaderResourceView(d3d12.device, texture, description, srv_handle);
|
||||
|
||||
/* Set nk handle (0 - Font Texture; 1 - First user texture) */
|
||||
*handle_out = nk_handle_id(1 + index);
|
||||
result = nk_true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NK_API
|
||||
void nk_d3d12_shutdown(void)
|
||||
{
|
||||
/* Nuklear cleanup */
|
||||
nk_font_atlas_clear(&d3d12.atlas);
|
||||
nk_buffer_free(&d3d12.cmds);
|
||||
nk_free(&d3d12.ctx);
|
||||
|
||||
/* DirectX 12 cleanup */
|
||||
ID3D12Device_Release(d3d12.device);
|
||||
ID3D12PipelineState_Release(d3d12.pipeline_state);
|
||||
ID3D12RootSignature_Release(d3d12.root_signature);
|
||||
ID3D12DescriptorHeap_Release(d3d12.desc_heap);
|
||||
ID3D12Resource_Release(d3d12.upload_buffer);
|
||||
ID3D12Resource_Release(d3d12.const_buffer);
|
||||
ID3D12Resource_Release(d3d12.index_buffer);
|
||||
ID3D12Resource_Release(d3d12.vertex_buffer);
|
||||
if(d3d12.font_texture)
|
||||
ID3D12Resource_Release(d3d12.font_texture);
|
||||
if(d3d12.font_upload_buffer)
|
||||
ID3D12Resource_Release(d3d12.font_upload_buffer);
|
||||
}
|
||||
|
||||
#endif
|
53
demo/d3d12/nuklear_d3d12.hlsl
Normal file
53
demo/d3d12/nuklear_d3d12.hlsl
Normal file
@ -0,0 +1,53 @@
|
||||
#define NK_ROOTSIGNATURE ""\
|
||||
"RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),"\
|
||||
"DescriptorTable("\
|
||||
"CBV(b0, numDescriptors = 1, flags = DATA_VOLATILE),"\
|
||||
"SRV(t0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)"\
|
||||
"),"\
|
||||
"RootConstants(num32BitConstants = 1, b1),"\
|
||||
"StaticSampler(s0, "\
|
||||
"filter = FILTER_MIN_MAG_MIP_LINEAR,"\
|
||||
"addressU = TEXTURE_ADDRESS_CLAMP,"\
|
||||
"addressV = TEXTURE_ADDRESS_CLAMP,"\
|
||||
"addressW = TEXTURE_ADDRESS_CLAMP,"\
|
||||
"comparisonFunc = COMPARISON_ALWAYS"\
|
||||
")"
|
||||
|
||||
cbuffer buffer0 : register(b0)
|
||||
{
|
||||
float4x4 ProjectionMatrix;
|
||||
};
|
||||
static uint texture_index : register(b1);
|
||||
|
||||
sampler sampler0 : register(s0);
|
||||
Texture2D<float4> textures[] : register(t0);
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
float2 pos : POSITION;
|
||||
float4 col : COLOR0;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct PS_INPUT
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float4 col : COLOR0;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
[RootSignature(NK_ROOTSIGNATURE)]
|
||||
PS_INPUT vs(VS_INPUT input)
|
||||
{
|
||||
PS_INPUT output;
|
||||
output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));
|
||||
output.col = input.col;
|
||||
output.uv = input.uv;
|
||||
return output;
|
||||
}
|
||||
|
||||
[RootSignature(NK_ROOTSIGNATURE)]
|
||||
float4 ps(PS_INPUT input) : SV_Target
|
||||
{
|
||||
return input.col * textures[texture_index].Sample(sampler0, input.uv);
|
||||
}
|
135
demo/d3d12/nuklear_d3d12_pixel_shader.h
Normal file
135
demo/d3d12/nuklear_d3d12_pixel_shader.h
Normal file
@ -0,0 +1,135 @@
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) D3D Shader Disassembler
|
||||
//
|
||||
//
|
||||
// Input signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------- ------
|
||||
// SV_POSITION 0 xyzw 0 POS float
|
||||
// COLOR 0 xyzw 1 NONE float xyzw
|
||||
// TEXCOORD 0 xy 2 NONE float xy
|
||||
//
|
||||
//
|
||||
// Output signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------- ------
|
||||
// SV_Target 0 xyzw 0 TARGET float xyzw
|
||||
//
|
||||
ps_5_1
|
||||
dcl_globalFlags refactoringAllowed
|
||||
dcl_sampler S0[0:0], mode_default, space=0
|
||||
dcl_resource_texture2d (float,float,float,float) T0[0:*], space=0
|
||||
dcl_input_ps linear v1.xyzw
|
||||
dcl_input_ps linear v2.xy
|
||||
dcl_output o0.xyzw
|
||||
dcl_temps 1
|
||||
sample r0.xyzw, v2.xyxx, T0[0].xyzw, S0[0]
|
||||
mul o0.xyzw, r0.xyzw, v1.xyzw
|
||||
ret
|
||||
// Approximately 0 instruction slots used
|
||||
#endif
|
||||
|
||||
const BYTE nk_d3d12_pixel_shader[] =
|
||||
{
|
||||
68, 88, 66, 67, 228, 128,
|
||||
250, 93, 94, 248, 174, 160,
|
||||
102, 133, 107, 228, 84, 49,
|
||||
109, 253, 1, 0, 0, 0,
|
||||
72, 2, 0, 0, 4, 0,
|
||||
0, 0, 48, 0, 0, 0,
|
||||
164, 0, 0, 0, 216, 0,
|
||||
0, 0, 152, 1, 0, 0,
|
||||
73, 83, 71, 78, 108, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
8, 0, 0, 0, 80, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 3, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
15, 0, 0, 0, 92, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
15, 15, 0, 0, 98, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
3, 3, 0, 0, 83, 86,
|
||||
95, 80, 79, 83, 73, 84,
|
||||
73, 79, 78, 0, 67, 79,
|
||||
76, 79, 82, 0, 84, 69,
|
||||
88, 67, 79, 79, 82, 68,
|
||||
0, 171, 79, 83, 71, 78,
|
||||
44, 0, 0, 0, 1, 0,
|
||||
0, 0, 8, 0, 0, 0,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 0, 0,
|
||||
0, 0, 15, 0, 0, 0,
|
||||
83, 86, 95, 84, 97, 114,
|
||||
103, 101, 116, 0, 171, 171,
|
||||
83, 72, 69, 88, 184, 0,
|
||||
0, 0, 81, 0, 0, 0,
|
||||
46, 0, 0, 0, 106, 8,
|
||||
0, 1, 90, 0, 0, 6,
|
||||
70, 110, 48, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 88, 24, 0, 7,
|
||||
70, 126, 48, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
255, 255, 255, 255, 85, 85,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
98, 16, 0, 3, 242, 16,
|
||||
16, 0, 1, 0, 0, 0,
|
||||
98, 16, 0, 3, 50, 16,
|
||||
16, 0, 2, 0, 0, 0,
|
||||
101, 0, 0, 3, 242, 32,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
104, 0, 0, 2, 1, 0,
|
||||
0, 0, 69, 0, 0, 11,
|
||||
242, 0, 16, 0, 0, 0,
|
||||
0, 0, 70, 16, 16, 0,
|
||||
2, 0, 0, 0, 70, 126,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 96,
|
||||
32, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 56, 0,
|
||||
0, 7, 242, 32, 16, 0,
|
||||
0, 0, 0, 0, 70, 14,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
70, 30, 16, 0, 1, 0,
|
||||
0, 0, 62, 0, 0, 1,
|
||||
82, 84, 83, 48, 168, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
2, 0, 0, 0, 24, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
116, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 48, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 104, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
56, 0, 0, 0, 2, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
255, 255, 255, 255, 0, 0,
|
||||
0, 0, 255, 255, 255, 255,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
255, 255, 255, 255, 1, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 21, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
3, 0, 0, 0, 3, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
16, 0, 0, 0, 8, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 255, 255,
|
||||
127, 127, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0
|
||||
};
|
168
demo/d3d12/nuklear_d3d12_vertex_shader.h
Normal file
168
demo/d3d12/nuklear_d3d12_vertex_shader.h
Normal file
@ -0,0 +1,168 @@
|
||||
#if 0
|
||||
//
|
||||
// Generated by Microsoft (R) D3D Shader Disassembler
|
||||
//
|
||||
//
|
||||
// Input signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------- ------
|
||||
// POSITION 0 xy 0 NONE float xy
|
||||
// COLOR 0 xyzw 1 NONE float xyzw
|
||||
// TEXCOORD 0 xy 2 NONE float xy
|
||||
//
|
||||
//
|
||||
// Output signature:
|
||||
//
|
||||
// Name Index Mask Register SysValue Format Used
|
||||
// -------------------- ----- ------ -------- -------- ------- ------
|
||||
// SV_POSITION 0 xyzw 0 POS float xyzw
|
||||
// COLOR 0 xyzw 1 NONE float xyzw
|
||||
// TEXCOORD 0 xy 2 NONE float xy
|
||||
//
|
||||
vs_5_1
|
||||
dcl_globalFlags refactoringAllowed
|
||||
dcl_constantbuffer CB0[0:0][4], immediateIndexed, space=0
|
||||
dcl_input v0.xy
|
||||
dcl_input v1.xyzw
|
||||
dcl_input v2.xy
|
||||
dcl_output_siv o0.xyzw, position
|
||||
dcl_output o1.xyzw
|
||||
dcl_output o2.xy
|
||||
dcl_temps 1
|
||||
mul r0.xyzw, v0.yyyy, CB0[0][1].xyzw
|
||||
mad r0.xyzw, CB0[0][0].xyzw, v0.xxxx, r0.xyzw
|
||||
add o0.xyzw, r0.xyzw, CB0[0][3].xyzw
|
||||
mov o1.xyzw, v1.xyzw
|
||||
mov o2.xy, v2.xyxx
|
||||
ret
|
||||
// Approximately 0 instruction slots used
|
||||
#endif
|
||||
|
||||
const BYTE nk_d3d12_vertex_shader[] =
|
||||
{
|
||||
68, 88, 66, 67, 187, 129,
|
||||
163, 57, 169, 94, 219, 158,
|
||||
174, 23, 30, 91, 108, 150,
|
||||
135, 141, 1, 0, 0, 0,
|
||||
232, 2, 0, 0, 4, 0,
|
||||
0, 0, 48, 0, 0, 0,
|
||||
160, 0, 0, 0, 20, 1,
|
||||
0, 0, 56, 2, 0, 0,
|
||||
73, 83, 71, 78, 104, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
8, 0, 0, 0, 80, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
3, 3, 0, 0, 89, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
15, 15, 0, 0, 95, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
3, 3, 0, 0, 80, 79,
|
||||
83, 73, 84, 73, 79, 78,
|
||||
0, 67, 79, 76, 79, 82,
|
||||
0, 84, 69, 88, 67, 79,
|
||||
79, 82, 68, 0, 79, 83,
|
||||
71, 78, 108, 0, 0, 0,
|
||||
3, 0, 0, 0, 8, 0,
|
||||
0, 0, 80, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 15, 0,
|
||||
0, 0, 92, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
1, 0, 0, 0, 15, 0,
|
||||
0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
2, 0, 0, 0, 3, 12,
|
||||
0, 0, 83, 86, 95, 80,
|
||||
79, 83, 73, 84, 73, 79,
|
||||
78, 0, 67, 79, 76, 79,
|
||||
82, 0, 84, 69, 88, 67,
|
||||
79, 79, 82, 68, 0, 171,
|
||||
83, 72, 69, 88, 28, 1,
|
||||
0, 0, 81, 0, 1, 0,
|
||||
71, 0, 0, 0, 106, 8,
|
||||
0, 1, 89, 0, 0, 7,
|
||||
70, 142, 48, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
95, 0, 0, 3, 50, 16,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
95, 0, 0, 3, 242, 16,
|
||||
16, 0, 1, 0, 0, 0,
|
||||
95, 0, 0, 3, 50, 16,
|
||||
16, 0, 2, 0, 0, 0,
|
||||
103, 0, 0, 4, 242, 32,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 101, 0,
|
||||
0, 3, 242, 32, 16, 0,
|
||||
1, 0, 0, 0, 101, 0,
|
||||
0, 3, 50, 32, 16, 0,
|
||||
2, 0, 0, 0, 104, 0,
|
||||
0, 2, 1, 0, 0, 0,
|
||||
56, 0, 0, 9, 242, 0,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
86, 21, 16, 0, 0, 0,
|
||||
0, 0, 70, 142, 48, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
50, 0, 0, 11, 242, 0,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
70, 142, 48, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 6, 16,
|
||||
16, 0, 0, 0, 0, 0,
|
||||
70, 14, 16, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 9,
|
||||
242, 32, 16, 0, 0, 0,
|
||||
0, 0, 70, 14, 16, 0,
|
||||
0, 0, 0, 0, 70, 142,
|
||||
48, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 3, 0,
|
||||
0, 0, 54, 0, 0, 5,
|
||||
242, 32, 16, 0, 1, 0,
|
||||
0, 0, 70, 30, 16, 0,
|
||||
1, 0, 0, 0, 54, 0,
|
||||
0, 5, 50, 32, 16, 0,
|
||||
2, 0, 0, 0, 70, 16,
|
||||
16, 0, 2, 0, 0, 0,
|
||||
62, 0, 0, 1, 82, 84,
|
||||
83, 48, 168, 0, 0, 0,
|
||||
2, 0, 0, 0, 2, 0,
|
||||
0, 0, 24, 0, 0, 0,
|
||||
1, 0, 0, 0, 116, 0,
|
||||
0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 48, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 104, 0, 0, 0,
|
||||
2, 0, 0, 0, 56, 0,
|
||||
0, 0, 2, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0, 255, 255,
|
||||
255, 255, 0, 0, 0, 0,
|
||||
255, 255, 255, 255, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 255, 255,
|
||||
255, 255, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0,
|
||||
0, 0, 21, 0, 0, 0,
|
||||
3, 0, 0, 0, 3, 0,
|
||||
0, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 16, 0,
|
||||
0, 0, 8, 0, 0, 0,
|
||||
2, 0, 0, 0, 0, 0,
|
||||
0, 0, 255, 255, 127, 127,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0
|
||||
};
|
Loading…
Reference in New Issue
Block a user