diff --git a/OptiScaler/OptiScaler.vcxproj b/OptiScaler/OptiScaler.vcxproj index 662dfb82..04c6ff4d 100644 --- a/OptiScaler/OptiScaler.vcxproj +++ b/OptiScaler/OptiScaler.vcxproj @@ -307,6 +307,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y + @@ -452,7 +453,6 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y - @@ -624,6 +624,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y + @@ -721,7 +722,6 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y - diff --git a/OptiScaler/OptiScaler.vcxproj.filters b/OptiScaler/OptiScaler.vcxproj.filters index 620a5d4c..91a845dc 100644 --- a/OptiScaler/OptiScaler.vcxproj.filters +++ b/OptiScaler/OptiScaler.vcxproj.filters @@ -566,9 +566,6 @@ Header Files - - Header Files - Header Files @@ -977,6 +974,9 @@ Header Files + + Header Files + Header Files @@ -1340,9 +1340,6 @@ Source Files - - Source Files - Source Files @@ -1610,6 +1607,9 @@ Source Files + + Source Files + Source Files diff --git a/OptiScaler/gpu_time/GpuTime_Vk.cpp b/OptiScaler/gpu_time/GpuTime_Vk.cpp new file mode 100644 index 00000000..b6b0977c --- /dev/null +++ b/OptiScaler/gpu_time/GpuTime_Vk.cpp @@ -0,0 +1,98 @@ +#include "pch.h" +#include "GpuTime_Vk.h" + +#include + +GpuTime_Vk::GpuTime_Vk(VkDevice device, VkPhysicalDevice physicalDevice) : _device(device) +{ + if (device == VK_NULL_HANDLE || physicalDevice == VK_NULL_HANDLE) + { + LOG_ERROR("GpuTime_Vk created with null device"); + return; + } + + // Start and End timestamps per buffer + VkQueryPoolCreateInfo queryPoolInfo {}; + queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + queryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP; + queryPoolInfo.queryCount = QUERY_BUFFER_COUNT * 2; + + auto result = vkCreateQueryPool(device, &queryPoolInfo, nullptr, &_queryPool); + + if (result != VK_SUCCESS) + { + LOG_ERROR("vkCreateQueryPool error: {}", (int) result); + _queryPool = VK_NULL_HANDLE; + return; + } + + VkPhysicalDeviceProperties deviceProperties {}; + vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); + _timestampPeriod = deviceProperties.limits.timestampPeriod; + + _init = true; +} + +GpuTime_Vk::~GpuTime_Vk() +{ + if (State::Instance().isShuttingDown) + return; + + if (_queryPool != VK_NULL_HANDLE) + { + vkDestroyQueryPool(_device, _queryPool, nullptr); + _queryPool = VK_NULL_HANDLE; + } +} + +void GpuTime_Vk::Start(VkCommandBuffer cmdBuffer) +{ + if (_init && _queryPool != VK_NULL_HANDLE) + { + _currentFrameIndex = (_currentFrameIndex + 1) % QUERY_BUFFER_COUNT; + + vkCmdResetQueryPool(cmdBuffer, _queryPool, _currentFrameIndex * 2, 2); + vkCmdWriteTimestamp(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, _queryPool, _currentFrameIndex * 2); + } +} + +void GpuTime_Vk::End(VkCommandBuffer cmdBuffer) +{ + if (_init && _queryPool != VK_NULL_HANDLE) + { + vkCmdWriteTimestamp(cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, _queryPool, _currentFrameIndex * 2 + 1); + + _trigger[_currentFrameIndex] = true; + } +} + +std::optional GpuTime_Vk::ReadGpuTime() +{ + std::optional elapsedTimeMs = std::nullopt; + + if (!_init || _queryPool == VK_NULL_HANDLE) + return elapsedTimeMs; + + // Try to read the oldest frame's timestamps + uint32_t previousFrameIndex = (_currentFrameIndex + 1) % QUERY_BUFFER_COUNT; + + if (!_trigger[previousFrameIndex]) + return elapsedTimeMs; + + uint64_t timestamps[2] {}; + auto result = vkGetQueryPoolResults(_device, _queryPool, previousFrameIndex * 2, 2, sizeof(timestamps), timestamps, + sizeof(uint64_t), VK_QUERY_RESULT_64_BIT); + + // Results not available yet, the slot will get overwritten by the next Start anyway + if (result != VK_SUCCESS) + return elapsedTimeMs; + + _trigger[previousFrameIndex] = false; + + if (timestamps[1] < timestamps[0]) + return elapsedTimeMs; + + elapsedTimeMs = (timestamps[1] - timestamps[0]) * _timestampPeriod / 1e6; + + return elapsedTimeMs; +} diff --git a/OptiScaler/gpu_time/GpuTime_Vk.h b/OptiScaler/gpu_time/GpuTime_Vk.h new file mode 100644 index 00000000..10b933c5 --- /dev/null +++ b/OptiScaler/gpu_time/GpuTime_Vk.h @@ -0,0 +1,47 @@ +#pragma once + +#include "SysUtils.h" +#include +#include +#include + +class GpuTime_Vk +{ + static constexpr int QUERY_BUFFER_COUNT = 3; + + VkDevice _device = VK_NULL_HANDLE; + VkQueryPool _queryPool = VK_NULL_HANDLE; + double _timestampPeriod = 1.0; + std::array _trigger {}; + + int _currentFrameIndex = 0; + bool _init = false; + + public: + GpuTime_Vk(VkDevice device, VkPhysicalDevice physicalDevice); + ~GpuTime_Vk(); + + void Start(VkCommandBuffer cmdBuffer); + void End(VkCommandBuffer cmdBuffer); + + std::optional ReadGpuTime(); +}; + +class ScopedGpuTime_Vk +{ + GpuTime_Vk* _gpuTime; + VkCommandBuffer _cmdBuffer; + + public: + ScopedGpuTime_Vk(GpuTime_Vk* gpuTime, VkCommandBuffer cmdBuffer) : _gpuTime(gpuTime), _cmdBuffer(cmdBuffer) + { + if (_gpuTime && _cmdBuffer) + _gpuTime->Start(_cmdBuffer); + } + + ~ScopedGpuTime_Vk() + { + if (_gpuTime && _cmdBuffer) + _gpuTime->End(_cmdBuffer); + } +}; diff --git a/OptiScaler/hooks/Vulkan_Hooks.cpp b/OptiScaler/hooks/Vulkan_Hooks.cpp index 426ab87c..ab373c9d 100644 --- a/OptiScaler/hooks/Vulkan_Hooks.cpp +++ b/OptiScaler/hooks/Vulkan_Hooks.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include "Reflex_Hooks.h" @@ -243,8 +243,24 @@ static VkResult hkvkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPres { LOG_FUNC(); - // get upscaler time - UpscalerTimeVk::ReadUpscalingTime(_device); + // Upscaler GPU time computation + if (auto vkFeature = dynamic_cast(State::Instance().currentFeature); vkFeature != nullptr) + { + if (auto upscalerTimeOpt = vkFeature->ReadUpscalerTime(nullptr); upscalerTimeOpt.has_value()) + { + vkFeature->ReadDetailedGpuTimes(nullptr, State::Instance().detailedGpuTimes); + + auto upscalerTime = upscalerTimeOpt.value(); + // filter out possibly wrong measured high values + if (upscalerTime < 100.0) + { + State::Instance().frameTimeMutex.lock(); + State::Instance().upscaleTimes.push_back(upscalerTime); + State::Instance().upscaleTimes.pop_front(); + State::Instance().frameTimeMutex.unlock(); + } + } + } // ??? TODO: if we are hooking dxvk's vulkan calls then this present call could be either coming from dxvk or from a // native vk game diff --git a/OptiScaler/inputs/NVNGX_DLSS_Vk.cpp b/OptiScaler/inputs/NVNGX_DLSS_Vk.cpp index 136f072b..76fa16e6 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Vk.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Vk.cpp @@ -10,8 +10,6 @@ #include "upscalers/FeatureProvider_Vk.h" -#include - #include #include #include @@ -246,8 +244,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Init_Ext2( State::Instance().currentVkDevice = InDevice; - UpscalerTimeVk::Init(InDevice, InPD); - State::Instance().nvngxVkInited = true; return NVSDK_NGX_Result_Success; @@ -1063,8 +1059,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_EvaluateFeature(VkCommandBuffer deviceContext = VkContexts[handleId].feature.get(); state.currentFeature = deviceContext; - UpscalerTimeVk::UpscaleStart(InCmdList); - auto upscaleResult = deviceContext->Evaluate(InCmdList, InParameters); if (!upscaleResult) @@ -1078,8 +1072,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_EvaluateFeature(VkCommandBuffer return NVSDK_NGX_Result_Success; } - UpscalerTimeVk::UpscaleEnd(InCmdList); - return upscaleResult ? NVSDK_NGX_Result_Success : NVSDK_NGX_Result_Fail; } diff --git a/OptiScaler/menu/menu_common.cpp b/OptiScaler/menu/menu_common.cpp index 765291ab..1c3e9f52 100644 --- a/OptiScaler/menu/menu_common.cpp +++ b/OptiScaler/menu/menu_common.cpp @@ -19,8 +19,6 @@ #include #include -#include - #include #include #include diff --git a/OptiScaler/shaders/Shader_Vk.cpp b/OptiScaler/shaders/Shader_Vk.cpp index 0f455980..41e081cd 100644 --- a/OptiScaler/shaders/Shader_Vk.cpp +++ b/OptiScaler/shaders/Shader_Vk.cpp @@ -5,6 +5,7 @@ Shader_Vk::Shader_Vk(std::string InName, VkDevice InDevice, VkPhysicalDevice InPhysicalDevice) : _name(InName), _device(InDevice), _physicalDevice(InPhysicalDevice) { + GpuTime = std::make_unique(InDevice, InPhysicalDevice); } Shader_Vk::~Shader_Vk() diff --git a/OptiScaler/shaders/Shader_Vk.h b/OptiScaler/shaders/Shader_Vk.h index 5a89688d..1d50da14 100644 --- a/OptiScaler/shaders/Shader_Vk.h +++ b/OptiScaler/shaders/Shader_Vk.h @@ -2,6 +2,7 @@ #include "SysUtils.h" #include +#include #include #include @@ -25,6 +26,8 @@ class Shader_Vk VkDevice _device = VK_NULL_HANDLE; VkPhysicalDevice _physicalDevice = VK_NULL_HANDLE; + std::unique_ptr GpuTime = nullptr; + // Pipeline Layouts VkPipeline _pipeline = VK_NULL_HANDLE; VkPipelineLayout _pipelineLayout = VK_NULL_HANDLE; @@ -84,6 +87,8 @@ class Shader_Vk public: bool IsInit() const { return _init; } bool CanRender() const { return _init && _pipeline != VK_NULL_HANDLE; } + std::string Name() const { return _name; } + std::optional ReadGpuTime() { return GpuTime->ReadGpuTime(); } VkImageView GetImageView() const { return _intermediateImageView; } VkImage GetImage() const { return _intermediateImage; } diff --git a/OptiScaler/shaders/magnifier/Magnifier_Vk.cpp b/OptiScaler/shaders/magnifier/Magnifier_Vk.cpp index 7fdbca33..dee7b4b4 100644 --- a/OptiScaler/shaders/magnifier/Magnifier_Vk.cpp +++ b/OptiScaler/shaders/magnifier/Magnifier_Vk.cpp @@ -66,6 +66,8 @@ bool Magnifier_Vk::Dispatch(VkCommandBuffer InCmdList, const VkImageInfo& InReso LOG_DEBUG("[{0}] Start!", _name); + ScopedGpuTime_Vk scopedGpuTime(GpuTime.get(), InCmdList); + if (!InitializeViews(InResourceInfo.ImageView, OutResourceInfo.ImageView)) return false; diff --git a/OptiScaler/shaders/output_scaling/OS_Vk.cpp b/OptiScaler/shaders/output_scaling/OS_Vk.cpp index d3cfb2ab..0824c91f 100644 --- a/OptiScaler/shaders/output_scaling/OS_Vk.cpp +++ b/OptiScaler/shaders/output_scaling/OS_Vk.cpp @@ -113,6 +113,8 @@ bool OS_Vk::Dispatch(VkCommandBuffer InCmdList, const VkImageInfo& InResourceVie if (!_init || InCmdList == VK_NULL_HANDLE) return false; + ScopedGpuTime_Vk scopedGpuTime(GpuTime.get(), InCmdList); + // Update Constants FsrEasuCon(fsr1Constants.const0, fsr1Constants.const1, fsr1Constants.const2, fsr1Constants.const3, State::Instance().currentFeature->TargetWidth(), State::Instance().currentFeature->TargetHeight(), diff --git a/OptiScaler/shaders/rcas/RCAS_Vk.cpp b/OptiScaler/shaders/rcas/RCAS_Vk.cpp index af4a57a1..14dd8ff7 100644 --- a/OptiScaler/shaders/rcas/RCAS_Vk.cpp +++ b/OptiScaler/shaders/rcas/RCAS_Vk.cpp @@ -241,6 +241,8 @@ bool RCAS_Vk::Dispatch(VkDevice InDevice, VkCommandBuffer InCmdList, RcasConstan State::Instance().currentFeature == nullptr) return false; + ScopedGpuTime_Vk scopedGpuTime(GpuTime.get(), InCmdList); + auto sharpnessShader = Config::Instance()->SharpnessShader.value_or_default(); if (sharpnessShader == SharpenShader::LocalContrastDepthAware) { diff --git a/OptiScaler/upscaler_time/UpscalerTime_Vk.cpp b/OptiScaler/upscaler_time/UpscalerTime_Vk.cpp deleted file mode 100644 index 853257e8..00000000 --- a/OptiScaler/upscaler_time/UpscalerTime_Vk.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "pch.h" -#include "UpscalerTime_Vk.h" - -#include - -void UpscalerTimeVk::Init(VkDevice device, VkPhysicalDevice pd) -{ - VkQueryPoolCreateInfo queryPoolInfo = {}; - queryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; - queryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP; - queryPoolInfo.queryCount = 2; // Start and End timestamps - - vkCreateQueryPool(device, &queryPoolInfo, nullptr, &_queryPool); - - VkPhysicalDeviceProperties deviceProperties; - vkGetPhysicalDeviceProperties(pd, &deviceProperties); - _timeStampPeriod = deviceProperties.limits.timestampPeriod; -} - -void UpscalerTimeVk::UpscaleStart(VkCommandBuffer cmdBuffer) -{ - if (_queryPool == VK_NULL_HANDLE) - return; - - vkCmdResetQueryPool(cmdBuffer, _queryPool, 0, 2); - vkCmdWriteTimestamp(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, _queryPool, 0); -} - -void UpscalerTimeVk::UpscaleEnd(VkCommandBuffer cmdBuffer) -{ - if (_queryPool == VK_NULL_HANDLE) - return; - - vkCmdWriteTimestamp(cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, _queryPool, 1); - _vkUpscaleTrig = true; -} - -void UpscalerTimeVk::ReadUpscalingTime(VkDevice device) -{ - if (_vkUpscaleTrig && _queryPool != VK_NULL_HANDLE) - { - // Retrieve timestamps - uint64_t timestamps[2]; - vkGetQueryPoolResults(device, _queryPool, 0, 2, sizeof(timestamps), timestamps, sizeof(uint64_t), - VK_QUERY_RESULT_64_BIT); - - // Calculate elapsed time in milliseconds - double elapsedTimeMs = (timestamps[1] - timestamps[0]) * _timeStampPeriod / 1e6; - - if (elapsedTimeMs > 0.0 && elapsedTimeMs < 5000.0) - { - State::Instance().frameTimeMutex.lock(); - State::Instance().upscaleTimes.push_back(elapsedTimeMs); - State::Instance().upscaleTimes.pop_front(); - State::Instance().frameTimeMutex.unlock(); - } - } - - _vkUpscaleTrig = false; -} diff --git a/OptiScaler/upscaler_time/UpscalerTime_Vk.h b/OptiScaler/upscaler_time/UpscalerTime_Vk.h deleted file mode 100644 index c4e38d10..00000000 --- a/OptiScaler/upscaler_time/UpscalerTime_Vk.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "SysUtils.h" - -#include - -class UpscalerTimeVk -{ - public: - static void Init(VkDevice device, VkPhysicalDevice pd); - static void UpscaleStart(VkCommandBuffer cmdBuffer); - static void UpscaleEnd(VkCommandBuffer cmdBuffer); - static void ReadUpscalingTime(VkDevice device); - - private: - static inline VkQueryPool _queryPool = VK_NULL_HANDLE; - static inline double _timeStampPeriod = 1.0; - static inline bool _vkUpscaleTrig = false; -}; diff --git a/OptiScaler/upscalers/IFeature_Vk.cpp b/OptiScaler/upscalers/IFeature_Vk.cpp index 30922131..14ccc19a 100644 --- a/OptiScaler/upscalers/IFeature_Vk.cpp +++ b/OptiScaler/upscalers/IFeature_Vk.cpp @@ -18,12 +18,10 @@ bool IFeature_Vk::Init(VkInstance InInstance, VkPhysicalDevice InPD, VkDevice In if (result) { - OutputScaler = std::make_unique("Output Scaling", InDevice, InPD, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", InDevice, InPD); Magnifier = std::make_unique("Magnifier", InDevice, InPD); - - // UpscalerTime = std::make_unique(InDevice); + UpscalerTime = std::make_unique(InDevice, InPD); } return result; @@ -271,11 +269,11 @@ bool IFeature_Vk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* InP paramOutput->Resource.ImageViewInfo.Height = currentTarget.Height; } - // UpscalerTime->Start(InCmdBuffer); + UpscalerTime->Start(InCmdBuffer); auto evalResult = EvaluateInternal(InCmdBuffer, InParameters); - // UpscalerTime->End(InCmdBuffer); + UpscalerTime->End(InCmdBuffer); if (!evalResult) return false; @@ -306,4 +304,39 @@ bool IFeature_Vk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* InP _frameCount++; return evalResult; -} \ No newline at end of file +} + +std::optional IFeature_Vk::ReadUpscalerTime(void* unused) +{ + if (!UpscalerTime || !RCAS || !OutputScaler) + return std::nullopt; + + lastUpscalerTime = UpscalerTime->ReadGpuTime(); + lastRcasTime = RCAS->ReadGpuTime(); + lastOutputScalingTime = OutputScaler->ReadGpuTime(); + + return sumOpts(lastUpscalerTime, lastRcasTime, lastOutputScalingTime); +} + +void IFeature_Vk::ReadDetailedGpuTimes(void* unused, std::vector& detailedGpuTimes) +{ + detailedGpuTimes.clear(); + + // Do not call ReadGpuTime twice for shaders + if (lastUpscalerTime) + detailedGpuTimes.emplace_back(DetailedGpuTime { ShortName(), lastUpscalerTime.value(), true }); + + if (lastRcasTime) + detailedGpuTimes.emplace_back(DetailedGpuTime { RCAS->Name(), lastRcasTime.value(), true }); + + if (lastOutputScalingTime) + detailedGpuTimes.emplace_back(DetailedGpuTime { OutputScaler->Name(), lastOutputScalingTime.value(), true }); + + if (!Magnifier) + return; + + auto magnifierTime = Magnifier->ReadGpuTime(); + + if (magnifierTime) + detailedGpuTimes.emplace_back(DetailedGpuTime { Magnifier->Name(), magnifierTime.value(), false }); +} diff --git a/OptiScaler/upscalers/IFeature_Vk.h b/OptiScaler/upscalers/IFeature_Vk.h index e7b742c4..28ff6cf5 100644 --- a/OptiScaler/upscalers/IFeature_Vk.h +++ b/OptiScaler/upscalers/IFeature_Vk.h @@ -5,6 +5,7 @@ #include #include #include +#include class IFeature_Vk : public virtual IFeature { @@ -33,6 +34,8 @@ class IFeature_Vk : public virtual IFeature std::unique_ptr RCAS = nullptr; std::unique_ptr Magnifier = nullptr; + std::unique_ptr UpscalerTime = nullptr; + virtual bool InitInternal(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* InParameters) = 0; virtual bool EvaluateInternal(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* InParameters) = 0; @@ -42,6 +45,9 @@ class IFeature_Vk : public virtual IFeature NVSDK_NGX_Parameter* InParameters); virtual bool Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* InParameters); + std::optional ReadUpscalerTime(void* unused) override; + void ReadDetailedGpuTimes(void* unused, std::vector& detailedGpuTimes) override; + IFeature_Vk(unsigned int InHandleId, NVSDK_NGX_Parameter* InParameters) : IFeature(InHandleId, InParameters) {} bool IsWithDx12() override { return false; } diff --git a/OptiScaler/upscalers/IFeature_VkwDx12.cpp b/OptiScaler/upscalers/IFeature_VkwDx12.cpp index f33bd4b6..871564d8 100644 --- a/OptiScaler/upscalers/IFeature_VkwDx12.cpp +++ b/OptiScaler/upscalers/IFeature_VkwDx12.cpp @@ -1622,6 +1622,8 @@ bool IFeature_VkwDx12::CopyBackOutput(VkCommandBuffer InCmdBuffer) vkOut.VkSourceImageAccess = copyBarriers[1].dstAccessMask; } + UpscalerTime->End(b.VulkanCopyCommandBuffer[frame]); + vkResult = vkEndCommandBuffer(b.VulkanCopyCommandBuffer[frame]); if (vkResult != VK_SUCCESS) { @@ -2041,6 +2043,8 @@ bool IFeature_VkwDx12::Init(VkInstance InInstance, VkPhysicalDevice InPD, VkDevi return false; } + UpscalerTime = std::make_unique(InDevice, InPD); + SetInitParameters(InParameters); // Non-DLSS upscalers don't use the cmdList during Init @@ -2061,6 +2065,9 @@ bool IFeature_VkwDx12::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter auto frame = _frameCount % VKDX12_BUFFER_COUNT; auto cmdList = Dx12CommandList[frame]; + // Ends in the copy back command buffer, covers the whole interop with D3D12 upscaling in between + UpscalerTime->Start(InCmdBuffer); + void* originalColor = nullptr; void* originalMotionVectors = nullptr; void* originalOutput = nullptr; diff --git a/OptiScaler/upscalers/IFeature_VkwDx12.h b/OptiScaler/upscalers/IFeature_VkwDx12.h index bb92f13f..8817641e 100644 --- a/OptiScaler/upscalers/IFeature_VkwDx12.h +++ b/OptiScaler/upscalers/IFeature_VkwDx12.h @@ -87,6 +87,8 @@ class IFeature_VkwDx12 : public virtual IFeature_Vk uint64_t pendingResourceCopyValue = 0; std::mutex EvaluateMutex; + std::vector detailedGpuTimes; + // Copy shaders std::unique_ptr ColorCopy = nullptr; std::unique_ptr VelocityCopy = nullptr; @@ -148,6 +150,45 @@ class IFeature_VkwDx12 : public virtual IFeature_Vk API Api() const override { return API::DX12; } bool IsWithDx12() override { return true; } + std::optional ReadUpscalerTime(void* unused) override + { + if (auto feature = dx12Feature.get(); feature && Dx12CommandQueue && UpscalerTime) + { + auto dx12UpscalerTime = feature->ReadUpscalerTime(Dx12CommandQueue); + + feature->ReadDetailedGpuTimes(Dx12CommandQueue, detailedGpuTimes); + + // Count up shader times that are included in upscalerWithInterop but not in dx12UpscalerTime + double deductedUpscalerTime = 0.0; + for (const auto& time : detailedGpuTimes) + { + if (!time.includedInUpscalerTime) + deductedUpscalerTime += time.time; + } + + auto upscalerWithInterop = UpscalerTime->ReadGpuTime(); + + if (dx12UpscalerTime && upscalerWithInterop) + { + auto interopTime = upscalerWithInterop.value() - dx12UpscalerTime.value() - deductedUpscalerTime; + + if (interopTime > 0.0) + { + detailedGpuTimes.push_back({ "Interop", interopTime, true }); + return interopTime + dx12UpscalerTime.value(); + } + } + } + + return std::nullopt; + }; + + void ReadDetailedGpuTimes(void* unused, std::vector& detailedGpuTimes) override + { + // We already queried and prepared detailedGpuTimes in ReadUpscalerTime + detailedGpuTimes = this->detailedGpuTimes; + }; + feature_version Version() final { return CallFeature([](auto f) { return f->Version(); }, feature_version {}); diff --git a/OptiScaler/upscalers/dlss/DLSSFeature_Vk.h b/OptiScaler/upscalers/dlss/DLSSFeature_Vk.h index 341f158d..adf3396e 100644 --- a/OptiScaler/upscalers/dlss/DLSSFeature_Vk.h +++ b/OptiScaler/upscalers/dlss/DLSSFeature_Vk.h @@ -16,6 +16,11 @@ class DLSSFeatureVk : public DLSSFeature, public IFeature_Vk feature_version Version() override { return DLSSFeature::Version(); } Upscaler GetUpscalerType() const final { return DLSSFeature::GetUpscalerType(); } API Api() const override { return IFeature_Vk::Api(); } + std::optional ReadUpscalerTime(void* unused) override { return IFeature_Vk::ReadUpscalerTime(unused); }; + void ReadDetailedGpuTimes(void* unused, std::vector& detailedGpuTimes) override + { + return IFeature_Vk::ReadDetailedGpuTimes(unused, detailedGpuTimes); + }; bool IsWithDx12() override { return false; } diff --git a/OptiScaler/upscalers/dlssd/DLSSDFeature_Vk.h b/OptiScaler/upscalers/dlssd/DLSSDFeature_Vk.h index 19044f66..1883719b 100644 --- a/OptiScaler/upscalers/dlssd/DLSSDFeature_Vk.h +++ b/OptiScaler/upscalers/dlssd/DLSSDFeature_Vk.h @@ -16,6 +16,11 @@ class DLSSDFeatureVk : public DLSSDFeature, public IFeature_Vk feature_version Version() override { return DLSSDFeature::Version(); } Upscaler GetUpscalerType() const final { return DLSSDFeature::GetUpscalerType(); } API Api() const override { return IFeature_Vk::Api(); } + std::optional ReadUpscalerTime(void* unused) override { return IFeature_Vk::ReadUpscalerTime(unused); }; + void ReadDetailedGpuTimes(void* unused, std::vector& detailedGpuTimes) override + { + return IFeature_Vk::ReadDetailedGpuTimes(unused, detailedGpuTimes); + }; bool IsWithDx12() override { return false; } diff --git a/OptiScaler/upscalers/ffx/FFXFeature_Vk.h b/OptiScaler/upscalers/ffx/FFXFeature_Vk.h index eb58f095..c9c758da 100644 --- a/OptiScaler/upscalers/ffx/FFXFeature_Vk.h +++ b/OptiScaler/upscalers/ffx/FFXFeature_Vk.h @@ -21,6 +21,11 @@ class FFXFeatureVk : public FFXFeature, public IFeature_Vk feature_version Version() override { return FFXFeature::Version(); } Upscaler GetUpscalerType() const final { return Upscaler::FFX; } API Api() const override { return IFeature_Vk::Api(); } + std::optional ReadUpscalerTime(void* unused) override { return IFeature_Vk::ReadUpscalerTime(unused); }; + void ReadDetailedGpuTimes(void* unused, std::vector& detailedGpuTimes) override + { + return IFeature_Vk::ReadDetailedGpuTimes(unused, detailedGpuTimes); + }; bool IsWithDx12() final { return false; } diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.h b/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.h index 49eb531f..c2cd62ca 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.h +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.h @@ -26,6 +26,11 @@ class FSR2FeatureVk : public FSR2Feature, public IFeature_Vk feature_version Version() override { return FSR2Feature::Version(); } Upscaler GetUpscalerType() const final { return Upscaler::FSR22; } API Api() const override { return IFeature_Vk::Api(); } + std::optional ReadUpscalerTime(void* unused) override { return IFeature_Vk::ReadUpscalerTime(unused); }; + void ReadDetailedGpuTimes(void* unused, std::vector& detailedGpuTimes) override + { + return IFeature_Vk::ReadDetailedGpuTimes(unused, detailedGpuTimes); + }; bool IsWithDx12() override { return false; } }; diff --git a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.h b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.h index 213beee3..3567a294 100644 --- a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.h +++ b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.h @@ -26,6 +26,11 @@ class FSR2FeatureVk212 : public FSR2Feature212, public IFeature_Vk feature_version Version() override { return FSR2Feature212::Version(); } Upscaler GetUpscalerType() const final { return Upscaler::FSR21; } API Api() const override { return IFeature_Vk::Api(); } + std::optional ReadUpscalerTime(void* unused) override { return IFeature_Vk::ReadUpscalerTime(unused); }; + void ReadDetailedGpuTimes(void* unused, std::vector& detailedGpuTimes) override + { + return IFeature_Vk::ReadDetailedGpuTimes(unused, detailedGpuTimes); + }; bool IsWithDx12() override { return false; } };