refactored to single thread for d3d12 testing
This commit is contained in:
parent
d26fe05f19
commit
d73c450d21
11
anton_render.raddbgproj
Normal file
11
anton_render.raddbgproj
Normal file
@ -0,0 +1,11 @@
|
||||
// raddbg 0.9.17 project file
|
||||
|
||||
recent_file: path: "src/render/d3d12/render_d3d12.c"
|
||||
recent_file: path: "src/os/win32/os_gfx_win32.c"
|
||||
recent_file: path: "src/main.c"
|
||||
target:
|
||||
{
|
||||
executable: "build/program.exe"
|
||||
working_directory: build
|
||||
enabled: 1
|
||||
}
|
||||
@ -149,3 +149,43 @@ temp_end(Temp temp)
|
||||
arena_pop_to(temp.arena, temp.pos);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~ TODO(anton): Testing, to be refactored or removed.
|
||||
internal void
|
||||
test_arena(Arena *arena)
|
||||
{
|
||||
LOG("Testing arena with filled entries with A prefix.\n");
|
||||
U64 count = 0;
|
||||
U64 N1 = 32;
|
||||
U64 *arr = push_array(arena, U64, N1);
|
||||
for(U64 i = 0; i < N1; i += 1)
|
||||
{
|
||||
arr[i] = i;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
for(U64 i = 0; i < count; i += 1)
|
||||
{
|
||||
U64 value = arr[i];
|
||||
LOG("arr[%i] = %i \n", i, value);
|
||||
}
|
||||
|
||||
arena_pop(arena, sizeof(U64)*N1);
|
||||
|
||||
U64 N2 = 8;
|
||||
count = 0;
|
||||
for(U64 i = 0; i < N2; i += 1)
|
||||
{
|
||||
arr[i] = 100 + i;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
LOG("After pop: \n");
|
||||
for(U64 i = 0; i < count; i += 1)
|
||||
{
|
||||
U64 value = arr[i];
|
||||
LOG("arr[%i] = %i \n", i, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#ifndef BASE_CORE_H
|
||||
#define BASE_CORE_H
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
#include <stdint.h>
|
||||
|
||||
70
src/main.c
70
src/main.c
@ -1,5 +1,11 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define WINDOW_WIDTH_PX 1280
|
||||
#define WINDOW_HEIGHT_PX 720
|
||||
|
||||
|
||||
static int g_do_exit = 0;
|
||||
|
||||
|
||||
static void entry_point();
|
||||
|
||||
@ -19,45 +25,6 @@ static void entry_point();
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
internal void
|
||||
test_arena(Arena *arena)
|
||||
{
|
||||
LOG("Testing arena with filled entries with A prefix.\n");
|
||||
U64 count = 0;
|
||||
U64 N1 = 32;
|
||||
U64 *arr = push_array(arena, U64, N1);
|
||||
for(U64 i = 0; i < N1; i += 1)
|
||||
{
|
||||
arr[i] = i;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
for(U64 i = 0; i < count; i += 1)
|
||||
{
|
||||
U64 value = arr[i];
|
||||
LOG("arr[%i] = %i \n", i, value);
|
||||
}
|
||||
|
||||
arena_pop(arena, sizeof(U64)*N1);
|
||||
|
||||
U64 N2 = 8;
|
||||
count = 0;
|
||||
for(U64 i = 0; i < N2; i += 1)
|
||||
{
|
||||
arr[i] = 100 + i;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
LOG("After pop: \n");
|
||||
for(U64 i = 0; i < count; i += 1)
|
||||
{
|
||||
U64 value = arr[i];
|
||||
LOG("arr[%i] = %i \n", i, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~ Main entry
|
||||
internal void
|
||||
@ -67,31 +34,34 @@ entry_point()
|
||||
|
||||
// Init systems
|
||||
Arena *arena = arena_alloc();
|
||||
//test_arena(arena);
|
||||
|
||||
r_init();
|
||||
//test_arena(arena);
|
||||
|
||||
r_trigger_debug_message();
|
||||
//r_log_debug_messages();
|
||||
|
||||
// Main program loop
|
||||
U32 do_exit = 0;
|
||||
g_do_exit = 0;
|
||||
for(;;)
|
||||
{
|
||||
MSG Message;
|
||||
while(PeekMessage(&Message, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
switch(Message.message)
|
||||
{
|
||||
case WM_CLOSE:
|
||||
{
|
||||
SendMessageW(g_service_window_handle, OS_W32_MSG_DESTROY_WINDOW, Message.wParam, 0);
|
||||
do_exit = 1;
|
||||
} break;
|
||||
}
|
||||
|
||||
TranslateMessage(&Message);
|
||||
DispatchMessageW(&Message);
|
||||
}
|
||||
|
||||
if(do_exit)
|
||||
|
||||
//r_log_debug_messages();
|
||||
if(g_do_exit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
r_cleanup();
|
||||
|
||||
arena_release(arena);
|
||||
|
||||
|
||||
@ -2,4 +2,7 @@
|
||||
//~ os source includes
|
||||
|
||||
#include "os/os_core.c"
|
||||
#include "os/win32/os_core_win32.c"
|
||||
|
||||
// If win32
|
||||
#include "os/win32/os_core_win32.c"
|
||||
#include "os/win32/os_gfx_win32.c"
|
||||
@ -8,5 +8,6 @@
|
||||
|
||||
// If win32
|
||||
#include "os/win32/os_core_win32.h"
|
||||
#include "os/win32/os_gfx_win32.h"
|
||||
|
||||
#endif /* OS_INC_H */
|
||||
@ -1,16 +1,11 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
#pragma comment(lib, "kernel32")
|
||||
#pragma comment(lib, "user32")
|
||||
#pragma comment(lib, "gdi32")
|
||||
#pragma comment(lib, "kernel32.lib")
|
||||
#pragma comment(lib, "user32.lib")
|
||||
#pragma comment(lib, "gdi32.lib")
|
||||
|
||||
|
||||
#define OS_W32_MSG_CREATE_WINDOW (WM_USER + 0x1337)
|
||||
#define OS_W32_MSG_DESTROY_WINDOW (WM_USER + 0x1338)
|
||||
global DWORD MainThreadID;
|
||||
global HWND g_service_window_handle;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
@ -43,205 +38,6 @@ os_release(void *ptr, U64 size)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
internal LRESULT CALLBACK
|
||||
ServiceWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
|
||||
{
|
||||
/* NOTE(casey): This is not really a window handler per se, it's actually just
|
||||
a remote thread call handler. Windows only really has blocking remote thread
|
||||
calls if you register a WndProc for them, so that's what we do.
|
||||
|
||||
This handles CREATE_DANGEROUS_WINDOW and DESTROY_DANGEROUS_WINDOW, which are
|
||||
just calls that do CreateWindow and DestroyWindow here on this thread when
|
||||
some other thread wants that to happen.
|
||||
*/
|
||||
|
||||
LRESULT result = 0;
|
||||
|
||||
switch(Message)
|
||||
{
|
||||
case OS_W32_MSG_CREATE_WINDOW:
|
||||
{
|
||||
OS_W32_WndParam *wndParam = (OS_W32_WndParam *)WParam;
|
||||
result = (LRESULT)CreateWindowExW(wndParam->dwExStyle,
|
||||
wndParam->lpClassName,
|
||||
wndParam->lpWindowName,
|
||||
wndParam->dwStyle,
|
||||
wndParam->X,
|
||||
wndParam->Y,
|
||||
wndParam->nWidth,
|
||||
wndParam->nHeight,
|
||||
wndParam->hWndParent,
|
||||
wndParam->hMenu,
|
||||
wndParam->hInstance,
|
||||
wndParam->lpParam);
|
||||
|
||||
} break;
|
||||
|
||||
case OS_W32_MSG_DESTROY_WINDOW:
|
||||
{
|
||||
DestroyWindow((HWND)WParam);
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
result = DefWindowProcW(Window, Message, WParam, LParam);
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal LRESULT CALLBACK
|
||||
DisplayWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
|
||||
{
|
||||
/* NOTE(casey): This is an example of an actual window procedure. It doesn't do anything
|
||||
but forward things to the main thread, because again, all window messages now occur
|
||||
on the message thread, and presumably we would rather handle everything there. You
|
||||
don't _have_ to do that - you could choose to handle some of the messages here.
|
||||
But if you did, you would have to actually think about whether there are race conditions
|
||||
with your main thread and all that. So just PostThreadMessageW()'ing everything gets
|
||||
you out of having to think about it.
|
||||
*/
|
||||
|
||||
LRESULT Result = 0;
|
||||
|
||||
switch (Message)
|
||||
{
|
||||
// NOTE(casey): Mildly annoying, if you want to specify a window, you have
|
||||
// to snuggle the params yourself, because Windows doesn't let you forward
|
||||
// a god damn window message even though the program IS CALLED WINDOWS. It's
|
||||
// in the name! Let me pass it!
|
||||
case WM_CLOSE:
|
||||
{
|
||||
PostThreadMessageW(MainThreadID, Message, (WPARAM)Window, LParam);
|
||||
} break;
|
||||
|
||||
// NOTE(casey): Anything you want the application to handle, forward to the main thread
|
||||
// here.
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_DESTROY:
|
||||
case WM_CHAR:
|
||||
{
|
||||
PostThreadMessageW(MainThreadID, Message, WParam, LParam);
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
Result = DefWindowProcW(Window, Message, WParam, LParam);
|
||||
} break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal DWORD WINAPI
|
||||
MainThreadEntryPoint(LPVOID Param)
|
||||
{
|
||||
/* NOTE(Casey): This is your app code. Basically you just do everything the same,
|
||||
but instead of calling CreateWindow/DestroyWindow, you use SendMessage to
|
||||
do it on the other thread, using the CREATE_DANGEROUS_WINDOW and DESTROY_DANGEROUS_WINDOW
|
||||
user messages. Otherwise, everything proceeds as normal.
|
||||
*/
|
||||
HWND ServiceWindow = (HWND)Param;
|
||||
g_service_window_handle = ServiceWindow;
|
||||
|
||||
WNDCLASSEXW WindowClass = {0};
|
||||
WindowClass.cbSize = sizeof(WindowClass);
|
||||
WindowClass.lpfnWndProc = &DisplayWndProc;
|
||||
WindowClass.hInstance = GetModuleHandleW(NULL);
|
||||
WindowClass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
|
||||
WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
|
||||
WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
WindowClass.lpszClassName = L"Dangerous Class";
|
||||
RegisterClassExW(&WindowClass);
|
||||
|
||||
OS_W32_WndParam wndParam = {0};
|
||||
wndParam.dwExStyle = 0;;
|
||||
wndParam.lpClassName = WindowClass.lpszClassName;
|
||||
wndParam.lpWindowName = L"Dangerous Window";
|
||||
wndParam.dwStyle = WS_OVERLAPPEDWINDOW|WS_VISIBLE;
|
||||
wndParam.X = CW_USEDEFAULT;
|
||||
wndParam.Y = CW_USEDEFAULT;
|
||||
wndParam.nWidth = CW_USEDEFAULT;
|
||||
wndParam.nHeight = CW_USEDEFAULT;
|
||||
wndParam.hInstance = WindowClass.hInstance;
|
||||
|
||||
// Create initial window
|
||||
HWND ThisWouldBeTheHandleIfYouCared = (HWND)SendMessageW(ServiceWindow,
|
||||
OS_W32_MSG_CREATE_WINDOW,
|
||||
(WPARAM)&wndParam,
|
||||
0);
|
||||
|
||||
entry_point();
|
||||
|
||||
|
||||
LOG("Exited main program. Terminating \n");
|
||||
ExitProcess(0);
|
||||
}
|
||||
|
||||
int
|
||||
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||
{
|
||||
|
||||
/* NOTE(casey): At startup, you create one hidden window used to handle requests
|
||||
to create or destroy windows. There's nothing special about this window; it
|
||||
only exists because Windows doesn't have a way to do a remote thread call without
|
||||
a window handler. You could instead just do this with your own synchronization
|
||||
primitives if you wanted - this is just the easiest way to do it on Windows
|
||||
because they've already built it for you.
|
||||
*/
|
||||
|
||||
LOG("Entered WinMain\n");
|
||||
|
||||
WNDCLASSEXW WindowClass = {0};
|
||||
WindowClass.cbSize = sizeof(WindowClass);
|
||||
WindowClass.lpfnWndProc = &ServiceWndProc;
|
||||
WindowClass.hInstance = GetModuleHandleW(NULL);
|
||||
WindowClass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
|
||||
WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
|
||||
WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
WindowClass.lpszClassName = L"DTCClass";
|
||||
RegisterClassExW(&WindowClass);
|
||||
|
||||
HWND ServiceWindow = CreateWindowExW(0, WindowClass.lpszClassName, L"DTCService", 0,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
0, 0, WindowClass.hInstance, 0);
|
||||
|
||||
// NOTE(casey): Once the service window is created, you can start the main thread,
|
||||
// which is where all your app code would actually happen.
|
||||
CreateThread(0, 0, MainThreadEntryPoint, ServiceWindow, 0, &MainThreadID);
|
||||
|
||||
// NOTE(casey): This thread can just idle for the rest of the run, forwarding
|
||||
// messages to the main thread that it thinks the main thread wants.
|
||||
DWORD exitCode;
|
||||
for(;;)
|
||||
{
|
||||
|
||||
MSG Message;
|
||||
GetMessageW(&Message, 0, 0, 0);
|
||||
TranslateMessage(&Message);
|
||||
if((Message.message == WM_CHAR) ||
|
||||
(Message.message == WM_KEYDOWN) ||
|
||||
(Message.message == WM_QUIT) ||
|
||||
(Message.message == WM_SIZE))
|
||||
{
|
||||
PostThreadMessageW(MainThreadID, Message.message, Message.wParam, Message.lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
DispatchMessageW(&Message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
internal void
|
||||
|
||||
@ -6,26 +6,6 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
// Temp struct for launching window on separate thread.
|
||||
// Trying to learn from https://github.com/cmuratori/dtc/blob/main/dtc.cpp
|
||||
typedef struct OS_W32_WndParam OS_W32_WndParam;
|
||||
struct OS_W32_WndParam
|
||||
{
|
||||
DWORD dwExStyle;
|
||||
LPCWSTR lpClassName;
|
||||
LPCWSTR lpWindowName;
|
||||
DWORD dwStyle;
|
||||
S32 X;
|
||||
S32 Y;
|
||||
S32 nWidth;
|
||||
S32 nHeight;
|
||||
HWND hWndParent;
|
||||
HMENU hMenu;
|
||||
HINSTANCE hInstance;
|
||||
LPVOID lpParam;
|
||||
};
|
||||
|
||||
|
||||
internal void OS_W32_log_debug(const char *fmt_string, ...);
|
||||
|
||||
#endif /* OS_CORE_WIN32_H */
|
||||
362
src/os/win32/os_gfx_win32.c
Normal file
362
src/os/win32/os_gfx_win32.c
Normal file
@ -0,0 +1,362 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
global HWND g_win32_window_handle;
|
||||
|
||||
internal LRESULT CALLBACK
|
||||
DisplayWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
|
||||
{
|
||||
|
||||
LRESULT Result = 0;
|
||||
switch (Message)
|
||||
{
|
||||
case WM_QUIT:
|
||||
case WM_DESTROY:
|
||||
case WM_CLOSE:
|
||||
{
|
||||
g_do_exit = 1;
|
||||
} break;
|
||||
// NOTE(casey): Anything you want the application to handle, forward to the main thread
|
||||
// here.
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_CHAR:
|
||||
{
|
||||
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
Result = DefWindowProcW(Window, Message, WParam, LParam);
|
||||
} break;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal DWORD WINAPI
|
||||
MainThreadEntryPoint()
|
||||
{
|
||||
|
||||
|
||||
WNDCLASSEXW WindowClass = {0};
|
||||
WindowClass.cbSize = sizeof(WindowClass);
|
||||
WindowClass.lpfnWndProc = &DisplayWndProc;
|
||||
WindowClass.hInstance = GetModuleHandleW(NULL);
|
||||
WindowClass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
|
||||
WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
|
||||
WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
WindowClass.lpszClassName = L"TESTING SOME STUFF";
|
||||
RegisterClassExW(&WindowClass);
|
||||
|
||||
OS_W32_WndParam wndParam = {0};
|
||||
wndParam.dwExStyle = 0;;
|
||||
wndParam.lpClassName = WindowClass.lpszClassName;
|
||||
wndParam.lpWindowName = L"TESTING SOME STUFF";
|
||||
wndParam.dwStyle = WS_OVERLAPPEDWINDOW|WS_VISIBLE;
|
||||
wndParam.X = CW_USEDEFAULT;
|
||||
wndParam.Y = CW_USEDEFAULT;
|
||||
wndParam.nWidth = WINDOW_WIDTH_PX;
|
||||
wndParam.nHeight = WINDOW_HEIGHT_PX;
|
||||
wndParam.hInstance = WindowClass.hInstance;
|
||||
|
||||
HWND hwnd = CreateWindowExW(wndParam.dwExStyle,
|
||||
wndParam.lpClassName,
|
||||
wndParam.lpWindowName,
|
||||
wndParam.dwStyle,
|
||||
wndParam.X,
|
||||
wndParam.Y,
|
||||
wndParam.nWidth,
|
||||
wndParam.nHeight,
|
||||
wndParam.hWndParent,
|
||||
wndParam.hMenu,
|
||||
wndParam.hInstance,
|
||||
wndParam.lpParam);
|
||||
|
||||
g_win32_window_handle = hwnd;
|
||||
|
||||
entry_point();
|
||||
|
||||
|
||||
LOG("Exited main program. Terminating \n");
|
||||
ExitProcess(0);
|
||||
}
|
||||
|
||||
int
|
||||
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||
{
|
||||
MainThreadEntryPoint();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~ Below is code for creating a window on a service thread and handling messaging there.
|
||||
// There are some issues with doing this with D3D12, and since the point is that I want to
|
||||
// try and use mesh shaders with Vulkan and/or D3D12, I will just have everything running on a main thread
|
||||
// for now. Eventually I have to fix this properly, but I have to read up a bit
|
||||
|
||||
|
||||
//#define OS_W32_MSG_CREATE_WINDOW (WM_USER + 0x1337)
|
||||
//#define OS_W32_MSG_DESTROY_WINDOW (WM_USER + 0x1338)
|
||||
//#define OS_W32_MSG_CREATE_SWAPCHAIN (WM_USER + 0x1339)
|
||||
//
|
||||
//global DWORD MainThreadID;
|
||||
//global HWND g_win32_service_window_handle;
|
||||
//global HWND g_win32_window_handle;
|
||||
//
|
||||
//
|
||||
//
|
||||
//internal LRESULT CALLBACK
|
||||
//ServiceWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
|
||||
//{
|
||||
// /* NOTE(casey): This is not really a window handler per se, it's actually just
|
||||
// a remote thread call handler. Windows only really has blocking remote thread
|
||||
// calls if you register a WndProc for them, so that's what we do.
|
||||
//
|
||||
// This handles CREATE_DANGEROUS_WINDOW and DESTROY_DANGEROUS_WINDOW, which are
|
||||
// just calls that do CreateWindow and DestroyWindow here on this thread when
|
||||
// some other thread wants that to happen.
|
||||
// */
|
||||
//
|
||||
// LRESULT result = 0;
|
||||
//
|
||||
// switch(Message)
|
||||
// {
|
||||
// case OS_W32_MSG_CREATE_WINDOW:
|
||||
// {
|
||||
// OS_W32_WndParam *wndParam = (OS_W32_WndParam *)WParam;
|
||||
// HWND hwnd = CreateWindowExW(wndParam->dwExStyle,
|
||||
// wndParam->lpClassName,
|
||||
// wndParam->lpWindowName,
|
||||
// wndParam->dwStyle,
|
||||
// wndParam->X,
|
||||
// wndParam->Y,
|
||||
// wndParam->nWidth,
|
||||
// wndParam->nHeight,
|
||||
// wndParam->hWndParent,
|
||||
// wndParam->hMenu,
|
||||
// wndParam->hInstance,
|
||||
// wndParam->lpParam);
|
||||
//
|
||||
// if(hwnd)
|
||||
// {
|
||||
// ShowWindow(hwnd, SW_SHOW);
|
||||
// UpdateWindow(hwnd);
|
||||
//
|
||||
// // Pump messages for this window
|
||||
// MSG msg;
|
||||
// while (PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)) {
|
||||
// TranslateMessage(&msg);
|
||||
// DispatchMessageW(&msg);
|
||||
// }
|
||||
// // Signal that window is ready
|
||||
// HANDLE windowReadyEvent = (HANDLE)LParam; // Pass event via LParam
|
||||
// if (windowReadyEvent) {
|
||||
// SetEvent(windowReadyEvent);
|
||||
// }
|
||||
//
|
||||
// result = (LRESULT)hwnd;
|
||||
// } else {
|
||||
// LOG("WIN32 ERROR: failed to create window: %lu \n", GetLastError());
|
||||
// result = 0;
|
||||
// }
|
||||
//
|
||||
// } break;
|
||||
//
|
||||
// case OS_W32_MSG_CREATE_SWAPCHAIN:
|
||||
// {
|
||||
// IDXGIFactory4 *factory = (IDXGIFactory4 *)WParam;
|
||||
// result = r_d3d12_create_swapchain(factory);
|
||||
// } break;
|
||||
//
|
||||
// case OS_W32_MSG_DESTROY_WINDOW:
|
||||
// {
|
||||
// DestroyWindow((HWND)WParam);
|
||||
// } break;
|
||||
//
|
||||
// default:
|
||||
// {
|
||||
// result = DefWindowProcW(Window, Message, WParam, LParam);
|
||||
// } break;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return result;
|
||||
//}
|
||||
//
|
||||
//internal LRESULT CALLBACK
|
||||
//DisplayWndProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
|
||||
//{
|
||||
// /* NOTE(casey): This is an example of an actual window procedure. It doesn't do anything
|
||||
// but forward things to the main thread, because again, all window messages now occur
|
||||
// on the message thread, and presumably we would rather handle everything there. You
|
||||
// don't _have_ to do that - you could choose to handle some of the messages here.
|
||||
// But if you did, you would have to actually think about whether there are race conditions
|
||||
// with your main thread and all that. So just PostThreadMessageW()'ing everything gets
|
||||
// you out of having to think about it.
|
||||
// */
|
||||
//
|
||||
// LRESULT Result = 0;
|
||||
//
|
||||
// switch (Message)
|
||||
// {
|
||||
// // NOTE(casey): Mildly annoying, if you want to specify a window, you have
|
||||
// // to snuggle the params yourself, because Windows doesn't let you forward
|
||||
// // a god damn window message even though the program IS CALLED WINDOWS. It's
|
||||
// // in the name! Let me pass it!
|
||||
// case WM_CLOSE:
|
||||
// {
|
||||
// PostThreadMessageW(MainThreadID, Message, (WPARAM)Window, LParam);
|
||||
// } break;
|
||||
//
|
||||
// // NOTE(casey): Anything you want the application to handle, forward to the main thread
|
||||
// // here.
|
||||
// case WM_MOUSEMOVE:
|
||||
// case WM_LBUTTONDOWN:
|
||||
// case WM_LBUTTONUP:
|
||||
// case WM_DESTROY:
|
||||
// case WM_CHAR:
|
||||
// {
|
||||
// PostThreadMessageW(MainThreadID, Message, WParam, LParam);
|
||||
// } break;
|
||||
//
|
||||
// default:
|
||||
// {
|
||||
// Result = DefWindowProcW(Window, Message, WParam, LParam);
|
||||
// } break;
|
||||
// }
|
||||
//
|
||||
// return Result;
|
||||
//}
|
||||
//
|
||||
//internal DWORD WINAPI
|
||||
//MainThreadEntryPoint(LPVOID Param)
|
||||
//{
|
||||
// /* NOTE(Casey): This is your app code. Basically you just do everything the same,
|
||||
// but instead of calling CreateWindow/DestroyWindow, you use SendMessage to
|
||||
// do it on the other thread, using the CREATE_DANGEROUS_WINDOW and DESTROY_DANGEROUS_WINDOW
|
||||
// user messages. Otherwise, everything proceeds as normal.
|
||||
// */
|
||||
// HWND ServiceWindow = (HWND)Param;
|
||||
// g_win32_service_window_handle = ServiceWindow;
|
||||
//
|
||||
// WNDCLASSEXW WindowClass = {0};
|
||||
// WindowClass.cbSize = sizeof(WindowClass);
|
||||
// WindowClass.lpfnWndProc = &DisplayWndProc;
|
||||
// WindowClass.hInstance = GetModuleHandleW(NULL);
|
||||
// WindowClass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
|
||||
// WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
|
||||
// WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
// WindowClass.lpszClassName = L"Dangerous Class";
|
||||
// RegisterClassExW(&WindowClass);
|
||||
//
|
||||
// OS_W32_WndParam wndParam = {0};
|
||||
// wndParam.dwExStyle = 0;;
|
||||
// wndParam.lpClassName = WindowClass.lpszClassName;
|
||||
// wndParam.lpWindowName = L"Dangerous Window";
|
||||
// wndParam.dwStyle = WS_OVERLAPPEDWINDOW|WS_VISIBLE;
|
||||
// wndParam.X = CW_USEDEFAULT;
|
||||
// wndParam.Y = CW_USEDEFAULT;
|
||||
// wndParam.nWidth = WINDOW_WIDTH_PX;
|
||||
// wndParam.nHeight = WINDOW_HEIGHT_PX;
|
||||
// wndParam.hInstance = WindowClass.hInstance;
|
||||
//
|
||||
// // To ensure that we can set up D3D12 on this thread we wait for synchronisation until the
|
||||
// // window is created on the service thread.
|
||||
// HANDLE window_ready_event = CreateEventW(0, FALSE, FALSE, 0);
|
||||
// if(!window_ready_event)
|
||||
// {
|
||||
// LOG("WIN32 ERROR: Failed to create window ready event: %lu \n", GetLastError());
|
||||
// ExitProcess(1);
|
||||
// }
|
||||
//
|
||||
// g_win32_window_handle = (HWND)SendMessageW(ServiceWindow,
|
||||
// OS_W32_MSG_CREATE_WINDOW,
|
||||
// (WPARAM)&wndParam,
|
||||
// (LPARAM)window_ready_event);
|
||||
//
|
||||
// if(!g_win32_window_handle)
|
||||
// {
|
||||
// LOG("WIN32 ERROR: Failed to create window on service thread \n");
|
||||
// CloseHandle(window_ready_event);
|
||||
// ExitProcess(1);
|
||||
// }
|
||||
//
|
||||
// // Wait for initialisation
|
||||
// DWORD wait_result = WaitForSingleObject(window_ready_event, 5000);
|
||||
// CloseHandle(window_ready_event);
|
||||
// if(wait_result != WAIT_OBJECT_0)
|
||||
// {
|
||||
// LOG("WIN32 ERROR: Window creation timeout on service thread: %lu \n", GetLastError());
|
||||
// SendMessageW(g_win32_service_window_handle,
|
||||
// OS_W32_MSG_DESTROY_WINDOW,
|
||||
// (WPARAM)g_win32_window_handle, 0);
|
||||
// ExitProcess(1);
|
||||
// }
|
||||
//
|
||||
// entry_point();
|
||||
//
|
||||
//
|
||||
// LOG("Exited main program. Terminating \n");
|
||||
// ExitProcess(0);
|
||||
//}
|
||||
//
|
||||
//int
|
||||
//WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||
//{
|
||||
//
|
||||
// /* NOTE(casey): At startup, you create one hidden window used to handle requests
|
||||
// to create or destroy windows. There's nothing special about this window; it
|
||||
// only exists because Windows doesn't have a way to do a remote thread call without
|
||||
// a window handler. You could instead just do this with your own synchronization
|
||||
// primitives if you wanted - this is just the easiest way to do it on Windows
|
||||
// because they've already built it for you.
|
||||
// */
|
||||
//
|
||||
// LOG("Entered WinMain\n");
|
||||
//
|
||||
// WNDCLASSEXW WindowClass = {0};
|
||||
// WindowClass.cbSize = sizeof(WindowClass);
|
||||
// WindowClass.lpfnWndProc = &ServiceWndProc;
|
||||
// WindowClass.hInstance = GetModuleHandleW(NULL);
|
||||
// WindowClass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
|
||||
// WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
|
||||
// WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
// WindowClass.lpszClassName = L"DTCClass";
|
||||
// RegisterClassExW(&WindowClass);
|
||||
//
|
||||
// HWND ServiceWindow = CreateWindowExW(0, WindowClass.lpszClassName, L"DTCService", 0,
|
||||
// CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
// 0, 0, WindowClass.hInstance, 0);
|
||||
//
|
||||
// // NOTE(casey): Once the service window is created, you can start the main thread,
|
||||
// // which is where all your app code would actually happen.
|
||||
// CreateThread(0, 0, MainThreadEntryPoint, ServiceWindow, 0, &MainThreadID);
|
||||
//
|
||||
// // NOTE(casey): This thread can just idle for the rest of the run, forwarding
|
||||
// // messages to the main thread that it thinks the main thread wants.
|
||||
// DWORD exitCode;
|
||||
// for(;;)
|
||||
// {
|
||||
//
|
||||
// MSG Message;
|
||||
// GetMessageW(&Message, 0, 0, 0);
|
||||
// TranslateMessage(&Message);
|
||||
// if((Message.message == WM_CHAR) ||
|
||||
// (Message.message == WM_KEYDOWN) ||
|
||||
// (Message.message == WM_QUIT) ||
|
||||
// (Message.message == WM_SIZE))
|
||||
// {
|
||||
// PostThreadMessageW(MainThreadID, Message.message, Message.wParam, Message.lParam);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// DispatchMessageW(&Message);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
//
|
||||
//
|
||||
27
src/os/win32/os_gfx_win32.h
Normal file
27
src/os/win32/os_gfx_win32.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef OS_GFX_WIN32_H
|
||||
#define OS_GFX_WIN32_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
// Temp struct for launching window on separate thread.
|
||||
// Trying to learn from https://github.com/cmuratori/dtc/blob/main/dtc.cpp
|
||||
typedef struct OS_W32_WndParam OS_W32_WndParam;
|
||||
struct OS_W32_WndParam
|
||||
{
|
||||
DWORD dwExStyle;
|
||||
LPCWSTR lpClassName;
|
||||
LPCWSTR lpWindowName;
|
||||
DWORD dwStyle;
|
||||
S32 X;
|
||||
S32 Y;
|
||||
S32 nWidth;
|
||||
S32 nHeight;
|
||||
HWND hWndParent;
|
||||
HMENU hMenu;
|
||||
HINSTANCE hInstance;
|
||||
LPVOID lpParam;
|
||||
};
|
||||
|
||||
|
||||
#endif /* OS_GFX_WIN32_H */
|
||||
192
src/render/d3d12/render_d3d12.c
Normal file
192
src/render/d3d12/render_d3d12.c
Normal file
@ -0,0 +1,192 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
#pragma comment(lib, "d3d12.lib")
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
#define D3D12_ERROR(msg, ...) LOG("D3D12 ERROR (anton): "); LOG(msg, __VA_ARGS__); Trap();
|
||||
#define D3D12_CHECK(hr) if(FAILED((hr))) { Trap(); }
|
||||
|
||||
#define D3D12_RELEASE(res) if( (res) && (res)->lpVtbl) { (res)->lpVtbl->Release((res)); (res) = 0; }
|
||||
|
||||
global R_D3D12_State *r_d3d12_state = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
|
||||
// D3D12 initialisiation
|
||||
internal void
|
||||
r_init()
|
||||
{
|
||||
Arena *arena = arena_alloc();
|
||||
r_d3d12_state = push_array(arena, R_D3D12_State, 1);
|
||||
r_d3d12_state->arena = arena;
|
||||
|
||||
HRESULT hr;
|
||||
hr = D3D12GetDebugInterface(&IID_ID3D12Debug, (void**)&r_d3d12_state->debug);
|
||||
if(SUCCEEDED(hr) && r_d3d12_state->debug )
|
||||
{
|
||||
r_d3d12_state->debug->lpVtbl->EnableDebugLayer(r_d3d12_state->debug);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D12_ERROR("Failed to create D3D12 Debug interface \n");
|
||||
}
|
||||
|
||||
hr = D3D12CreateDevice(0,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
&IID_ID3D12Device,
|
||||
(void **)&r_d3d12_state->device);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
D3D12_ERROR("Failed to create device \n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//internal void
|
||||
//r_log_debug_messages()
|
||||
//{
|
||||
// if(r_d3d12_state->info_queue)
|
||||
// {
|
||||
// UINT64 numMessages = r_d3d12_state->info_queue->lpVtbl->GetNumStoredMessages(r_d3d12_state->info_queue);
|
||||
// for (UINT64 i = 0; i < numMessages; i++) {
|
||||
// SIZE_T messageLength = 0;
|
||||
// r_d3d12_state->info_queue->lpVtbl->GetMessage(r_d3d12_state->info_queue, i, NULL, &messageLength);
|
||||
//
|
||||
// D3D12_MESSAGE* message = (D3D12_MESSAGE*)malloc(messageLength);
|
||||
// if (message) {
|
||||
// r_d3d12_state->info_queue->lpVtbl->GetMessage(r_d3d12_state->info_queue, i, message, &messageLength);
|
||||
// LOG("DX12 Debug: %s\n", message->pDescription);
|
||||
// free(message);
|
||||
// }
|
||||
// }
|
||||
// r_d3d12_state->info_queue->lpVtbl->ClearStoredMessages(r_d3d12_state->info_queue);
|
||||
// }
|
||||
//}
|
||||
|
||||
internal void
|
||||
r_trigger_debug_message()
|
||||
{
|
||||
if(r_d3d12_state->device)
|
||||
{
|
||||
D3D12_COMMAND_QUEUE_DESC queue_desc = {0};
|
||||
queue_desc.Type = -1; // Error value, should be 0,1,2 or 3
|
||||
|
||||
ID3D12CommandQueue *queue = 0;
|
||||
HRESULT hr = r_d3d12_state->device->lpVtbl->CreateCommandQueue(r_d3d12_state->device,
|
||||
&queue_desc,
|
||||
&IID_ID3D12CommandQueue,
|
||||
(void**)&queue);
|
||||
if(queue) {
|
||||
queue->lpVtbl->Release(queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
r_cleanup()
|
||||
{
|
||||
|
||||
// Report live objects
|
||||
{
|
||||
if(r_d3d12_state->device)
|
||||
{
|
||||
ID3D12DebugDevice *debug_device = 0;
|
||||
HRESULT hr = r_d3d12_state->device->lpVtbl->QueryInterface(r_d3d12_state->device,
|
||||
&IID_ID3D12DebugDevice,
|
||||
(void **)&debug_device);
|
||||
if(SUCCEEDED(hr) && debug_device)
|
||||
{
|
||||
debug_device->lpVtbl->ReportLiveDeviceObjects(debug_device,
|
||||
D3D12_RLDO_DETAIL | D3D12_RLDO_IGNORE_INTERNAL);
|
||||
debug_device->lpVtbl->Release(debug_device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_RELEASE(r_d3d12_state->device);
|
||||
D3D12_RELEASE(r_d3d12_state->debug);
|
||||
|
||||
|
||||
arena_release(r_d3d12_state->arena);
|
||||
}
|
||||
|
||||
//internal LRESULT
|
||||
//r_d3d12_create_swapchain(IDXGIFactory4 *factory)
|
||||
//{
|
||||
// LRESULT result = 0;
|
||||
// HRESULT hr = 0;
|
||||
//
|
||||
// // Log window state
|
||||
// RECT clientRect;
|
||||
// GetClientRect(g_win32_window_handle, &clientRect);
|
||||
// LOG("Swap chain creation - Window state: HWND %p, Visible %d, Client area %ldx%ld\n",
|
||||
// g_win32_window_handle,
|
||||
// IsWindowVisible(g_win32_window_handle),
|
||||
// clientRect.right - clientRect.left,
|
||||
// clientRect.bottom - clientRect.top);
|
||||
//
|
||||
// if (!IsWindowVisible(g_win32_window_handle)) {
|
||||
// LOG("WARNING: Window not visible, attempting to show\n");
|
||||
// ShowWindow(g_win32_window_handle, SW_SHOW);
|
||||
// UpdateWindow(g_win32_window_handle);
|
||||
// }
|
||||
//
|
||||
// if (clientRect.right - clientRect.left == 0 || clientRect.bottom - clientRect.top == 0) {
|
||||
// LOG("ERROR: Window has zero client area\n");
|
||||
// result = 0;
|
||||
// Trap();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// DXGI_SWAP_CHAIN_DESC1 swapDesc = {0};
|
||||
// swapDesc.Width = WINDOW_WIDTH_PX;
|
||||
// swapDesc.Height = WINDOW_HEIGHT_PX;
|
||||
// swapDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
// swapDesc.SampleDesc.Count = 1;
|
||||
// swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
// swapDesc.BufferCount = 2;
|
||||
// swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
// swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
//
|
||||
// LOG("Creating swap chain on service thread: %dx%d\n", swapDesc.Width, swapDesc.Height);
|
||||
// IDXGISwapChain1* swapChain = 0;
|
||||
// hr = factory->lpVtbl->CreateSwapChainForHwnd(
|
||||
// factory,
|
||||
// (IUnknown*)r_d3d12_state->device,
|
||||
// g_win32_window_handle,
|
||||
// &swapDesc,
|
||||
// 0, 0,
|
||||
// &swapChain
|
||||
// );
|
||||
// if (FAILED(hr)) {
|
||||
// LOG("Failed to create swap chain in service thread: HRESULT 0x%X\n", hr);
|
||||
// r_log_debug_messages();
|
||||
// result = 0;
|
||||
// } else {
|
||||
// hr = swapChain->lpVtbl->QueryInterface(
|
||||
// swapChain,
|
||||
// &IID_IDXGISwapChain3,
|
||||
// (void**)&r_d3d12_state->swapchain
|
||||
// );
|
||||
// swapChain->lpVtbl->Release(swapChain);
|
||||
// if (FAILED(hr)) {
|
||||
// LOG("Failed to query swap chain: HRESULT 0x%X\n", hr);
|
||||
// r_log_debug_messages();
|
||||
// Trap();
|
||||
// result = 0;
|
||||
// } else {
|
||||
// result = 1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
//}
|
||||
30
src/render/d3d12/render_d3d12.h
Normal file
30
src/render/d3d12/render_d3d12.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef RENDER_D3D12_H
|
||||
#define RENDER_D3D12_H
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
typedef struct R_D3D12_State R_D3D12_State;
|
||||
struct R_D3D12_State
|
||||
{
|
||||
Arena *arena;
|
||||
HWND window_handle;
|
||||
ID3D12Device *device;
|
||||
ID3D12Debug *debug;
|
||||
ID3D12InfoQueue *info_queue;
|
||||
IDXGISwapChain3 *swapchain;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
internal LRESULT r_d3d12_create_swapchain(IDXGIFactory4 *factory);
|
||||
|
||||
#endif /* RENDER_D3D12_H */
|
||||
2
src/render/render_core.c
Normal file
2
src/render/render_core.c
Normal file
@ -0,0 +1,2 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
15
src/render/render_core.h
Normal file
15
src/render/render_core.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef RENDER_CORE_H
|
||||
#define RENDER_CORE_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
|
||||
internal void r_init();
|
||||
|
||||
internal void r_log_debug_messages();
|
||||
|
||||
// TODO(anton): Temp for testing, to be removed
|
||||
internal void r_trigger_debug_message();
|
||||
|
||||
#endif /* RENDER_CORE_H */
|
||||
@ -1,2 +1,6 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
//~
|
||||
|
||||
|
||||
#include "render/render_core.c"
|
||||
#include "render/d3d12/render_d3d12.c"
|
||||
@ -4,4 +4,8 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//~
|
||||
|
||||
|
||||
#include "render/render_core.h"
|
||||
#include "render/d3d12/render_d3d12.h"
|
||||
|
||||
#endif /* RENDER_INC_H */
|
||||
Loading…
Reference in New Issue
Block a user