From 707755e503b384111bdb946b3ae8348c26931a93 Mon Sep 17 00:00:00 2001 From: jacob Date: Fri, 6 Mar 2026 12:15:36 -0800 Subject: [PATCH] conservative d3d12 sync --- src/base/base.cgh | 2 + src/base/base_log.h | 40 +- src/base/base_win32/base_win32.c | 391 +++++++++++------- src/base/base_win32/base_win32.h | 85 ++-- src/gpu/gpu_core.h | 35 +- src/gpu/gpu_dx12/gpu_dx12_core.c | 339 ++++++++++----- src/gpu/gpu_dx12/gpu_dx12_core.h | 37 +- .../meta_os/meta_os_win32/meta_os_win32.c | 28 -- .../meta_os/meta_os_win32/meta_os_win32.h | 5 - src/pp/pp_vis/pp_vis_core.c | 8 +- 10 files changed, 584 insertions(+), 386 deletions(-) diff --git a/src/base/base.cgh b/src/base/base.cgh index 362529f3..b40dff4c 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -795,6 +795,8 @@ Inline u64 MixU64s(u64 seed_a, u64 seed_b) #if IsCpu StringList GetRawCommandline(void); String GetAppName(void); + String GetEngineDirectory(void); + String GetLibsDirectory(void); String GetAppDirectory(void); void Echo(String msg); b32 Panic(String msg); diff --git a/src/base/base_log.h b/src/base/base_log.h index 514369fb..fc7b5229 100644 --- a/src/base/base_log.h +++ b/src/base/base_log.h @@ -18,7 +18,7 @@ Struct(LogEvent) Struct(LogEventsArray) { u64 count; - LogEvent *logs; + LogEvent *events; }; //////////////////////////////////////////////////////////// @@ -45,44 +45,6 @@ Struct(LogEventsArray) #define LogLevel_Trace 6 #define LogLevel_COUNT 7 -//////////////////////////////////////////////////////////// -//~ Log level types - -Struct(LogLevelSettings) -{ - String shorthand; -}; - -Global Readonly LogLevelSettings log_settings[LogLevel_COUNT] = { - [LogLevel_Critical] = { - CompLit("CRITICAL"), - }, - - [LogLevel_Error] = { - CompLit("ERROR"), - }, - - [LogLevel_Warning] = { - CompLit("WARNING"), - }, - - [LogLevel_Success] = { - CompLit("SUCCESS"), - }, - - [LogLevel_Info] = { - CompLit("INFO"), - }, - - [LogLevel_Debug] = { - CompLit("DEBUG"), - }, - - [LogLevel_Trace] = { - CompLit("TRACE"), - }, -}; - //////////////////////////////////////////////////////////// //~ Compile-time logging macros diff --git a/src/base/base_win32/base_win32.c b/src/base/base_win32/base_win32.c index 1e6584d7..96d3f370 100644 --- a/src/base/base_win32/base_win32.c +++ b/src/base/base_win32/base_win32.c @@ -48,6 +48,21 @@ String GetAppName(void) return W32.app_name; } +String GetEngineDirectory(void) +{ + return W32.engine_dir_path; +} + +String GetLibsDirectory(void) +{ + return W32.libs_dir_path; +} + +String GetAppDirectory(void) +{ + return W32.app_dir_path; +} + void Echo(String msg) { HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); @@ -233,11 +248,6 @@ void SleepSeconds(f64 seconds) } } -String GetAppDirectory(void) -{ - return W32.appdir_path; -} - //////////////////////////////////////////////////////////// //~ @hookimpl Swap @@ -323,89 +333,107 @@ void ExitNow(i32 code) ExitProcess(code); } +//////////////////////////////////////////////////////////// +//~ Error + +String W32_StringFromError(Arena *arena, i32 code) +{ + String result = Lit("Unknown error"); + { + wchar_t *msg_wstr = 0; + i64 msg_len = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, + code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR)&msg_wstr, + 0, + 0 + ); + result = StringFromWstr(arena, msg_wstr, msg_len); + if (msg_wstr) + { + LocalFree(msg_wstr); + } + } + return result; +} + //////////////////////////////////////////////////////////// //~ Log -void W32_BootstrapLogs(void) +void W32_LogEventToFile(LogEvent *ev, HANDLE file) { - Arena *perm = PermArena(); - W32.logs_arena = AcquireArena(Gibi(64)); - W32.log_msgs_arena = AcquireArena(Gibi(64)); - W32.readable_log_events = ArenaNext(W32.logs_arena, LogEvent); - String logfile_path = StringF(perm, "%F/log.log", FmtString(GetAppDirectory())); - wchar_t *path_wstr = WstrFromString(perm, logfile_path); - W32.logfile = CreateFileW( - path_wstr, - FILE_APPEND_DATA, - FILE_SHARE_READ | FILE_SHARE_WRITE, - 0, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - 0 - ); - Atomic32Set(&W32.logs_initialized, 1); - LogInfoF("Log file path: %F", FmtString(logfile_path)); + Struct(LogLevelSettings) + { + String shorthand; + }; + PERSIST Readonly LogLevelSettings level_settings[LogLevel_COUNT] = { + [LogLevel_Critical] = { CompLit("CRITICAL") }, + [LogLevel_Error] = { CompLit("ERROR") }, + [LogLevel_Warning] = { CompLit("WARNING") }, + [LogLevel_Success] = { CompLit("SUCCESS") }, + [LogLevel_Info] = { CompLit("INFO") }, + [LogLevel_Debug] = { CompLit("DEBUG") }, + [LogLevel_Trace] = { CompLit("TRACE") }, + }; + + TempArena scratch = BeginScratchNoConflict(); + { + LogLevelSettings settings = level_settings[ev->level]; + String shorthand = settings.shorthand; + String msg_formatted = StringF( + scratch.arena, + "[%F:%F:%F.%F] <%F> [%F] %F\n", + + // Time + FmtUint(ev->datetime.hour, .z = 2), + FmtUint(ev->datetime.minute, .z = 2), + FmtUint(ev->datetime.second, .z = 2), + FmtUint(ev->datetime.milliseconds, .z = 3), + + // Thread id + FmtUint(ev->thread_id, .z = 5), + + // Level + FmtString(shorthand), + + // Message + FmtString(ev->msg) + ); + WriteFile(file, msg_formatted.text, msg_formatted.len, 0, 0); + } + EndScratch(scratch); } void W32_Log(i32 level, String msg) { - TempArena scratch = BeginScratchNoConflict(); - if (Atomic32Fetch(&W32.logs_initialized)) + level = ClampI32(level, 0, LogLevel_COUNT - 1); + + DateTime datetime = LocalDateTime(); + i64 now_ns = TimeNs(); + i32 thread_id = GetCurrentThreadId(); + + LogEvent *ev = 0; + LockTicketMutex(&W32.logs_tm); { - LogLevelSettings settings = log_settings[level]; - if (level < 0 || level >= LogLevel_COUNT) - { - Panic(Lit("Invalid log level")); - } - - DateTime datetime = LocalDateTime(); - i64 now_ns = TimeNs(); - i32 thread_id = GetCurrentThreadId(); - - // TODO: Log asynchronously - - //- Log message to file - { - String shorthand = settings.shorthand; - String msg_formatted = StringF( - scratch.arena, - "[%F:%F:%F.%F] <%F> [%F] %F\n", - - // Time - FmtUint(datetime.hour, .z = 2), - FmtUint(datetime.minute, .z = 2), - FmtUint(datetime.second, .z = 2), - FmtUint(datetime.milliseconds, .z = 3), - - // Thread id - FmtUint(thread_id, .z = 5), - - // Level - FmtString(shorthand), - - // Message - FmtString(msg) - ); - WriteFile(W32.logfile, msg_formatted.text, msg_formatted.len, 0, 0); - } - - //- Log message to queue - LockTicketMutex(&W32.logs_tm); - { - // Get staged data - LogEvent *ev = PushStruct(W32.logs_arena, LogEvent); - ev->msg = PushString(W32.log_msgs_arena, msg); - ev->datetime = datetime; - ev->time_ns = now_ns; - ev->level = level; - ev->thread_id = thread_id; - ev->id = W32.logs_count++; - ev->level_id = W32.log_level_counts[level]++; - Atomic64Set(&W32.readable_logs_count, W32.logs_count); - } - UnlockTicketMutex(&W32.logs_tm); + // Get staged data + ev = PushStruct(W32.logs_arena, LogEvent); + ev->msg = PushString(W32.log_events_arena, msg); + ev->datetime = datetime; + ev->time_ns = now_ns; + ev->level = level; + ev->thread_id = thread_id; + ev->id = W32.logs_count++; + ev->level_id = W32.log_level_counts[level]++; + Atomic64Set(&W32.readable_logs_count, W32.logs_count); + } + UnlockTicketMutex(&W32.logs_tm); + + if (W32.logfile) + { + W32_LogEventToFile(ev, W32.logfile); } - EndScratch(scratch); } //////////////////////////////////////////////////////////// @@ -415,7 +443,7 @@ void W32_Log(i32 level, String msg) // immediately writing to log file. void LogPanic(String msg) { - if (Atomic32Fetch(&W32.logs_initialized)) + if (W32.logfile) { String beg = Lit("******** PANICKING ********\n"); String end = Lit("\n***************************\n"); @@ -432,18 +460,15 @@ void Log_(i32 level, String msg) void LogF_(i32 level, String fmt, ...) { - if (Atomic32Fetch(&W32.logs_initialized)) + TempArena scratch = BeginScratchNoConflict(); + va_list args; + va_start(args, fmt); { - TempArena scratch = BeginScratchNoConflict(); - va_list args; - va_start(args, fmt); - { - String msg = FormatString(scratch.arena, fmt, FmtArgsFromVaList(scratch.arena, args)); - W32_Log(level, msg); - } - va_end(args); - EndScratch(scratch); + String msg = FormatString(scratch.arena, fmt, FmtArgsFromVaList(scratch.arena, args)); + W32_Log(level, msg); } + va_end(args); + EndScratch(scratch); } LogEventsArray GetLogEvents(void) @@ -452,7 +477,7 @@ LogEventsArray GetLogEvents(void) result.count = Atomic64Fetch(&W32.readable_logs_count); if (result.count > 0) { - result.logs = W32.readable_log_events; + result.events = W32.readable_log_events; } return result; } @@ -498,6 +523,11 @@ i32 W32_Main(void) // Query system info GetSystemInfo(&W32.info); + // Setup logging memory + W32.logs_arena = AcquireArena(Gibi(64)); + W32.log_events_arena = AcquireArena(Gibi(64)); + W32.readable_log_events = ArenaNext(W32.logs_arena, LogEvent); + // Init main thread W32_InitCurrentThread(Lit("Main")); @@ -534,96 +564,141 @@ i32 W32_Main(void) } ////////////////////////////// - //- Bootstrap + //- Bootstrap tweak vars - // Bootstrap tweak vars BootstrapTweakVars(); - // Bootstrap command line + ////////////////////////////// + //- Bootstrap command line + BootstrapCmdline(); - // Init app directory - String appdir_error = Zi; - { - String appdir_path = Zi; - CommandlineArg appdir_arg = CommandlineArgFromName(Lit("appdir")); - CommandlineArg app_name_arg = CommandlineArgFromName(Lit("app_name")); - if (appdir_arg.exists && appdir_arg.value.len > 0) - { - appdir_path = appdir_arg.value; - } - else - { - String app_name = Lit(Stringize(DefaultAppName)); - if (app_name_arg.exists && app_name_arg.value.len > 0) - { - app_name = app_name_arg.value; - } - W32.app_name = app_name; + ////////////////////////////// + //- Initialize app directories - wchar_t *path_wstr = 0; - HRESULT hr = SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, 0, &path_wstr); + { + String app_name = CommandlineArgFromName(Lit("app_name")).value; + if (!app_name.len) + { + app_name = StringFromCstrNoLimit(Stringize(DefaultAppName)); + } + W32.app_name = app_name; + + String appdata_path = Zi; + { + wchar_t *appdata_path_wstr = 0; + HRESULT hr = SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, 0, &appdata_path_wstr); if (!SUCCEEDED(hr)) { - Panic(Lit("Failed to locate AppData directory")); + Panic(Lit("Failed to locate AppData/Local directory")); } - appdir_path = StringFromWstrNoLimit(perm, path_wstr); - CoTaskMemFree(path_wstr); - appdir_path = PathFromString(perm, StringF(perm, "%F\\Cabin\\%F\\", FmtString(appdir_path), FmtString(app_name)), '/'); + appdata_path = PathFromString(perm, StringFromWstrNoLimit(perm, appdata_path_wstr), '/'); + CoTaskMemFree(appdata_path_wstr); } - // Create app dir + + W32.engine_dir_path = StringF(perm, "%F/Cabin/", FmtString(appdata_path)); + W32.libs_dir_path = StringF(perm, "%F/libs/", FmtString(W32.engine_dir_path)); + W32.app_dir_path = StringF(perm, "%F/%F/", FmtString(W32.engine_dir_path), FmtString(app_name)); + + // Initialize engine/app dir { - String path = PathFromString(perm, appdir_path, '\\'); + String path = PathFromString(perm, W32.app_dir_path, '\\'); wchar_t *path_wstr = WstrFromString(perm, path); - i32 err_code = SHCreateDirectoryExW(0, path_wstr, 0); - String err = StringF(perm, "Error code %F", FmtSint(err_code)); - switch (err_code) + i32 err = SHCreateDirectoryExW(0, path_wstr, 0); + if (err != ERROR_SUCCESS && err != ERROR_ALREADY_EXISTS && err != ERROR_FILE_EXISTS) { - default: break; - case ERROR_BAD_PATHNAME: - { - err = Lit("Bad path name"); - } break; - case ERROR_FILENAME_EXCED_RANGE: - { - err = Lit("Path name too long"); - } break; - case ERROR_CANCELLED: - { - err = Lit("User canceled the operation"); - } break; - case ERROR_PATH_NOT_FOUND: - { - err = Lit("The system cannot find the path specified."); - } break; - } - if (err_code != ERROR_SUCCESS && err_code != ERROR_ALREADY_EXISTS && err_code != ERROR_FILE_EXISTS) - { - appdir_error = StringF( + String msg = StringF( perm, "Failed to initialize app directory at \"%F\": %F", FmtString(path), - FmtString(err) + FmtString(W32_StringFromError(perm, err)) ); - wchar_t *msg_wstr = WstrFromString(perm, appdir_error); - MessageBoxExW(0, msg_wstr, L"Warning", MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST, 0); + LogError(msg); + MessageBoxExW(0, WstrFromString(perm, msg), L"Warning", MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST, 0); } } - W32.appdir_path = appdir_path; } - // Bootstrap log system - W32_BootstrapLogs(); + // Initialize libs dir + { + String path = PathFromString(perm, W32.libs_dir_path, '\\'); + wchar_t *path_wstr = WstrFromString(perm, path); + i32 err = SHCreateDirectoryExW(0, path_wstr, 0); + if (err != ERROR_SUCCESS && err != ERROR_ALREADY_EXISTS && err != ERROR_FILE_EXISTS) + { + String msg = StringF( + perm, + "Failed to initialize libs directory at \"%F\": %F", + FmtString(path), + FmtString(W32_StringFromError(perm, err)) + ); + LogError(msg); + } + else + { + err = SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + if (err != ERROR_SUCCESS) + { + LogErrorF( + "Failed call to SetDefaultDllDirectories: %F", + FmtString(W32_StringFromError(perm, err)) + ); + } + else + { + String libs_path = PathFromString(perm, StringF(perm, "%F/libs/", FmtString(W32.engine_dir_path)), '\\'); + wchar_t *libs_path_wstr = WstrFromString(perm, libs_path); + DLL_DIRECTORY_COOKIE cookie = AddDllDirectory(libs_path_wstr); + err = GetLastError(); + if (!cookie || err != ERROR_SUCCESS) + { + LogErrorF( + "Failed to add libs directory to dll search path at \"%F\": %F", + FmtString(path), + FmtString(W32_StringFromError(perm, err)) + ); + } + } + } + } + + ////////////////////////////// + //- Initialize log file + + { + String logfile_path = StringF(perm, "%F/log.log", FmtString(GetAppDirectory())); + wchar_t *path_wstr = WstrFromString(perm, logfile_path); + LogInfoF("Log file path: %F", FmtString(logfile_path)); + W32.logfile = CreateFileW( + path_wstr, + FILE_APPEND_DATA, + FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + 0 + ); + + if (W32.logfile) + { + LogEventsArray unwritten_log_events = GetLogEvents(); + for (u64 ev_idx = 0; ev_idx < unwritten_log_events.count; ++ev_idx) + { + LogEvent *ev = &unwritten_log_events.events[ev_idx]; + W32_LogEventToFile(ev, W32.logfile); + } + } + else + { + LogErrorF("Failed to create log file at path: %F", FmtString(logfile_path)); + } + } + LogInfoF("Command line: [%F]", FmtString(cmdline_str)); if (W32.wine_version.len > 0) { LogInfoF("Wine version: \"%F\"", FmtString(W32.wine_version)); } - if (appdir_error.len > 0) - { - LogError(appdir_error); - } - // Bootstrap resource system { W32_FindEmbeddedDataCtx ctx = Zi; @@ -631,10 +706,14 @@ i32 W32_Main(void) BootstrapResources(ctx.embedded_strings_count, ctx.embedded_strings); } - // Bootstrap async + ////////////////////////////// + //- Bootstrap async + BootstrapAsync(); - // Bootstrap layers + ////////////////////////////// + //- Bootstrap layers + if (!Atomic32Fetch(&W32.panicking)) { BootstrapLayers(); diff --git a/src/base/base_win32/base_win32.h b/src/base/base_win32/base_win32.h index 6ee8538e..5e2ab51f 100644 --- a/src/base/base_win32/base_win32.h +++ b/src/base/base_win32/base_win32.h @@ -6,32 +6,25 @@ #define COBJMACROS #define WIN32_LEAN_AND_MEAN #define UNICODE -// #pragma warning(push, 0) - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include -// #pragma warning(pop) - -#ifndef BCRYPT_RNG_ALG_HANDLE - #define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081) - u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags); -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //- Windows libs @@ -49,21 +42,16 @@ #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "advapi32.lib") -//////////////////////////////////////////////////////////// -//~ Embedded data iter types - -Struct(W32_FindEmbeddedDataCtx) -{ - u64 embedded_strings_count; - String embedded_strings[64]; -}; - -//////////////////////////////////////////////////////////// -//~ API types +//- Windows API typedef char *W32_WineVersionFunc(void); typedef BOOL W32_IsWindowArrangedFunc(HWND hwnd); +#ifndef BCRYPT_RNG_ALG_HANDLE + #define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081) + u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags); +#endif + Struct(W32_Api) { struct @@ -79,6 +67,15 @@ Struct(W32_Api) } func; }; +//////////////////////////////////////////////////////////// +//~ Embedded data iter types + +Struct(W32_FindEmbeddedDataCtx) +{ + u64 embedded_strings_count; + String embedded_strings[64]; +}; + //////////////////////////////////////////////////////////// //~ State types @@ -96,7 +93,9 @@ Struct(W32_Ctx) StringList raw_command_line; String app_name; - String appdir_path; + String engine_dir_path; + String libs_dir_path; + String app_dir_path; //- Application control flow @@ -113,11 +112,10 @@ Struct(W32_Ctx) //- Logs HANDLE logfile; - Atomic32 logs_initialized; TicketMutex logs_tm; - Arena *log_msgs_arena; Arena *logs_arena; + Arena *log_events_arena; u64 logs_count; u64 log_level_counts[LogLevel_COUNT]; @@ -133,10 +131,15 @@ extern W32_Ctx W32; #define W32_EmbeddedDataPrefix EMBEDDED_RESOURCE_DATA__ BOOL W32_FindEmbeddedRcData(HMODULE module, LPCWSTR type, LPWSTR wstr_entry_name, LONG_PTR udata); +//////////////////////////////////////////////////////////// +//~ Error + +String W32_StringFromError(Arena *arena, i32 code); + //////////////////////////////////////////////////////////// //~ Log -void W32_BootstrapLogs(void); +void W32_LogEventToFile(LogEvent *ev, HANDLE file); void W32_Log(i32 level, String msg); //////////////////////////////////////////////////////////// diff --git a/src/gpu/gpu_core.h b/src/gpu/gpu_core.h index af16ca8e..c99ada48 100644 --- a/src/gpu/gpu_core.h +++ b/src/gpu/gpu_core.h @@ -572,6 +572,26 @@ u32 G_PushRef(G_ArenaHandle arena, G_ResourceHandle resource, G_RefDesc desc); G_CommandListHandle G_PrepareCommandList(G_QueueKind queue); i64 G_CommitCommandList(G_CommandListHandle cl); +//- Constant + +void G_SetConstantEx(G_CommandListHandle cl, i32 slot, void *src_32bit, u32 size); + +#define G_SetConstant(cl, name, value) do { \ + CAT(name, __shaderconstanttype) __src; \ + __src.v = value; \ + G_SetConstantEx((cl), (name), &__src, sizeof(__src)); \ + } while (0) + +//- Barrier + +void G_Sync(G_CommandListHandle cl); +void G_SyncLayout(G_CommandListHandle cl, G_ResourceHandle resource, G_Layout layout); + +//- Event + +void G_BeginEvent(G_CommandListHandle cl, String name); +void G_EndEvent(G_CommandListHandle cl); + //- Cpu -> Gpu staged copy void G_CopyCpuToBuffer(G_CommandListHandle cl, G_ResourceHandle dst, u64 dst_offset, void *src, RngU64 src_copy_range); @@ -584,21 +604,6 @@ void G_CopyBufferToTexture(G_CommandListHandle cl_handle, G_ResourceHandle dst_h void G_CopyTextureToTexture(G_CommandListHandle cl, G_ResourceHandle dst, Vec3I32 dst_offset, G_ResourceHandle src, Rng3I32 src_copy_range); void G_CopyTextureToBuffer(G_CommandListHandle cl, G_ResourceHandle dst, Vec3I32 dst_offset, G_ResourceHandle src, Rng3I32 src_copy_range); -//- Constant - -void G_SetConstantEx(G_CommandListHandle cl, i32 slot, void *src_32bit, u32 size); - -#define G_SetConstant(cl, name, value) do { \ - CAT(name, __shaderconstanttype) __src; \ - __src.v = value; \ - G_SetConstantEx((cl), (name), &__src, sizeof(__src)); \ - } while (0) - -//- Sync - -void G_Sync(G_CommandListHandle cl); -void G_SyncLayout(G_CommandListHandle cl, G_ResourceHandle resource, G_Layout layout); - //- Compute void G_ComputeEx(G_CommandListHandle cl, ComputeShaderDesc cs, Vec3I32 threads); diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index 79ff85fd..d29e6fcd 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -13,17 +13,47 @@ void G_Bootstrap(void) G_D12.independent_devices_enabled = !CommandlineArgFromName(Lit("no-d3d12-independent-devices")).exists; G_D12.validation_layer_enabled = CommandlineArgFromName(Lit("gpu-debug-validation")).exists; G_D12.debug_layer_enabled = G_D12.validation_layer_enabled || CommandlineArgFromName(Lit("gpu-debug")).exists; + G_D12.events_enabled = IsDeveloperModeEnabled; if (G_D12.independent_devices_enabled && IsRunningInWine()) { + // NOTE: Independent devices only supported in newer versions of Proton, which just ignores them anyway LogInfoF("Wine detected, disabling D3D12 independent devices"); G_D12.independent_devices_enabled = 0; } LogInfoF("D3D12 independent devices enabled: %F", FmtSint(G_D12.independent_devices_enabled)); + LogInfoF("D3D12 events enabled: %F", FmtSint(G_D12.events_enabled)); LogInfoF("D3D12 debug layer enabled: %F", FmtSint(G_D12.debug_layer_enabled)); LogInfoF("D3D12 validation layer enabled: %F", FmtSint(G_D12.validation_layer_enabled)); + ////////////////////////////// + //- Load pix event runtime + + if (G_D12.events_enabled) + { + HMODULE pix = LoadLibraryW(L"WinPixEventRuntime"); + if (pix) + { + G_D12_PixBeginEventOnCommandList = (G_D12_PixBeginEventOnCommandListFunc *)GetProcAddress(pix, "PIXBeginEventOnCommandList"); + G_D12_PixEndEventOnCommandList = (G_D12_PixEndEventOnCommandListFunc *)GetProcAddress(pix, "PIXEndEventOnCommandList"); + G_D12_PixSetMarkerOnCommandList = (G_D12_PixSetMarkerOnCommandListFunc *)GetProcAddress(pix, "PIXSetMarkerOnCommandList"); + if (!G_D12_PixBeginEventOnCommandList && !G_D12_PixEndEventOnCommandList && !G_D12_PixSetMarkerOnCommandList) + { + LogErrorF("Failed to retrieve pix procedures"); + } + else + { + LogInfoF("Pix enabled"); + G_D12.pix_enabled = 1; + } + } + else + { + LogInfoF("Pix event runtime not found"); + } + } + ////////////////////////////// //- Initialize independent device factory with Agility SDK @@ -32,11 +62,11 @@ void G_Bootstrap(void) ////////////////////////////// //- Extract agility SDK - String appdir = GetAppDirectory(); + String libs_dir = GetLibsDirectory(); u32 sdk_ver_num = 619; String sdk_ver_str = Lit("1.619.0"); - String sdk_dir_path = StringF(scratch.arena, "%Fd3d12/%F/", FmtString(appdir), FmtString(sdk_ver_str)); + String sdk_dir_path = StringF(scratch.arena, "%Fd3d12/%F/", FmtString(libs_dir), FmtString(sdk_ver_str)); { LogInfoF("D3D12 agility sdk path: \"%F\"", FmtString(sdk_dir_path)); String core_path = StringF(scratch.arena, "%FD3D12Core.dll", FmtString(sdk_dir_path)); @@ -48,9 +78,9 @@ void G_Bootstrap(void) ResourceKey layers_key = ResourceKeyFromStore(&G_D12_Resources, Lit("AgilitySDK/1.619.0/d3d12SDKLayers.dat")); String core_data = PLT_Decompress(scratch.arena, DataFromResource(core_key), PLT_CompressionLevel_3); String layers_data = PLT_Decompress(scratch.arena, DataFromResource(layers_key), PLT_CompressionLevel_3); - PLT_MkDir(StringF(scratch.arena, "%Fd3d12/", FmtString(appdir))); - PLT_MkDir(StringF(scratch.arena, "%Fd3d12/", FmtString(appdir))); - PLT_MkDir(StringF(scratch.arena, "%Fd3d12/%F/", FmtString(appdir), FmtString(sdk_ver_str))); + PLT_MkDir(StringF(scratch.arena, "%Fd3d12/", FmtString(libs_dir))); + PLT_MkDir(StringF(scratch.arena, "%Fd3d12/", FmtString(libs_dir))); + PLT_MkDir(StringF(scratch.arena, "%Fd3d12/%F/", FmtString(libs_dir), FmtString(sdk_ver_str))); { PLT_File file = PLT_OpenFileWrite(core_path); PLT_WriteFile(file, core_data); @@ -302,8 +332,8 @@ void G_Bootstrap(void) { Panic(Lit("Failed to retrieve DXGI debug interface")); } - // IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, 1); - // IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, 1); + IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, 1); + IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, 1); } } @@ -588,26 +618,16 @@ DXGI_FORMAT G_D12_DxgiFormatFromGpuFormat(G_Format format) return (DXGI_FORMAT)format; } -D3D12_BARRIER_LAYOUT G_D12_BarrierLayoutFromUsageKind(G_QueueKind queue_kind, G_D12_TrackedUsageKind usage_kind) +D3D12_BARRIER_LAYOUT G_D12_CommonLayoutFromQueueKind(G_QueueKind queue_kind) { - D3D12_BARRIER_LAYOUT untracked_layout; - switch (queue_kind) + D3D12_BARRIER_LAYOUT result = D3D12_BARRIER_LAYOUT_COMMON; + if (queue_kind == G_QueueKind_Direct) { - default: untracked_layout = D3D12_BARRIER_LAYOUT_COMMON; break; - case G_QueueKind_Direct: untracked_layout = D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON; break; - case G_QueueKind_AsyncCompute: untracked_layout = D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON; break; + result = D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON; } - - D3D12_BARRIER_LAYOUT result; - switch(usage_kind) + else if (queue_kind == G_QueueKind_AsyncCompute) { - default: - case G_D12_TrackedUsageKind_Untracked: result = untracked_layout; break; - case G_D12_TrackedUsageKind_RenderTarget: result = D3D12_BARRIER_LAYOUT_RENDER_TARGET; break; - case G_D12_TrackedUsageKind_DepthStencilRead: result = D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ; break; - case G_D12_TrackedUsageKind_DepthStencilReadWrite: result = D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE; break; - case G_D12_TrackedUsageKind_MakeCommon: result = D3D12_BARRIER_LAYOUT_COMMON; break; - case G_D12_TrackedUsageKind_MakeExclusive: result = untracked_layout; break; + result = D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON; } return result; } @@ -2077,6 +2097,9 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size) return result; } +//////////////////////////////////////////////////////////// +//~ Tracking + void G_D12_UpdateTrackedUsage(Arena *arena, G_D12_CmdBatch *batch, G_D12_Resource *resource, RngI32 mips, G_D12_TrackedUsageKind usage_kind) { b32 should_track = !AnyBit(resource->d3d_desc.Flags, D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS); @@ -2107,6 +2130,7 @@ void G_D12_UpdateTrackedUsage(Arena *arena, G_D12_CmdBatch *batch, G_D12_Resourc tmp = PushStruct(arena, G_D12_TrackedResourceNode); tmp->resource = resource; tmp->hash = hash; + ++batch->tracked_resources_count; SllQueuePush(batch->first_tracked_resource, batch->last_tracked_resource, tmp); SllStackPushN(bin->first, tmp, next_in_bin); } @@ -2154,15 +2178,15 @@ void G_D12_UpdateTrackedUsage(Arena *arena, G_D12_CmdBatch *batch, G_D12_Resourc mip->usage = usage_kind; } - if (usage_kind == G_D12_TrackedUsageKind_MakeExclusive) + if (usage_kind == G_D12_TrackedUsageKind_Acquire) { - mip->prev_usage = G_D12_TrackedUsageKind_MakeCommon; + mip->prev_usage = G_D12_TrackedUsageKind_Release; } else { - if (usage_kind == G_D12_TrackedUsageKind_MakeCommon) + if (usage_kind == G_D12_TrackedUsageKind_Release) { - mip->next_usage = G_D12_TrackedUsageKind_MakeCommon; + mip->next_usage = G_D12_TrackedUsageKind_Release; } if (prev_mip) { @@ -2179,6 +2203,109 @@ void G_D12_UpdateTrackedUsage(Arena *arena, G_D12_CmdBatch *batch, G_D12_Resourc } } +G_D12_BarrierInfo G_D12_BarrierInfoFromBatch(G_D12_CmdBatch *batch, G_QueueKind queue_kind) +{ + G_D12_BarrierInfo result = Zi; + + if (batch->contains_compute_shader) + { + result.sync |= D3D12_BARRIER_SYNC_COMPUTE_SHADING; + result.access |= D3D12_BARRIER_ACCESS_UNORDERED_ACCESS | D3D12_BARRIER_ACCESS_SHADER_RESOURCE; + } + if (batch->contains_draw_shader) + { + result.sync |= D3D12_BARRIER_SYNC_VERTEX_SHADING | D3D12_BARRIER_SYNC_PIXEL_SHADING; + result.access |= D3D12_BARRIER_ACCESS_UNORDERED_ACCESS | D3D12_BARRIER_ACCESS_SHADER_RESOURCE; + } + if (batch->contains_indirect) + { + result.sync |= D3D12_BARRIER_SYNC_EXECUTE_INDIRECT; + result.access |= D3D12_BARRIER_ACCESS_INDIRECT_ARGUMENT; + } + if (batch->contains_rtv) + { + result.sync |= D3D12_BARRIER_SYNC_RENDER_TARGET; + result.access |= D3D12_BARRIER_ACCESS_RENDER_TARGET; + } + if (batch->contains_dsv_read) + { + result.sync |= D3D12_BARRIER_SYNC_DEPTH_STENCIL; + result.access |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_READ; + } + if (batch->contains_dsv_write) + { + result.sync |= D3D12_BARRIER_SYNC_DEPTH_STENCIL; + result.access |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE; + } + if (batch->contains_copy) + { + result.sync |= D3D12_BARRIER_SYNC_COPY; + result.access |= D3D12_BARRIER_ACCESS_COPY_DEST | D3D12_BARRIER_ACCESS_COPY_SOURCE; + } + + return result; +} + +G_D12_BarrierInfo G_D12_BarrierInfoFromUsageKind(G_D12_TrackedUsageKind usage_kind, G_D12_Resource *resource, G_D12_BarrierInfo global, G_QueueKind queue_kind) +{ + G_D12_BarrierInfo result = Zi; + + { + if (usage_kind == G_D12_TrackedUsageKind_RenderTarget) + { + result.layout = D3D12_BARRIER_LAYOUT_RENDER_TARGET; + result.sync |= D3D12_BARRIER_SYNC_RENDER_TARGET; + result.access |= D3D12_BARRIER_ACCESS_RENDER_TARGET; + } + else if (usage_kind == G_D12_TrackedUsageKind_DepthStencilRead) + { + result.layout = D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ; + + result.sync |= D3D12_BARRIER_SYNC_DEPTH_STENCIL; + result.sync |= (global.sync & D3D12_BARRIER_SYNC_COPY); + result.sync |= (global.sync & D3D12_BARRIER_SYNC_VERTEX_SHADING); + result.sync |= (global.sync & D3D12_BARRIER_SYNC_PIXEL_SHADING); + result.sync |= (global.sync & D3D12_BARRIER_SYNC_COMPUTE_SHADING); + + result.access |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_READ; + result.access |= (global.access & D3D12_BARRIER_ACCESS_COPY_SOURCE); + result.access |= (global.access & D3D12_BARRIER_ACCESS_SHADER_RESOURCE); + } + else if (usage_kind == G_D12_TrackedUsageKind_DepthStencilReadWrite) + { + result.layout = D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE; + result.sync |= D3D12_BARRIER_SYNC_DEPTH_STENCIL; + result.access |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE; + } + else + { + if (usage_kind == G_D12_TrackedUsageKind_Release) + { + result.layout = D3D12_BARRIER_LAYOUT_COMMON; + } + else + { + result.layout = G_D12_CommonLayoutFromQueueKind(queue_kind); + if (resource->d3d_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) + { + result.access |= (global.access & D3D12_BARRIER_ACCESS_UNORDERED_ACCESS); + } + } + + result.sync |= D3D12_BARRIER_SYNC_VERTEX_SHADING; + result.sync |= D3D12_BARRIER_SYNC_PIXEL_SHADING; + result.sync |= D3D12_BARRIER_SYNC_COMPUTE_SHADING; + result.sync |= (global.sync & D3D12_BARRIER_SYNC_COPY); + + result.access |= D3D12_BARRIER_ACCESS_SHADER_RESOURCE; + result.access |= (global.access & D3D12_BARRIER_ACCESS_COPY_SOURCE); + result.access |= (global.access & D3D12_BARRIER_ACCESS_COPY_DEST); + } + } + + return result; +} + //////////////////////////////////////////////////////////// //~ @hookimpl Command @@ -2259,7 +2386,11 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) G_D12_Cmd *cmd = &cmds[cmd_idx]; G_D12_CmdKind cmd_kind = cmd->kind; - if (cmd_kind != G_D12_CmdKind_Barrier && cmd_kind != G_D12_CmdKind_Constant) + if ( + cmd_kind != G_D12_CmdKind_Barrier && + cmd_kind != G_D12_CmdKind_Constant && + cmd_kind != G_D12_CmdKind_Event + ) { batch->contains_hazard = 1; } @@ -2305,7 +2436,7 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) } else if (is_dsv) { - batch->contains_dsv = 1; + batch->contains_dsv_write = 1; G_D12_UpdateTrackedUsage(scratch.arena, batch, resource, RNGI32(0, resource->texture_mips - 1), G_D12_TrackedUsageKind_DepthStencilReadWrite); } } @@ -2327,13 +2458,13 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) G_D12_Resource *resource = cmd->barrier.resource; if (resource) { - if (cmd->barrier.to_exclusive) + if (cmd->barrier.acquire) { - G_D12_UpdateTrackedUsage(scratch.arena, batch, resource, RNGI32(0, resource->texture_mips - 1), G_D12_TrackedUsageKind_MakeExclusive); + G_D12_UpdateTrackedUsage(scratch.arena, batch, resource, RNGI32(0, resource->texture_mips - 1), G_D12_TrackedUsageKind_Acquire); } else { - G_D12_UpdateTrackedUsage(scratch.arena, batch, resource, RNGI32(0, resource->texture_mips - 1), G_D12_TrackedUsageKind_MakeCommon); + G_D12_UpdateTrackedUsage(scratch.arena, batch, resource, RNGI32(0, resource->texture_mips - 1), G_D12_TrackedUsageKind_Release); } } } @@ -2467,32 +2598,26 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) u64 texture_barriers_count = batch->transitions_count; D3D12_TEXTURE_BARRIER *texture_barriers = PushStructs(scratch.arena, D3D12_TEXTURE_BARRIER, texture_barriers_count); - // TODO: Granular - D3D12_BARRIER_SYNC sync_before = D3D12_BARRIER_SYNC_ALL; - D3D12_BARRIER_SYNC sync_after = D3D12_BARRIER_SYNC_ALL; - D3D12_BARRIER_ACCESS access_before = D3D12_BARRIER_ACCESS_COMMON; - D3D12_BARRIER_ACCESS access_after = D3D12_BARRIER_ACCESS_COMMON; - b32 is_transition_batch = batch->cmds_count == 0; + + G_D12_BarrierInfo global_after = G_D12_BarrierInfoFromBatch(batch, queue_kind); + G_D12_BarrierInfo global_before = Zi; + if (batch->prev) + { + global_before = G_D12_BarrierInfoFromBatch(batch->prev, queue_kind); + } + if (batch == first_batch) { is_transition_batch = 1; - sync_before = D3D12_BARRIER_SYNC_NONE; - access_before = D3D12_BARRIER_ACCESS_NO_ACCESS; + global_before.sync = D3D12_BARRIER_SYNC_NONE; + global_before.access = D3D12_BARRIER_ACCESS_NO_ACCESS; } if (batch == last_batch) { is_transition_batch = 1; - sync_after = D3D12_BARRIER_SYNC_NONE; - access_after = D3D12_BARRIER_ACCESS_NO_ACCESS; - } - - D3D12_GLOBAL_BARRIER global_barrier = Zi; - { - global_barrier.SyncBefore = sync_before; - global_barrier.SyncAfter = sync_after; - global_barrier.AccessBefore = access_before; - global_barrier.AccessAfter = access_after; + global_after.sync = D3D12_BARRIER_SYNC_NONE; + global_after.access = D3D12_BARRIER_ACCESS_NO_ACCESS; } // Push transition barriers @@ -2501,27 +2626,39 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) for (G_D12_TransitionNode *tn = batch->first_transition; tn; tn = tn->next) { G_D12_Resource *resource = tn->resource; - D3D12_BARRIER_LAYOUT old_layout = G_D12_BarrierLayoutFromUsageKind(queue_kind, tn->old); - D3D12_BARRIER_LAYOUT new_layout = G_D12_BarrierLayoutFromUsageKind(queue_kind, tn->new); + G_D12_TrackedUsageKind old_usage = tn->old; + G_D12_TrackedUsageKind new_usage = tn->new; + G_D12_BarrierInfo resource_before = G_D12_BarrierInfoFromUsageKind(old_usage, resource, global_before, queue_kind); + G_D12_BarrierInfo resource_after = G_D12_BarrierInfoFromUsageKind(new_usage, resource, global_after, queue_kind); + // D3D12_BARRIER_LAYOUT layout_before = G_D12_BarrierLayoutFromUsageKind(old_usage, queue_kind); + // D3D12_BARRIER_LAYOUT layout_after = G_D12_BarrierLayoutFromUsageKind(new_usage, queue_kind); D3D12_TEXTURE_BARRIER *barrier = &texture_barriers[barrier_idx]; - barrier->SyncBefore = sync_before; - barrier->SyncAfter = sync_after; - barrier->AccessBefore = access_before; - barrier->AccessAfter = access_after; - barrier->LayoutBefore = old_layout; - barrier->LayoutAfter = new_layout; - barrier->pResource = resource->d3d_resource; - barrier->Subresources.NumArraySlices = 1; - barrier->Subresources.NumPlanes = 1; - barrier->Subresources.IndexOrFirstMipLevel = tn->mips.min; - barrier->Subresources.NumMipLevels = tn->mips.max - tn->mips.min + 1; + { + barrier->SyncBefore = resource_before.sync; + barrier->SyncAfter = resource_after.sync; + barrier->AccessBefore = resource_before.access; + barrier->AccessAfter = resource_after.access; + barrier->LayoutBefore = resource_before.layout; + barrier->LayoutAfter = resource_after.layout; + barrier->pResource = resource->d3d_resource; + barrier->Subresources.NumArraySlices = 1; + barrier->Subresources.NumPlanes = 1; + barrier->Subresources.IndexOrFirstMipLevel = tn->mips.min; + barrier->Subresources.NumMipLevels = tn->mips.max - tn->mips.min + 1; + } ++barrier_idx; } } // Dispatch barriers { + D3D12_GLOBAL_BARRIER global_barrier = Zi; + global_barrier.SyncBefore = global_before.sync; + global_barrier.SyncAfter = global_before.sync; + global_barrier.AccessBefore = global_before.access; + global_barrier.AccessAfter = global_before.access; + u32 barrier_groups_count = 0; D3D12_BARRIER_GROUP barrier_groups[2] = Zi; if (!is_transition_batch) @@ -3012,6 +3149,51 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle) return completion_target; } +//- Constant + +void G_SetConstantEx(G_CommandListHandle cl_handle, i32 slot, void *src_32bit, u32 size) +{ + G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); + G_D12_Cmd *cmd = G_D12_PushCmd(cl); + cmd->kind = G_D12_CmdKind_Constant; + cmd->constant.slot = slot; + CopyBytes(&cmd->constant.value, src_32bit, MinU32(size, 4)); +} + +//- Barrier + +void G_Sync(G_CommandListHandle cl_handle) +{ + G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); + G_D12_Cmd *cmd = G_D12_PushCmd(cl); + cmd->kind = G_D12_CmdKind_Barrier; +} + +void G_SyncLayout(G_CommandListHandle cl_handle, G_ResourceHandle resource_handle, G_Layout layout) +{ + G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); + G_D12_Cmd *cmd = G_D12_PushCmd(cl); + cmd->kind = G_D12_CmdKind_Barrier; + cmd->barrier.resource = G_D12_ResourceFromHandle(resource_handle); + cmd->barrier.acquire = layout == G_Layout_Exclusive; +} + +//- Event + +void G_BeginEvent(G_CommandListHandle cl_handle, String name) +{ + G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); + G_D12_Cmd *cmd = G_D12_PushCmd(cl); + cmd->kind = G_D12_CmdKind_Event; +} + +void G_EndEvent(G_CommandListHandle cl_handle) +{ + G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); + G_D12_Cmd *cmd = G_D12_PushCmd(cl); + cmd->kind = G_D12_CmdKind_Event; +} + //- Cpu -> Gpu staged copy void G_CopyCpuToBuffer(G_CommandListHandle cl_handle, G_ResourceHandle dst_handle, u64 dst_offset, void *src, RngU64 src_copy_range) @@ -3217,35 +3399,6 @@ void G_CopyTextureToBuffer(G_CommandListHandle cl_handle, G_ResourceHandle dst_h Assert(0); } -//- Constant - -void G_SetConstantEx(G_CommandListHandle cl_handle, i32 slot, void *src_32bit, u32 size) -{ - G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); - G_D12_Cmd *cmd = G_D12_PushCmd(cl); - cmd->kind = G_D12_CmdKind_Constant; - cmd->constant.slot = slot; - CopyBytes(&cmd->constant.value, src_32bit, MinU32(size, 4)); -} - -//- Barrier - -void G_Sync(G_CommandListHandle cl_handle) -{ - G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); - G_D12_Cmd *cmd = G_D12_PushCmd(cl); - cmd->kind = G_D12_CmdKind_Barrier; -} - -void G_SyncLayout(G_CommandListHandle cl_handle, G_ResourceHandle resource_handle, G_Layout layout) -{ - G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle); - G_D12_Cmd *cmd = G_D12_PushCmd(cl); - cmd->kind = G_D12_CmdKind_Barrier; - cmd->barrier.resource = G_D12_ResourceFromHandle(resource_handle); - cmd->barrier.to_exclusive = layout == G_Layout_Exclusive; -} - //- Compute void G_ComputeEx(G_CommandListHandle cl_handle, ComputeShaderDesc cs, Vec3I32 threads) @@ -3477,7 +3630,7 @@ G_ResourceHandle G_PrepareBackbuffer(G_SwapchainHandle swapchain_handle, G_Forma desc.Height = size.y; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; - desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; desc.BufferCount = G_D12_SwapchainBufferCount; desc.Scaling = DXGI_SCALING_NONE; desc.Flags = G_D12_SwapchainFlags; diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.h b/src/gpu/gpu_dx12/gpu_dx12_core.h index fcee93b2..a23313ed 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.h +++ b/src/gpu/gpu_dx12/gpu_dx12_core.h @@ -10,6 +10,14 @@ #pragma comment(lib, "d3d12") #pragma comment(lib, "dxgi") +//- Pix +typedef void(WINAPI* G_D12_PixBeginEventOnCommandListFunc)(ID3D12GraphicsCommandList* commandList, UINT64 color, _In_ PCSTR formatString); +typedef void(WINAPI* G_D12_PixEndEventOnCommandListFunc)(ID3D12GraphicsCommandList* commandList); +typedef void(WINAPI* G_D12_PixSetMarkerOnCommandListFunc)(ID3D12GraphicsCommandList* commandList, UINT64 color, _In_ PCSTR formatString); +G_D12_PixBeginEventOnCommandListFunc *G_D12_PixBeginEventOnCommandList; +G_D12_PixEndEventOnCommandListFunc *G_D12_PixEndEventOnCommandList; +G_D12_PixSetMarkerOnCommandListFunc *G_D12_PixSetMarkerOnCommandList; + //////////////////////////////////////////////////////////// //~ Tweakable definitions @@ -300,8 +308,9 @@ Struct(G_D12_ReleasableList) Enum(G_D12_CmdKind) { G_D12_CmdKind_None, - G_D12_CmdKind_Barrier, G_D12_CmdKind_Constant, + G_D12_CmdKind_Barrier, + G_D12_CmdKind_Event, G_D12_CmdKind_CopyBytes, G_D12_CmdKind_CopyTexels, G_D12_CmdKind_Compute, @@ -324,7 +333,7 @@ Struct(G_D12_Cmd) struct { G_D12_Resource *resource; - b32 to_exclusive; + b32 acquire; } barrier; struct @@ -411,11 +420,11 @@ Struct(G_D12_CmdList) Enum(G_D12_TrackedUsageKind) { G_D12_TrackedUsageKind_Untracked, - G_D12_TrackedUsageKind_MakeExclusive, + G_D12_TrackedUsageKind_Acquire, G_D12_TrackedUsageKind_DepthStencilRead, G_D12_TrackedUsageKind_DepthStencilReadWrite, G_D12_TrackedUsageKind_RenderTarget, - G_D12_TrackedUsageKind_MakeCommon, + G_D12_TrackedUsageKind_Release, }; Struct(G_D12_TransitionNode) @@ -456,6 +465,13 @@ Struct(G_D12_BatchedCmdNode) G_D12_Cmd *cmd; }; +Struct(G_D12_BarrierInfo) +{ + D3D12_BARRIER_SYNC sync; + D3D12_BARRIER_ACCESS access; + D3D12_BARRIER_LAYOUT layout; +}; + Struct(G_D12_CmdBatch) { G_D12_CmdBatch *next; @@ -478,7 +494,8 @@ Struct(G_D12_CmdBatch) b32 contains_compute_shader; b32 contains_draw_shader; b32 contains_rtv; - b32 contains_dsv; + b32 contains_dsv_read; + b32 contains_dsv_write; b32 contains_indirect; b32 contains_copy; }; @@ -517,6 +534,8 @@ Struct(G_D12_Ctx) b32 independent_devices_enabled; b32 debug_layer_enabled; b32 validation_layer_enabled; + b32 events_enabled; + b32 pix_enabled; // Stats Atomic64 arenas_count; @@ -591,7 +610,7 @@ G_D12_Resource *G_D12_ResourceFromHandle(G_ResourceHandle handle); G_D12_Swapchain *G_D12_SwapchainFromHandle(G_SwapchainHandle handle); DXGI_FORMAT G_D12_DxgiFormatFromGpuFormat(G_Format format); -D3D12_BARRIER_LAYOUT G_D12_BarrierLayoutFromUsageKind(G_QueueKind queue_kind, G_D12_TrackedUsageKind usage_kind); +D3D12_BARRIER_LAYOUT G_D12_CommonLayoutFromQueueKind(G_QueueKind queue_kind); void G_D12_InitRtv(G_D12_Resource *resource, D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle, i32 mip); @@ -632,7 +651,13 @@ G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorH G_D12_Cmd *G_D12_PushCmd(G_D12_CmdList *cl); G_D12_Cmd *G_D12_PushConstCmd(G_D12_CmdList *cl, i32 slot, void *v); G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size); + +//////////////////////////////////////////////////////////// +//~ Tracking + void G_D12_UpdateTrackedUsage(Arena *arena, G_D12_CmdBatch *batch, G_D12_Resource *resource, RngI32 mips, G_D12_TrackedUsageKind usage_kind); +G_D12_BarrierInfo G_D12_BarrierInfoFromBatch(G_D12_CmdBatch *batch, G_QueueKind queue_kind); +G_D12_BarrierInfo G_D12_BarrierInfoFromUsageKind(G_D12_TrackedUsageKind usage_kind, G_D12_Resource *resource, G_D12_BarrierInfo global, G_QueueKind queue_kind); //////////////////////////////////////////////////////////// //~ Debug diff --git a/src/meta/meta_os/meta_os_win32/meta_os_win32.c b/src/meta/meta_os/meta_os_win32/meta_os_win32.c index 213ff848..2b60abde 100644 --- a/src/meta/meta_os/meta_os_win32/meta_os_win32.c +++ b/src/meta/meta_os/meta_os_win32/meta_os_win32.c @@ -1,31 +1,3 @@ -//////////////////////////////////////////////////////////// -//~ Win32 helpers - -String W32_StringFromError(Arena *arena, DWORD err) -{ - String result = Zi; - char *msg_cstr = 0; - i64 len = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - 0, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&msg_cstr, - 0, - 0 - ); - if (len > 0) - { - result = PushString(arena, TrimWhitespace(StringFromCstr(msg_cstr, len))); - LocalFree(msg_cstr); - } - else - { - result = StringF(arena, "Unknown win32 error - %F", FmtHex(err)); - } - return result; -} - //////////////////////////////////////////////////////////// //~ @hookimpl Bootstrap diff --git a/src/meta/meta_os/meta_os_win32/meta_os_win32.h b/src/meta/meta_os/meta_os_win32/meta_os_win32.h index 13f6a19d..9103c4e4 100644 --- a/src/meta/meta_os/meta_os_win32/meta_os_win32.h +++ b/src/meta/meta_os/meta_os_win32/meta_os_win32.h @@ -3,8 +3,3 @@ #pragma comment(lib, "kernel32") #pragma comment(lib, "user32") - -//////////////////////////////////////////////////////////// -//~ Win32 helpers - -String W32_StringFromError(Arena *arena, DWORD err); diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 7deb9b34..d02988ab 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -4843,10 +4843,10 @@ void V_TickForever(WaveLaneCtx *lane) { max = 5; } - LogEventsArray logs = GetLogEvents(); - for (u64 i = logs.count; i-- > 0 && display_count < max && !done;) + LogEventsArray log_events = GetLogEvents(); + for (u64 i = log_events.count; i-- > 0 && display_count < max && !done;) { - LogEvent ev = logs.logs[i]; + LogEvent ev = log_events.events[i]; if (ev.time_ns > (frame->time_ns - max_time_ns)) { if (ev.level <= console_level) @@ -5279,6 +5279,7 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Initialization pass + G_BeginEvent(cl, Lit("Testing")); { // Prepare shade G_Compute2D(cl, V_PrepareShadeCS, frame->shade_dims); @@ -5323,6 +5324,7 @@ void V_TickForever(WaveLaneCtx *lane) G_Sync(cl); } + G_EndEvent(cl); ////////////////////////////// //- Quads & emitters pass