From bb66dcebcf61fab9b1fc8786d8a6edfc1c86de06 Mon Sep 17 00:00:00 2001 From: Asuro Date: Sun, 9 Feb 2025 15:22:45 +0100 Subject: [PATCH] hot reload setup --- src/.clang-format | 3 + src/engine/Shared.h | 4 +- src/engine/Window.cpp | 5 ++ src/engine/main.cpp | 130 ++++++++++++++++++++++--------- src/game/rendering/Rendering.cpp | 8 +- src/shadercompile.bat | 12 +-- tools/remedy-session.rdbg | Bin 299 -> 418 bytes 7 files changed, 114 insertions(+), 48 deletions(-) create mode 100644 src/.clang-format diff --git a/src/.clang-format b/src/.clang-format new file mode 100644 index 0000000..947e6c7 --- /dev/null +++ b/src/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: Microsoft +IndentWidth: 4 +NamespaceIndentation: NI_All diff --git a/src/engine/Shared.h b/src/engine/Shared.h index 72a08b5..2d7d407 100644 --- a/src/engine/Shared.h +++ b/src/engine/Shared.h @@ -1,6 +1,5 @@ #pragma once #include -#include struct SharedWindowData { @@ -16,7 +15,8 @@ struct FileChangeNotification struct SharedDevData { - bx::SpScUnboundedQueueT* ShaderChangeQueue; + uint32_t ChangedShaderCount = 0; + FileChangeNotification ChangedShaders[16]; }; struct GameData diff --git a/src/engine/Window.cpp b/src/engine/Window.cpp index c8a12ba..928c0e7 100644 --- a/src/engine/Window.cpp +++ b/src/engine/Window.cpp @@ -51,3 +51,8 @@ void EngineWindow::Update(SharedWindowData& Shared) } } } + +void EngineWindow::Shutdown() +{ + SDL_Quit(); +} diff --git a/src/engine/main.cpp b/src/engine/main.cpp index 216fd9f..76f76be 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #define WIN32_LEAN_AND_MEAN #include #undef min @@ -8,7 +9,7 @@ #include #include -#include +#include #include #include "Shared.h" @@ -23,7 +24,7 @@ constexpr const char* DLLPath = "PuzGame.dll"; constexpr const wchar_t* DLLWatch = L"PuzGame2.dll"; #else constexpr const char* DLLPath = "libPuzGame.dll"; -constexpr const wchar_t* DLLWatch = L"cmake-build\\libPuzGame2.dll"; +constexpr const wchar_t* DLLWatch = L"libPuzGame2.dll"; #endif namespace @@ -38,19 +39,26 @@ enum class FileChangeType CompiledShader, }; +struct FileWatcherStartup +{ + char DirPath[512]{0}; + wchar_t CompName[512]{0}; + FileChangeType ChangeType = FileChangeType::Shader; + bool Shutdown = false; +}; + struct FileWatcherData { - bx::SpScUnboundedQueueT ShaderQueue{defaultAllocator}; - bx::SpScUnboundedQueueT DLLQueue{defaultAllocator}; + FileWatcherStartup DLLWatcher; + FileWatcherStartup ShaderWatcher; + FileWatcherStartup CompiledShaderWatcher; + bx::MpScUnboundedQueueT ShaderQueue{defaultAllocator}; + bx::MpScUnboundedQueueT DLLQueue{defaultAllocator}; }; struct DevelopmentData { - uint8_t FileChangeBuffer[1024]{ 0 }; HMODULE GameLib = NULL; - HANDLE DevDir = NULL; - HANDLE ShaderDir = NULL; - HANDLE CompiledShaderDir = NULL; FileWatcherData FileWatcher; }; @@ -71,18 +79,20 @@ namespace void FileChangeCheck(HANDLE dirHandle, FileChangeType changeType, const wchar_t* compName = nullptr) { + if (dirHandle == NULL) return; + + uint8_t fileChangeBuffer[1024]{ 0 }; + bx::memSet(fileChangeBuffer, 0, sizeof(fileChangeBuffer)); DWORD bytesReturned = 0; - bx::memSet(DevData.FileChangeBuffer, 0, sizeof(DevData.FileChangeBuffer)); - if (ReadDirectoryChangesW(dirHandle, DevData.FileChangeBuffer, sizeof(DevData.FileChangeBuffer), true, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE, &bytesReturned, NULL, NULL)) + if (ReadDirectoryChangesW(dirHandle, fileChangeBuffer, sizeof(fileChangeBuffer), true, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE, &bytesReturned, NULL, NULL)) { uint32_t offset = 0; while (true) { - FILE_NOTIFY_INFORMATION* notifyData = reinterpret_cast(&DevData.FileChangeBuffer[offset]); - + FILE_NOTIFY_INFORMATION* notifyData = reinterpret_cast(&fileChangeBuffer[offset]); if (notifyData->Action == FILE_ACTION_ADDED || notifyData->Action == FILE_ACTION_MODIFIED || notifyData->Action == FILE_ACTION_RENAMED_NEW_NAME) { - if (compName == nullptr || wcscmp(notifyData->FileName, compName) == 0) + if (compName == nullptr || compName[0] == 0 || wcscmp(notifyData->FileName, compName) == 0) { FileChangeNotification notif; wcscpy(notif.FileName, notifyData->FileName); @@ -92,14 +102,13 @@ void FileChangeCheck(HANDLE dirHandle, FileChangeType changeType, const wchar_t* } else if (changeType == FileChangeType::Shader) { - std::system("../shadercompile.bat"); + std::system("shadercompile.bat"); } else if (changeType == FileChangeType::CompiledShader) { DevData.FileWatcher.ShaderQueue.push(¬if); } printf("detected file change of type %u!\n", changeType); - wprintf(L"%s\n", notifyData->FileName); } } @@ -109,14 +118,42 @@ void FileChangeCheck(HANDLE dirHandle, FileChangeType changeType, const wchar_t* } } +HANDLE LoadDirHandle(const char* name) +{ + HANDLE h = CreateFileA(name, + FILE_LIST_DIRECTORY, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, + NULL); + + if (h == NULL) + { + printf("Failed to load dir handle for %s", name); + } + return h; +} + unsigned long FileWatcherThread(void* data) { - bool isRunning = DevData.DevDir; - while (isRunning) + FileWatcherStartup* startupData = reinterpret_cast(data); + printf("Starting file watcher of type %u\n", startupData->ChangeType); + if (startupData->DirPath[0] == 0) { - FileChangeCheck(DevData.DevDir, FileChangeType::DLL, DLLWatch); - FileChangeCheck(DevData.ShaderDir, FileChangeType::Shader); - FileChangeCheck(DevData.CompiledShaderDir, FileChangeType::CompiledShader); + printf("Invalid file watcher path!\n"); + return 1; + } + HANDLE dirHandle = LoadDirHandle(startupData->DirPath); + if (dirHandle == NULL) + { + printf("Failed to load dir %s for file watcher!\n", startupData->DirPath); + return 1; + } + + while (!startupData->Shutdown) + { + FileChangeCheck(dirHandle, startupData->ChangeType, startupData->CompName); } printf("File watcher thread ended!\n"); return 0; @@ -191,17 +228,6 @@ bool ReloadDLL() return true; } -HANDLE LoadDirHandle(const char* name) -{ - return CreateFileA(name, - FILE_LIST_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, - NULL); -} - int main() { char PathBuf[512]{ 0 }; @@ -217,13 +243,20 @@ int main() return 1; } - Shared.Dev.ShaderChangeQueue = &DevData.FileWatcher.ShaderQueue; - DevData.DevDir = LoadDirHandle("."); - DevData.ShaderDir = LoadDirHandle("../game/shaders"); - DevData.CompiledShaderDir = LoadDirHandle("../game/compiled-shaders"); + DevData.FileWatcher.DLLWatcher.ChangeType = FileChangeType::DLL; + DevData.FileWatcher.ShaderWatcher.ChangeType = FileChangeType::Shader; + DevData.FileWatcher.CompiledShaderWatcher.ChangeType = FileChangeType::CompiledShader; + + bx::strCopy(DevData.FileWatcher.DLLWatcher.DirPath, sizeof(DevData.FileWatcher.DLLWatcher.DirPath), "cmake-build"); + bx::strCopy(DevData.FileWatcher.ShaderWatcher.DirPath, sizeof(DevData.FileWatcher.ShaderWatcher.DirPath), "game/shaders"); + bx::strCopy(DevData.FileWatcher.CompiledShaderWatcher.DirPath, sizeof(DevData.FileWatcher.CompiledShaderWatcher.DirPath), "game/compiled-shaders"); + + wcscpy(DevData.FileWatcher.DLLWatcher.CompName, DLLWatch); DWORD fileWatcherThreadId = 0; - CreateThread(NULL, 0, FileWatcherThread, NULL, 0, &fileWatcherThreadId); + HANDLE dllThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.DLLWatcher, 0, &fileWatcherThreadId); + HANDLE shaderThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.ShaderWatcher, 0, &fileWatcherThreadId); + HANDLE compiledShaderThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.CompiledShaderWatcher, 0, &fileWatcherThreadId); StartupFunc(Shared); @@ -245,7 +278,32 @@ int main() StartupFunc(Shared); } + FileChangeNotification* CompiledShaderChange = nullptr; + while ((CompiledShaderChange = DevData.FileWatcher.ShaderQueue.pop())) + { + if (Shared.Dev.ChangedShaderCount < BX_COUNTOF(Shared.Dev.ChangedShaders)) + { + wcscpy(Shared.Dev.ChangedShaders[Shared.Dev.ChangedShaderCount].FileName, CompiledShaderChange->FileName); + ++Shared.Dev.ChangedShaderCount; + } + else + { + printf("Ran out of shader change buffer!\n"); + } + } + UpdateFunc(); } + + ShutdownFunc(); + Engine.Window.Shutdown(); + + DevData.FileWatcher.DLLWatcher.Shutdown = true; + DevData.FileWatcher.ShaderWatcher.Shutdown = true; + DevData.FileWatcher.CompiledShaderWatcher.Shutdown = true; + WaitForSingleObject(dllThread, 100); + WaitForSingleObject(shaderThread, 100); + WaitForSingleObject(compiledShaderThread, 100); + return 0; } diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index bc15488..b799033 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -154,11 +154,11 @@ namespace Game SharedData& shared = GetShared(); FileChangeNotification* shaderChange = nullptr; - while ((shaderChange = shared.Dev.ShaderChangeQueue->pop())) + if (shared.Dev.ChangedShaderCount > 0) { + shared.Dev.ChangedShaderCount = 0; + bgfx::destroy(Shader); - VertexBuffer = bgfx::createVertexBuffer(bgfx::makeRef(cubeVertices, sizeof(cubeVertices)), VertLayout); - IndexBuffer = bgfx::createIndexBuffer(bgfx::makeRef(cubeTriList, sizeof(cubeTriList))); bgfx::ShaderHandle vertexShader = loadShader("vert"); bgfx::ShaderHandle fragmentShader = loadShader("frag"); Shader = bgfx::createProgram(vertexShader, fragmentShader, true); @@ -223,7 +223,7 @@ namespace Game } } - bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.2f", time); + bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.1f", time); bgfx::dbgTextPrintf(1, 2, 0x0f, "Frame: %u", GetInstance().FrameCounter); bgfx::frame(); diff --git a/src/shadercompile.bat b/src/shadercompile.bat index e8791bc..6095027 100644 --- a/src/shadercompile.bat +++ b/src/shadercompile.bat @@ -1,6 +1,6 @@ -.\cmake-build\dependency\bgfx.cmake\cmake\bgfx\shaderc.exe -f .\game\shaders\vert.sc -o .\game\compiled-shaders\dx11\vert.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type v --platform windows --profile s_5_0 -.\cmake-build\dependency\bgfx.cmake\cmake\bgfx\shaderc.exe -f .\game\shaders\frag.sc -o .\game\compiled-shaders\dx11\frag.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type f --platform windows --profile s_5_0 -.\cmake-build\dependency\bgfx.cmake\cmake\bgfx\shaderc.exe -f .\game\shaders\vert.sc -o .\game\compiled-shaders\glsl\vert.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type v --platform windows --profile 430 -.\cmake-build\dependency\bgfx.cmake\cmake\bgfx\shaderc.exe -f .\game\shaders\frag.sc -o .\game\compiled-shaders\glsl\frag.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type f --platform windows --profile 430 -.\cmake-build\dependency\bgfx.cmake\cmake\bgfx\shaderc.exe -f .\game\shaders\vert.sc -o .\game\compiled-shaders\spirv\vert.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type v --platform windows --profile spirv16-13 -.\cmake-build\dependency\bgfx.cmake\cmake\bgfx\shaderc.exe -f .\game\shaders\frag.sc -o .\game\compiled-shaders\spirv\frag.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type f --platform windows --profile spirv16-13 +.\cmake-build\shaderc.exe -f .\game\shaders\vert.sc -o .\game\compiled-shaders\dx11\vert.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type v --platform windows --profile s_5_0 +.\cmake-build\shaderc.exe -f .\game\shaders\frag.sc -o .\game\compiled-shaders\dx11\frag.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type f --platform windows --profile s_5_0 +.\cmake-build\shaderc.exe -f .\game\shaders\vert.sc -o .\game\compiled-shaders\glsl\vert.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type v --platform windows --profile 430 +.\cmake-build\shaderc.exe -f .\game\shaders\frag.sc -o .\game\compiled-shaders\glsl\frag.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type f --platform windows --profile 430 +.\cmake-build\shaderc.exe -f .\game\shaders\vert.sc -o .\game\compiled-shaders\spirv\vert.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type v --platform windows --profile spirv16-13 +.\cmake-build\shaderc.exe -f .\game\shaders\frag.sc -o .\game\compiled-shaders\spirv\frag.bin -i .\dependency\bgfx.cmake\bgfx\src\ --type f --platform windows --profile spirv16-13 diff --git a/tools/remedy-session.rdbg b/tools/remedy-session.rdbg index ece0cdb3812276f18a5099b9d69fa5508089391e..cfe2b36f77f01a6d25037bc0f95ab30b78f7cb18 100644 GIT binary patch delta 131 zcmZ3@w1|0v7b`OZ1B3QNe{tcW)V!3`qRhPXm>?KyVz$~uKSf?f1_%JrAf*~ula6E`YMmS<$0_*;hq#0RMb0RH(Ob^rhX delta 54 zcmZ3)yqal(7Yh>u1H;7miW6&