diff --git a/CMakeLists.txt b/CMakeLists.txt index 895a85e4d..9372a5593 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,9 +15,11 @@ message("Options:") option(AUTO_PLUGIN_DEPLOYMENT "Copy the build output and addons to env:CommunityShadersOutputDir." OFF) option(ZIP_TO_DIST "Zip the base mod and addons to their own 7z file in dist." ON) option(AIO_ZIP_TO_DIST "Zip the base mod and addons to a AIO 7z file in dist." ON) +option(TRACY_SUPPORT "Enable support for tracy profiler" OFF) message("\tAuto plugin deployment: ${AUTO_PLUGIN_DEPLOYMENT}") message("\tZip to dist: ${ZIP_TO_DIST}") message("\tAIO Zip to dist: ${AIO_ZIP_TO_DIST}") +message("\tTracy profiler: ${TRACY_SUPPORT}") # ####################################################################################################################### # # Add CMake features @@ -40,10 +42,17 @@ find_package(pystring CONFIG REQUIRED) find_package(cppwinrt CONFIG REQUIRED) find_package(unordered_dense CONFIG REQUIRED) find_package(efsw CONFIG REQUIRED) +find_package(Tracy CONFIG REQUIRED) set(NVAPI_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/extern/nvapi/" CACHE STRING "Path to NVAPI include headers/shaders" ) set(NVAPI_LIBRARY "${CMAKE_SOURCE_DIR}/extern/nvapi/amd64/nvapi64.lib" CACHE STRING "Path to NVAPI .lib file") +target_compile_definitions( + ${PROJECT_NAME} + PRIVATE + "$<$:TRACY_SUPPORT>" +) + target_include_directories( ${PROJECT_NAME} PRIVATE @@ -68,6 +77,7 @@ target_link_libraries( pystring::pystring unordered_dense::unordered_dense efsw::efsw + Tracy::TracyClient ${NVAPI_LIBRARY} ) diff --git a/CMakePresets.json b/CMakePresets.json index 9b960271d..7dd216b00 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -113,6 +113,13 @@ "ENABLE_SKYRIM_VR": "OFF" }, "inherits": "skyrim" + }, + { + "name": "ALL-TRACY", + "cacheVariables": { + "TRACY_SUPPORT": "ON" + }, + "inherits": "ALL" } ] } \ No newline at end of file diff --git a/README.md b/README.md index 9f00c7843..7ad689c93 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,10 @@ If you want an example CMakeUserPreset to start off with you can copy the `CMake * This option is default `"ON"` * Make sure `"ZIP_TO_DIST"` is set to `"ON"` in `CMakeUserPresets.json` * This will create a zip for each feature and one for the base Community shaders in /dist containing +#### TRACY_SUPPORT +* This option is default `"OFF"` +* This will enable tracy support, might need to delete build folder when this option is changed + When using custom preset you can call BuildRelease.bat with an parameter to specify which preset to configure eg: `.\BuildRelease.bat ALL-WITH-AUTO-DEPLOYMENT` diff --git a/include/PCH.h b/include/PCH.h index de9965b2b..05f058749 100644 --- a/include/PCH.h +++ b/include/PCH.h @@ -31,6 +31,10 @@ void* operator new[](size_t size, size_t alignment, size_t alignmentOffset, cons #define WIN32_LEAN_AND_MEAN #include +#ifndef TRACY_SUPPORT + #undef TRACY_ENABLE +#endif + using namespace std::literals; namespace stl diff --git a/src/Deferred.cpp b/src/Deferred.cpp index 4ec49719f..d3ec22d3e 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -189,6 +189,9 @@ void Deferred::SetupResources() void Deferred::CopyShadowData() { + ZoneScoped; + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "CopyShadowData"); + auto& context = State::GetSingleton()->context; ID3D11UnorderedAccessView* uavs[1]{ perShadow->uav.get() }; @@ -252,6 +255,9 @@ void Deferred::UpdateConstantBuffer() void Deferred::PrepassPasses() { + ZoneScoped; + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Prepass"); + auto& shaderCache = SIE::ShaderCache::Instance(); if (!shaderCache.IsEnabled()) @@ -337,6 +343,9 @@ void Deferred::StartDeferred() void Deferred::DeferredPasses() { + ZoneScoped; + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Deferred"); + auto renderer = RE::BSGraphics::Renderer::GetSingleton(); auto& context = State::GetSingleton()->context; @@ -377,6 +386,8 @@ void Deferred::DeferredPasses() // Ambient Composite { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Ambient Composite"); + ID3D11Buffer* buffer = skylighting->loaded ? skylighting->skylightingCB->CB() : nullptr; context->CSSetConstantBuffers(1, 1, &buffer); @@ -416,6 +427,8 @@ void Deferred::DeferredPasses() // Deferred Composite { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Deferred Composite"); + ID3D11Buffer* buffer = skylighting->loaded ? skylighting->skylightingCB->CB() : nullptr; context->CSSetConstantBuffers(1, 1, &buffer); diff --git a/src/Features/DynamicCubemaps.cpp b/src/Features/DynamicCubemaps.cpp index 8a83c7a7f..fd723146c 100644 --- a/src/Features/DynamicCubemaps.cpp +++ b/src/Features/DynamicCubemaps.cpp @@ -368,6 +368,8 @@ void DynamicCubemaps::Irradiance(bool a_reflections) void DynamicCubemaps::UpdateCubemap() { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Cubemap Update"); + switch (nextTask) { case NextTask::kInferrence: nextTask = NextTask::kIrradiance; diff --git a/src/Features/ScreenSpaceGI.cpp b/src/Features/ScreenSpaceGI.cpp index 999532dad..4c989d684 100644 --- a/src/Features/ScreenSpaceGI.cpp +++ b/src/Features/ScreenSpaceGI.cpp @@ -677,6 +677,9 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) return; } + ZoneScoped; + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "SSGI"); + static uint lastFrameGITexIdx = 0; static uint lastFrameAccumTexIdx = 0; uint inputGITexIdx = lastFrameGITexIdx; @@ -721,6 +724,8 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) // prefilter depths { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "SSGI - Prefilter Depths"); + srvs.at(0) = renderer->GetDepthStencilData().depthStencils[RE::RENDER_TARGETS_DEPTHSTENCIL::kPOST_ZPREPASS_COPY].depthSRV; for (int i = 0; i < 5; ++i) uavs.at(i) = uavWorkingDepth[i].get(); @@ -733,6 +738,8 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) // fetch radiance and disocclusion { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "SSGI - Radiance Disocc"); + resetViews(); srvs.at(0) = rts[deferred->forwardRenderTargets[0]].SRV; srvs.at(1) = texGI[inputGITexIdx]->srv.get(); @@ -762,6 +769,8 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) // GI { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "SSGI - GI"); + resetViews(); srvs.at(0) = texWorkingDepth->srv.get(); srvs.at(1) = rts[NORMALROUGHNESS].SRV; @@ -789,6 +798,7 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) if (settings.EnableBlur) { for (uint i = 0; i < settings.BlurPasses; i++) { if (doSpecular) { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "SSGI - Specular Blur"); resetViews(); srvs.at(0) = texGISpecular[inputGITexIdx]->srv.get(); srvs.at(1) = nullptr; @@ -804,6 +814,8 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) context->Dispatch((internalRes[0] + 7u) >> 3, (internalRes[1] + 7u) >> 3, 1); } + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "SSGI - Diffuse Blur"); + resetViews(); srvs.at(0) = texGI[inputGITexIdx]->srv.get(); srvs.at(1) = texAccumFrames[lastFrameAccumTexIdx]->srv.get(); diff --git a/src/Features/ScreenSpaceShadows.cpp b/src/Features/ScreenSpaceShadows.cpp index 223b65986..11b7bfe0a 100644 --- a/src/Features/ScreenSpaceShadows.cpp +++ b/src/Features/ScreenSpaceShadows.cpp @@ -87,6 +87,9 @@ ID3D11ComputeShader* ScreenSpaceShadows::GetComputeRaymarchRight() void ScreenSpaceShadows::DrawShadows() { + ZoneScoped; + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Screen Space Shadows"); + auto renderer = RE::BSGraphics::Renderer::GetSingleton(); auto context = State::GetSingleton()->context; @@ -134,6 +137,8 @@ void ScreenSpaceShadows::DrawShadows() float2 dynamicRes = { viewport->GetRuntimeData().dynamicResolutionWidthRatio, viewport->GetRuntimeData().dynamicResolutionHeightRatio }; for (int i = 0; i < dispatchList.DispatchCount; i++) { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "SSS - Ray March"); + auto dispatchData = dispatchList.Dispatch[i]; RaymarchCB data{}; @@ -174,6 +179,8 @@ void ScreenSpaceShadows::DrawShadows() dispatchList = Bend::BuildDispatchList(lightProjectionRightF, viewportSize, minRenderBounds, maxRenderBounds); for (int i = 0; i < dispatchList.DispatchCount; i++) { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "SSS - Ray March (VR Right Eye)"); + auto dispatchData = dispatchList.Dispatch[i]; RaymarchCB data{}; diff --git a/src/Features/Skylighting.cpp b/src/Features/Skylighting.cpp index 13f6dfa49..6f4273ac8 100644 --- a/src/Features/Skylighting.cpp +++ b/src/Features/Skylighting.cpp @@ -201,6 +201,8 @@ void Skylighting::CompileComputeShaders() void Skylighting::Prepass() { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Skylighting - Update Probes"); + auto& context = State::GetSingleton()->context; { @@ -494,7 +496,10 @@ void Skylighting::Main_Precipitation_RenderOcclusion::thunk() precip->SetupMask(); // Calling setup twice fixes an issue when it is raining BSParticleShaderRainEmitter* rain = new BSParticleShaderRainEmitter; - precip->RenderMask((RE::BSParticleShaderRainEmitter*)rain); + { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Skylighting - Render Height Map"); + precip->RenderMask((RE::BSParticleShaderRainEmitter*)rain); + } singleton->inOcclusion = false; singleton->OcclusionDir = -float4{ PrecipitationShaderDirectionF.x, PrecipitationShaderDirectionF.y, PrecipitationShaderDirectionF.z, 0 }; diff --git a/src/Features/SubsurfaceScattering.cpp b/src/Features/SubsurfaceScattering.cpp index 85847c3ed..e01017538 100644 --- a/src/Features/SubsurfaceScattering.cpp +++ b/src/Features/SubsurfaceScattering.cpp @@ -163,6 +163,9 @@ void SubsurfaceScattering::DrawSSS() if (!validMaterials) return; + ZoneScoped; + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Subsurface Scattering"); + validMaterials = false; auto dispatchCount = Util::GetScreenDispatchCount(); @@ -204,6 +207,8 @@ void SubsurfaceScattering::DrawSSS() // Horizontal pass to temporary texture { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Subsurface Scattering - Horizontal"); + auto shader = GetComputeShaderHorizontalBlur(); context->CSSetShader(shader, nullptr, 0); @@ -215,6 +220,8 @@ void SubsurfaceScattering::DrawSSS() // Vertical pass to main texture { + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Subsurface Scattering - Vertical"); + views[0] = blurHorizontalTemp->srv.get(); context->CSSetShaderResources(0, 1, views); diff --git a/src/Features/TerrainOcclusion.cpp b/src/Features/TerrainOcclusion.cpp index 801414661..82ce98d9a 100644 --- a/src/Features/TerrainOcclusion.cpp +++ b/src/Features/TerrainOcclusion.cpp @@ -432,6 +432,9 @@ void TerrainOcclusion::UpdateShadow() if (!sunLight) return; + ZoneScoped; + TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Terrain Occlusion - Update Shadows"); + /* ---- UPDATE CB ---- */ uint width = texNormalisedHeight->desc.Width; uint height = texNormalisedHeight->desc.Height; diff --git a/src/Hooks.cpp b/src/Hooks.cpp index 9198417c3..2e645828d 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -148,7 +148,9 @@ HRESULT WINAPI hk_IDXGISwapChain_Present(IDXGISwapChain* This, UINT SyncInterval { State::GetSingleton()->Reset(); Menu::GetSingleton()->DrawOverlay(); - return (This->*ptr_IDXGISwapChain_Present)(SyncInterval, Flags); + auto retval = (This->*ptr_IDXGISwapChain_Present)(SyncInterval, Flags); + TracyD3D11Collect(State::GetSingleton()->tracyCtx); + return retval; } void hk_BSGraphics_SetDirtyStates(bool isCompute); @@ -451,6 +453,18 @@ namespace Hooks static inline REL::Relocation func; }; +#ifdef TRACY_ENABLE + struct Main_Update + { + static void thunk(RE::Main* a_this, float a2) + { + func(a_this, a2); + FrameMark; + } + static inline REL::Relocation func; + }; +#endif + void Install() { SKSE::AllocTrampoline(14); @@ -490,5 +504,9 @@ namespace Hooks stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x406, 0x409)); stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x1245, 0x123B, 0x1917)); stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0xA25, 0xA25, 0xCD2)); + +#ifdef TRACY_ENABLE + stl::write_thunk_call(REL::RelocationID(35551, 36544).address() + REL::Relocate(0x11F, 0x160)); +#endif } } \ No newline at end of file diff --git a/src/State.cpp b/src/State.cpp index a5bf211ac..c4561251f 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -375,6 +375,8 @@ void State::SetupResources() context = reinterpret_cast(renderer->GetRuntimeData().context); device = reinterpret_cast(renderer->GetRuntimeData().forwarder); context->QueryInterface(__uuidof(pPerf), reinterpret_cast(&pPerf)); + + tracyCtx = TracyD3D11Context(device, context); } void State::ModifyShaderLookup(const RE::BSShader& a_shader, uint& a_vertexDescriptor, uint& a_pixelDescriptor, bool a_forceDeferred) diff --git a/src/State.h b/src/State.h index 370da213e..2645fbdc6 100644 --- a/src/State.h +++ b/src/State.h @@ -1,5 +1,8 @@ #pragma once +#include +#include + #include #include using json = nlohmann::json; @@ -139,6 +142,16 @@ class State ID3D11DeviceContext* context = nullptr; ID3D11Device* device = nullptr; + TracyD3D11Ctx tracyCtx = nullptr; // Tracy context + + inline ~State() + { +#ifdef TRACY_ENABLE + if (tracyCtx) + TracyD3D11Destroy(tracyCtx); +#endif + } + private: std::shared_ptr pPerf; bool initialized = false; diff --git a/vcpkg.json b/vcpkg.json index 13b790c2e..9d3314d21 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -24,6 +24,7 @@ "magic-enum", "nlohmann-json", "pystring", + "tracy", "unordered-dense", "xbyak" ], @@ -35,6 +36,10 @@ { "name": "imgui", "version": "1.90" + }, + { + "name": "tracy", + "version": "0.11.0" } ], "builtin-baseline": "1dc5ee30eb1032221d29f281f4a94b73f06b4284"