From 27c4a848371bb58242e1a24ba1b247f787dfcc1c Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Mon, 24 Jan 2022 19:08:26 +0100 Subject: [PATCH] AtlasEngine: Make shader hot-reloads possible in Windows Terminal (#12227) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This minor change makes it possible to hot-reload the AtlasEngine shaders under Windows Terminal. Launching an UWP application from Visual Studio doesn't necessarily result in a working directory inside the project folder, which makes relative file paths impractical. While the `__FILE__` macro is compiler dependent it works under our build setup with MSVC at least. ## Validation Steps Performed * Shader hot-reloading works under Windows Terminal ✅ --- src/renderer/atlas/AtlasEngine.cpp | 31 +++++++++++++++--------------- src/renderer/atlas/AtlasEngine.h | 1 + src/renderer/atlas/pch.h | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/renderer/atlas/AtlasEngine.cpp b/src/renderer/atlas/AtlasEngine.cpp index bff52ab13cc..4e4e75966a0 100644 --- a/src/renderer/atlas/AtlasEngine.cpp +++ b/src/renderer/atlas/AtlasEngine.cpp @@ -9,8 +9,6 @@ #include "../../interactivity/win32/CustomWindowMessages.h" -#define SHADER_SOURCE_DIRECTORY LR"(..\..\renderer\atlas\)" - // #### NOTE #### // This file should only contain methods that are only accessed by the caller of Present() (the "Renderer" class). // Basically this file poses the "synchronization" point between the concurrently running @@ -192,16 +190,17 @@ AtlasEngine::AtlasEngine() _sr.isWindows10OrGreater = IsWindows10OrGreater(); #ifndef NDEBUG - // If you run the Host.EXE project inside Visual Studio it'll have a working directory of - // $(SolutionDir)\src\host\exe. This relative path will thus end up in this source directory. - _sr.sourceCodeWatcher = wil::make_folder_change_reader_nothrow(SHADER_SOURCE_DIRECTORY, false, wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime, [this](wil::FolderChangeEvent, PCWSTR path) { - if (til::ends_with(path, L".hlsl")) - { - auto expected = INT64_MAX; - const auto invalidationTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(100); - _sr.sourceCodeInvalidationTime.compare_exchange_strong(expected, invalidationTime.time_since_epoch().count(), std::memory_order_relaxed); - } - }); + { + _sr.sourceDirectory = std::filesystem::path{ __FILE__ }.parent_path(); + _sr.sourceCodeWatcher = wil::make_folder_change_reader_nothrow(_sr.sourceDirectory.c_str(), false, wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime, [this](wil::FolderChangeEvent, PCWSTR path) { + if (til::ends_with(path, L".hlsl")) + { + auto expected = INT64_MAX; + const auto invalidationTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(100); + _sr.sourceCodeInvalidationTime.compare_exchange_strong(expected, invalidationTime.time_since_epoch().count(), std::memory_order_relaxed); + } + }); + } #endif } @@ -265,8 +264,8 @@ try try { - static const auto compile = [](const wchar_t* path, const char* target) { - const wil::unique_hfile fileHandle{ CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr) }; + static const auto compile = [](const std::filesystem::path& path, const char* target) { + const wil::unique_hfile fileHandle{ CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr) }; THROW_LAST_ERROR_IF(!fileHandle); const auto fileSize = GetFileSize(fileHandle.get(), nullptr); @@ -303,8 +302,8 @@ try return blob; }; - const auto vs = compile(SHADER_SOURCE_DIRECTORY "shader_vs.hlsl", "vs_4_1"); - const auto ps = compile(SHADER_SOURCE_DIRECTORY "shader_ps.hlsl", "ps_4_1"); + const auto vs = compile(_sr.sourceDirectory / L"shader_vs.hlsl", "vs_4_1"); + const auto ps = compile(_sr.sourceDirectory / L"shader_ps.hlsl", "ps_4_1"); THROW_IF_FAILED(_r.device->CreateVertexShader(vs->GetBufferPointer(), vs->GetBufferSize(), nullptr, _r.vertexShader.put())); THROW_IF_FAILED(_r.device->CreatePixelShader(ps->GetBufferPointer(), ps->GetBufferSize(), nullptr, _r.pixelShader.put())); diff --git a/src/renderer/atlas/AtlasEngine.h b/src/renderer/atlas/AtlasEngine.h index a9123128df4..4f930de2154 100644 --- a/src/renderer/atlas/AtlasEngine.h +++ b/src/renderer/atlas/AtlasEngine.h @@ -649,6 +649,7 @@ namespace Microsoft::Console::Render bool isWindows10OrGreater = true; #ifndef NDEBUG + std::filesystem::path sourceDirectory; wil::unique_folder_change_reader_nothrow sourceCodeWatcher; std::atomic sourceCodeInvalidationTime{ INT64_MAX }; #endif diff --git a/src/renderer/atlas/pch.h b/src/renderer/atlas/pch.h index e6ede9efed7..5d59e23544b 100644 --- a/src/renderer/atlas/pch.h +++ b/src/renderer/atlas/pch.h @@ -7,7 +7,7 @@ #define WIN32_LEAN_AND_MEAN #include -#include +#include #include #include #include