From ebc2d31deccf63da7cb8af85481a0438cc336130 Mon Sep 17 00:00:00 2001
From: FakeMichau <49685661+FakeMichau@users.noreply.github.com>
Date: Mon, 14 Sep 2026 23:13:38 +0200
Subject: [PATCH] Add Hudless fixup to No Man's Sky
Seems like the same issue as with Cyberprank's DLSSG inputs
Also enables hud cutoff on Vulkan NvngxFG
---
OptiScaler/OptiScaler.vcxproj | 3 +
OptiScaler/OptiScaler.vcxproj.filters | 9 ++
OptiScaler/framegen/nvngx/Nvngx_FG.cpp | 54 ++++++-
OptiScaler/framegen/nvngx/Nvngx_FG.h | 4 +-
OptiScaler/misc/Quirks.h | 2 +-
OptiScaler/shaders/hud_copy/HudCopy_Common.h | 63 +++++---
OptiScaler/shaders/hud_copy/HudCopy_Dx12.cpp | 4 +-
OptiScaler/shaders/hud_copy/HudCopy_Dx12.h | 8 +-
OptiScaler/shaders/hud_copy/HudCopy_Vk.cpp | 142 +++++++++++++++++
OptiScaler/shaders/hud_copy/HudCopy_Vk.h | 17 ++
.../shaders/hud_copy/precompile/HudCopy.hlsl | 14 ++
.../hud_copy/precompile/HudCopy_Shader_Vk.h | 90 +++++++++++
.../hud_copy/precompile/HudCopy_Shader_Vk.spv | Bin 0 -> 1624 bytes
.../shaders/magnifier/Magnifier_Common.h | 145 ++++++++++--------
14 files changed, 455 insertions(+), 100 deletions(-)
create mode 100644 OptiScaler/shaders/hud_copy/HudCopy_Vk.cpp
create mode 100644 OptiScaler/shaders/hud_copy/HudCopy_Vk.h
create mode 100644 OptiScaler/shaders/hud_copy/precompile/HudCopy_Shader_Vk.h
create mode 100644 OptiScaler/shaders/hud_copy/precompile/HudCopy_Shader_Vk.spv
diff --git a/OptiScaler/OptiScaler.vcxproj b/OptiScaler/OptiScaler.vcxproj
index 3f5d2407..776dc29f 100644
--- a/OptiScaler/OptiScaler.vcxproj
+++ b/OptiScaler/OptiScaler.vcxproj
@@ -333,6 +333,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
+
@@ -340,6 +341,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
+
@@ -621,6 +623,7 @@ 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 f2f52381..48316feb 100644
--- a/OptiScaler/OptiScaler.vcxproj.filters
+++ b/OptiScaler/OptiScaler.vcxproj.filters
@@ -956,6 +956,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
@@ -1544,6 +1550,9 @@
Source Files
+
+ Source Files
+
diff --git a/OptiScaler/framegen/nvngx/Nvngx_FG.cpp b/OptiScaler/framegen/nvngx/Nvngx_FG.cpp
index e137120a..09a43f37 100644
--- a/OptiScaler/framegen/nvngx/Nvngx_FG.cpp
+++ b/OptiScaler/framegen/nvngx/Nvngx_FG.cpp
@@ -12,6 +12,7 @@
#include "Nvngx_FFX.h"
#include "Nvngx_Combo.h"
#include
+#include
IFGNvngx* Nvngx_FG::getProvider()
{
@@ -363,10 +364,10 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_EvaluateFeature(ID3D12GraphicsCommandList* InCm
if (presentWithHud && hudlessResource && device)
{
- if (_hudCopy.get() == nullptr)
- _hudCopy = std::make_unique("HudCopy", device);
+ if (_hudCopyDx12.get() == nullptr)
+ _hudCopyDx12 = std::make_unique("HudCopy", device);
- if (auto hudCopy = _hudCopy.get(); hudCopy && hudCopy->IsInit())
+ if (auto hudCopy = _hudCopyDx12.get(); hudCopy && hudCopy->IsInit())
{
// In Cyberprank - DLSSG has noise issues, FSR FG has noise + vignetting
// In Death Stranding 2 - DLSSG has wrong colormapping it seems, FSR FG is fine
@@ -418,6 +419,9 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_Init(unsigned long long InApplicationId, const
if (!provider)
return NVSDK_NGX_Result_Fail;
+ if (!_hudCopyVk)
+ _hudCopyVk = std::make_unique("HudCopy", InDevice, InPD);
+
return provider->VULKAN_Init(InApplicationId, InApplicationDataPath, InInstance, InPD, InDevice, InGIPA, InGDPA,
InFeatureInfo, InSDKVersion);
}
@@ -432,6 +436,9 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_Init_Ext(unsigned long long InApplicationId, c
if (!provider)
return NVSDK_NGX_Result_Fail;
+ if (!_hudCopyVk)
+ _hudCopyVk = std::make_unique("HudCopy", InDevice, InPD);
+
return provider->VULKAN_Init_Ext(InApplicationId, InApplicationDataPath, InInstance, InPD, InDevice, InSDKVersion,
InFeatureInfo);
}
@@ -447,6 +454,9 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_Init_Ext2(unsigned long long InApplicationId,
if (!provider)
return NVSDK_NGX_Result_Fail;
+ if (!_hudCopyVk)
+ _hudCopyVk = std::make_unique("HudCopy", InDevice, InPD);
+
return provider->VULKAN_Init_Ext2(InApplicationId, InApplicationDataPath, InInstance, InPD, InDevice, InGIPA,
InGDPA, InSDKVersion, InFeatureInfo);
}
@@ -583,6 +593,44 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_EvaluateFeature(VkCommandBuffer InCmdList, con
Nvngx_FG_Handle* ourHandle = (Nvngx_FG_Handle*) InFeatureHandle;
std::shared_lock lock(ourHandle->handleMutex);
+ bool applyHudCutoff = Config::Instance()->FGHudCutoff.value_or_default() > 0.0f ||
+ State::Instance().gameQuirks & GameQuirk::FSRFGHudlessMismatchFixup;
+
+ uint32_t frameIndex = 1;
+ InParameters->Get("DLSSG.MultiFrameIndex", &frameIndex);
+
+ if (applyHudCutoff && frameIndex == 1)
+ {
+ NVSDK_NGX_Resource_VK* presentWithHud = nullptr;
+ InParameters->Get("DLSSG.Backbuffer", (void**) &presentWithHud);
+ VkImageLayout presentWithHudLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ NVSDK_NGX_Resource_VK* hudlessResource = nullptr;
+ InParameters->Get("DLSSG.HUDLess", (void**) &hudlessResource);
+ VkImageLayout hudlessLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+
+ if (presentWithHud && hudlessResource)
+ {
+ if (auto hudCopy = _hudCopyVk.get(); hudCopy && hudCopy->IsInit())
+ {
+ float hudDetectionThreshold = 0.03f;
+
+ if (Config::Instance()->FGHudCutoff.value_or_default() > 0.0f)
+ hudDetectionThreshold = Config::Instance()->FGHudCutoff.value_or_default() / 10.0f;
+
+ VkImageInfo presentWithHudInfo = *(VkImageInfo*) &presentWithHud->Resource.ImageViewInfo;
+ VkImageInfo hudlessResourceInfo = *(VkImageInfo*) &hudlessResource->Resource.ImageViewInfo;
+
+ hudCopy->Dispatch(InCmdList, hudlessResourceInfo, hudlessLayout, presentWithHudInfo,
+ presentWithHudLayout, hudDetectionThreshold);
+ }
+ }
+ else
+ {
+ LOG_WARN("Couldn't run hudless fixup");
+ }
+ }
+
if (Config::Instance()->NvngxFGDisableHudless.value_or_default())
InParameters->Set("DLSSG.HUDLess", (void*) nullptr);
diff --git a/OptiScaler/framegen/nvngx/Nvngx_FG.h b/OptiScaler/framegen/nvngx/Nvngx_FG.h
index d59a493f..0982f60e 100644
--- a/OptiScaler/framegen/nvngx/Nvngx_FG.h
+++ b/OptiScaler/framegen/nvngx/Nvngx_FG.h
@@ -5,6 +5,7 @@
#include "proxies/NVNGX_Proxy.h"
#include "proxies/Ntdll_Proxy.h"
#include
+#include
#include "IFGNvngx.h"
class Nvngx_FG
@@ -21,7 +22,8 @@ class Nvngx_FG
static inline std::atomic_uint32_t lastIdCreated = 0;
static inline std::unique_ptr _provider;
- static inline std::unique_ptr _hudCopy;
+ static inline std::unique_ptr _hudCopyDx12;
+ static inline std::unique_ptr _hudCopyVk;
static IFGNvngx* getProvider();
diff --git a/OptiScaler/misc/Quirks.h b/OptiScaler/misc/Quirks.h
index 2650a3ca..779f1861 100644
--- a/OptiScaler/misc/Quirks.h
+++ b/OptiScaler/misc/Quirks.h
@@ -569,7 +569,7 @@ static const QuirkEntry quirkTable[] = {
// No Man's Sky
QUIRK_ENTRY("nms.exe", GameQuirk::KernelBaseHooks, GameQuirk::VulkanDLSSBarrierFixup,
- GameQuirk::EnableVulkanSpoofing),
+ GameQuirk::EnableVulkanSpoofing, GameQuirk::FSRFGHudlessMismatchFixup),
// RTX Remix
QUIRK_ENTRY("nvremixbridge.exe", GameQuirk::DisableDxgiSpoofing, GameQuirk::LoadVulkanManually,
diff --git a/OptiScaler/shaders/hud_copy/HudCopy_Common.h b/OptiScaler/shaders/hud_copy/HudCopy_Common.h
index 4239e4de..70649240 100644
--- a/OptiScaler/shaders/hud_copy/HudCopy_Common.h
+++ b/OptiScaler/shaders/hud_copy/HudCopy_Common.h
@@ -2,32 +2,55 @@
#include "pch.h"
-static std::string shaderCode = R"(
-cbuffer Params : register(b0)
+class HudCopy_Common
{
- float DiffThreshold;
-};
+ protected:
+ struct alignas(256) InternalHudCopyParams
+ {
+ float DiffThreshold = 0.02f;
+ };
-Texture2D Hudless : register(t0);
-Texture2D PresentCopy : register(t1);
+ const std::string shaderCode = R"(
+ #ifdef VK_MODE
+ cbuffer Params : register(b0, space0)
+ #else
+ cbuffer Params : register(b0)
+ #endif
+ {
+ float DiffThreshold;
+ };
-RWTexture2D Present : register(u0);
+ #ifdef VK_MODE
+ [[vk::binding(1, 0)]]
+ #endif
+ Texture2D Hudless : register(t0);
-[numthreads(16, 16, 1)]
-void CSMain(uint3 dispatchThreadID : SV_DispatchThreadID)
-{
- uint2 pixelCoord = dispatchThreadID.xy;
+ #ifdef VK_MODE
+ [[vk::binding(2, 0)]]
+ #endif
+ Texture2D PresentCopy : register(t1);
- float3 hudless = Hudless.Load(int3(pixelCoord, 0));
- float3 present = PresentCopy.Load(int3(pixelCoord, 0));
+ #ifdef VK_MODE
+ [[vk::binding(3, 0)]]
+ #endif
+ RWTexture2D Present : register(u0);
+
+ [numthreads(16, 16, 1)]
+ void CSMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+ {
+ uint2 pixelCoord = dispatchThreadID.xy;
+
+ float3 hudless = Hudless.Load(int3(pixelCoord, 0));
+ float3 present = PresentCopy.Load(int3(pixelCoord, 0));
- float3 diff = abs(hudless - present);
- float delta = max(max(diff.r, diff.g), diff.b);
+ float3 diff = abs(hudless - present);
+ float delta = max(max(diff.r, diff.g), diff.b);
- float uiMask = smoothstep(DiffThreshold, DiffThreshold * 2.0f, delta);
+ float uiMask = smoothstep(DiffThreshold, DiffThreshold * 2.0f, delta);
- float3 ui = (present - hudless) * uiMask;
+ float3 ui = (present - hudless) * uiMask;
- Present[pixelCoord] = hudless + ui;
-}
-)";
+ Present[pixelCoord] = hudless + ui;
+ }
+ )";
+};
\ No newline at end of file
diff --git a/OptiScaler/shaders/hud_copy/HudCopy_Dx12.cpp b/OptiScaler/shaders/hud_copy/HudCopy_Dx12.cpp
index 66f9277a..232d6318 100644
--- a/OptiScaler/shaders/hud_copy/HudCopy_Dx12.cpp
+++ b/OptiScaler/shaders/hud_copy/HudCopy_Dx12.cpp
@@ -65,7 +65,7 @@ bool HudCopy_Dx12::Dispatch(ID3D12GraphicsCommandList* cmdList, ID3D12Resource*
CreateShaderResourceView(_device, present, currentHeap.GetSrvCPU(1));
CreateUnorderedAccessView(_device, _buffer, currentHeap.GetUavCPU(0), 0);
- InternalCompareParams constants {};
+ InternalHudCopyParams constants {};
constants.DiffThreshold = hudDetectionThreshold;
if (!CreateConstantsBuffer(_device, _constantBuffer, constants, currentHeap.GetCbvCPU(0)))
@@ -117,7 +117,7 @@ HudCopy_Dx12::HudCopy_Dx12(std::string InName, ID3D12Device* InDevice) : Shader_
return;
}
- D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(InternalCompareParams));
+ D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(InternalHudCopyParams));
auto heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
auto result =
diff --git a/OptiScaler/shaders/hud_copy/HudCopy_Dx12.h b/OptiScaler/shaders/hud_copy/HudCopy_Dx12.h
index a647a871..0b91be70 100644
--- a/OptiScaler/shaders/hud_copy/HudCopy_Dx12.h
+++ b/OptiScaler/shaders/hud_copy/HudCopy_Dx12.h
@@ -1,4 +1,5 @@
#pragma once
+#include "HudCopy_Common.h"
#include "SysUtils.h"
@@ -10,14 +11,9 @@
#define HudCopy_NUM_OF_HEAPS 2
-class HudCopy_Dx12 : public Shader_Dx12
+class HudCopy_Dx12 : public Shader_Dx12, public HudCopy_Common
{
private:
- struct alignas(256) InternalCompareParams
- {
- float DiffThreshold = 0.02f;
- };
-
FrameDescriptorHeap _frameHeaps[HudCopy_NUM_OF_HEAPS];
ID3D12Resource* _buffer = nullptr;
diff --git a/OptiScaler/shaders/hud_copy/HudCopy_Vk.cpp b/OptiScaler/shaders/hud_copy/HudCopy_Vk.cpp
new file mode 100644
index 00000000..f4169824
--- /dev/null
+++ b/OptiScaler/shaders/hud_copy/HudCopy_Vk.cpp
@@ -0,0 +1,142 @@
+#include "pch.h"
+#include "HudCopy_Vk.h"
+#include
+#include
+#include "precompile/HudCopy_Shader_Vk.h"
+
+HudCopy_Vk::HudCopy_Vk(std::string InName, VkDevice InDevice, VkPhysicalDevice InPhysicalDevice)
+ : Shader_Vk(InName, InDevice, InPhysicalDevice)
+{
+ if (InDevice == VK_NULL_HANDLE)
+ {
+ LOG_ERROR("InDevice is nullptr!");
+ return;
+ }
+
+ LOG_DEBUG("{0} start!", _name);
+
+ // Setup descriptor layouts (0: Params, 1: Hudless, 2: PresentCopy, 3: PresentOut)
+ CreateSampler(VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
+ CreateConstantBuffer(sizeof(InternalHudCopyParams));
+
+ std::vector bindings = { CreateBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER),
+ CreateBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER),
+ CreateBinding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER),
+ CreateBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) };
+ CreateLayouts(bindings);
+
+ std::vector poolSizes = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, _maxFramesInFlight },
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ _maxFramesInFlight * 2 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, _maxFramesInFlight } };
+ CreateDescriptorPool(poolSizes, _maxFramesInFlight);
+ CreateDescriptorSets(_descriptorSetLayout, _descriptorPool, _descriptorSets);
+
+ std::vector shaderCode(HudCopy_spv, HudCopy_spv + sizeof(HudCopy_spv));
+ if (!CreateComputePipeline(_device, _pipelineLayout, &_pipeline, shaderCode))
+ {
+ LOG_ERROR("[{0}] Failed to create pipeline!", _name);
+ _init = false;
+ return;
+ }
+
+ _init = true;
+}
+
+bool HudCopy_Vk::Dispatch(VkCommandBuffer InCmdList, const VkImageInfo& InHudlessInfo, VkImageLayout HudlessState,
+ const VkImageInfo& InPresentInfo, VkImageLayout PresentState, float HudDetectionThreshold)
+{
+ if (!_init || InCmdList == VK_NULL_HANDLE || InHudlessInfo.Image == VK_NULL_HANDLE ||
+ InPresentInfo.Image == VK_NULL_HANDLE)
+ return false;
+
+ if (!CreateImageResource(InPresentInfo.Width, InPresentInfo.Height, InPresentInfo.Format,
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT))
+ {
+ LOG_ERROR("[{0}] Failed to create or resize intermediate buffer", _name);
+ return false;
+ }
+
+ _currentSetIndex = (_currentSetIndex + 1) % _maxFramesInFlight;
+
+ VkImageSubresourceRange copySubresourceRange = InPresentInfo.SubresourceRange;
+ copySubresourceRange.baseMipLevel = 0;
+ copySubresourceRange.levelCount = 1;
+ copySubresourceRange.baseArrayLayer = 0;
+ copySubresourceRange.layerCount = 1;
+
+ SetImageLayout(InCmdList, InPresentInfo.Image, PresentState, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ copySubresourceRange);
+ SetImageLayout(InCmdList, _intermediateImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ copySubresourceRange);
+
+ VkImageCopy copyRegion {};
+ copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
+ copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
+ copyRegion.extent = { InPresentInfo.Width, InPresentInfo.Height, 1 };
+
+ vkCmdCopyImage(InCmdList, InPresentInfo.Image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, _intermediateImage,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region);
+
+ SetImageLayout(InCmdList, InPresentInfo.Image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, copySubresourceRange);
+ SetImageLayout(InCmdList, _intermediateImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
+ copySubresourceRange);
+ SetImageLayout(InCmdList, InHudlessInfo.Image, HudlessState, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ InHudlessInfo.SubresourceRange);
+
+ InternalHudCopyParams constants {};
+ constants.DiffThreshold = HudDetectionThreshold;
+
+ if (_mappedConstantBuffer)
+ memcpy(_mappedConstantBuffer, &constants, sizeof(InternalHudCopyParams));
+
+ VkDescriptorSet descriptorSet = _descriptorSets[_currentSetIndex];
+
+ VkDescriptorBufferInfo bufferInfo { _constantBuffer, 0, sizeof(InternalHudCopyParams) };
+ VkDescriptorImageInfo hudlessInfo { _textureSampler, InHudlessInfo.ImageView,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
+ VkDescriptorImageInfo presentInfo { _textureSampler, InPresentInfo.ImageView,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
+ VkDescriptorImageInfo destUAVInfo { VK_NULL_HANDLE, _intermediateImageView, VK_IMAGE_LAYOUT_GENERAL };
+
+ std::vector descriptorWritesBuffer = {
+ { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, descriptorSet, 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ nullptr, &bufferInfo, nullptr },
+ { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, descriptorSet, 1, 0, 1,
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &hudlessInfo, nullptr, nullptr },
+ { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, descriptorSet, 2, 0, 1,
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &presentInfo, nullptr, nullptr },
+ { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, descriptorSet, 3, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ &destUAVInfo, nullptr, nullptr }
+ };
+
+ vkUpdateDescriptorSets(_device, static_cast(descriptorWritesBuffer.size()), descriptorWritesBuffer.data(),
+ 0, nullptr);
+
+ // Bind & Dispatch
+ vkCmdBindPipeline(InCmdList, VK_PIPELINE_BIND_POINT_COMPUTE, _pipeline);
+ vkCmdBindDescriptorSets(InCmdList, VK_PIPELINE_BIND_POINT_COMPUTE, _pipelineLayout, 0, 1, &descriptorSet, 0,
+ nullptr);
+
+ uint32_t dispatchWidth = (InPresentInfo.Width + InNumThreadsX - 1) / InNumThreadsX;
+ uint32_t dispatchHeight = (InPresentInfo.Height + InNumThreadsY - 1) / InNumThreadsY;
+ vkCmdDispatch(InCmdList, dispatchWidth, dispatchHeight, 1);
+
+ // 3. Transition and copy the internal computed target back to 'present'
+ SetImageLayout(InCmdList, _intermediateImage, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ copySubresourceRange);
+ SetImageLayout(InCmdList, InPresentInfo.Image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copySubresourceRange);
+
+ vkCmdCopyImage(InCmdList, _intermediateImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, InPresentInfo.Image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region);
+
+ // 4. Restore original resource states
+ SetImageLayout(InCmdList, InPresentInfo.Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, PresentState,
+ copySubresourceRange);
+ SetImageLayout(InCmdList, InHudlessInfo.Image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, HudlessState,
+ InHudlessInfo.SubresourceRange);
+
+ return true;
+}
diff --git a/OptiScaler/shaders/hud_copy/HudCopy_Vk.h b/OptiScaler/shaders/hud_copy/HudCopy_Vk.h
new file mode 100644
index 00000000..7ed90bee
--- /dev/null
+++ b/OptiScaler/shaders/hud_copy/HudCopy_Vk.h
@@ -0,0 +1,17 @@
+#pragma once
+#include "HudCopy_Common.h"
+
+#include
+
+class HudCopy_Vk : public Shader_Vk, public HudCopy_Common
+{
+ uint32_t InNumThreadsX = 16;
+ uint32_t InNumThreadsY = 16;
+
+ public:
+ HudCopy_Vk(std::string InName, VkDevice InDevice, VkPhysicalDevice InPhysicalDevice);
+ virtual ~HudCopy_Vk() = default;
+
+ bool Dispatch(VkCommandBuffer InCmdList, const VkImageInfo& InHudlessInfo, VkImageLayout HudlessState,
+ const VkImageInfo& InPresentInfo, VkImageLayout PresentState, float HudDetectionThreshold);
+};
diff --git a/OptiScaler/shaders/hud_copy/precompile/HudCopy.hlsl b/OptiScaler/shaders/hud_copy/precompile/HudCopy.hlsl
index 03d281e8..dfbae936 100644
--- a/OptiScaler/shaders/hud_copy/precompile/HudCopy.hlsl
+++ b/OptiScaler/shaders/hud_copy/precompile/HudCopy.hlsl
@@ -1,11 +1,25 @@
+#ifdef VK_MODE
+cbuffer Params : register(b0, space0)
+#else
cbuffer Params : register(b0)
+#endif
{
float DiffThreshold;
};
+#ifdef VK_MODE
+[[vk::binding(1, 0)]]
+#endif
Texture2D Hudless : register(t0);
+
+#ifdef VK_MODE
+[[vk::binding(2, 0)]]
+#endif
Texture2D PresentCopy : register(t1);
+#ifdef VK_MODE
+[[vk::binding(3, 0)]]
+#endif
RWTexture2D Present : register(u0);
[numthreads(16, 16, 1)]
diff --git a/OptiScaler/shaders/hud_copy/precompile/HudCopy_Shader_Vk.h b/OptiScaler/shaders/hud_copy/precompile/HudCopy_Shader_Vk.h
new file mode 100644
index 00000000..cb77725d
--- /dev/null
+++ b/OptiScaler/shaders/hud_copy/precompile/HudCopy_Shader_Vk.h
@@ -0,0 +1,90 @@
+#pragma once
+
+inline static const unsigned char HudCopy_spv[] = {
+ 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x02, 0x00, 0x38, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00,
+ 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x43, 0x53, 0x4d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x05, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x05,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x00,
+ 0x06, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x69, 0x66, 0x66, 0x54, 0x68, 0x72,
+ 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x50, 0x61,
+ 0x72, 0x61, 0x6d, 0x73, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, 0x2e,
+ 0x32, 0x64, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x48, 0x75, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x00, 0x05, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x72, 0x65,
+ 0x73, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x70, 0x79, 0x00, 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x74, 0x79,
+ 0x70, 0x65, 0x2e, 0x32, 0x64, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0a,
+ 0x00, 0x00, 0x00, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x00, 0x05, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x43, 0x53, 0x4d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+ 0x00, 0x1c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47,
+ 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00,
+ 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x21, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x47, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0b, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1e, 0x00, 0x03,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x19, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00,
+ 0x00, 0x12, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x15, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x16,
+ 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x17, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00,
+ 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x1b,
+ 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1d, 0x00,
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4f,
+ 0x00, 0x07, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x21, 0x00,
+ 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x22,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+ 0x21, 0x00, 0x00, 0x00, 0x50, 0x00, 0x06, 0x00, 0x19, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
+ 0x00, 0x23, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x25, 0x00,
+ 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x07, 0x00,
+ 0x1b, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00,
+ 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x07, 0x00,
+ 0x1b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2a, 0x00,
+ 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x83,
+ 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x2c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x2d,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05,
+ 0x00, 0x0d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00,
+ 0x07, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
+ 0x00, 0x33, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00,
+ 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
+ 0x83, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
+ 0x00, 0x8e, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x36, 0x00,
+ 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x38,
+ 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x63, 0x00, 0x05, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
diff --git a/OptiScaler/shaders/hud_copy/precompile/HudCopy_Shader_Vk.spv b/OptiScaler/shaders/hud_copy/precompile/HudCopy_Shader_Vk.spv
new file mode 100644
index 0000000000000000000000000000000000000000..b81c6e3852d689871753d954e63f67110c47b10e
GIT binary patch
literal 1624
zcmZ{kOHY$g5QYzJxk=?B0^$W*>K(0$fK_6m!2}i*Y59@3
z(NI)mu`w|H=mmIf`%SZR5VGhveti@0cw}o9`H25Ou%Ax}{p9qhUEgXRH}|__4Q4*v
z;dN(c=l$++ySsb1*TNQUZiJ!_@QL}0t$Js_`MDi&3>P-OwD#KFF1Y?MWFDp32PbQX
zN2git@PBg8{l$VS{WIG-w$qQmS7B{?&BIc%tLVC5j3n0cUqDu1X$E@|sn7k0zlgM_{z*oz<~UzoXDGXmJ25Us
zvW}Qk>n^%GOttQz>pQE~0)FGNlxlrvC*J*i*nZ;5oK)WfSe$ok++BIUb=a7cd=JqR
zzRYam{Btya3pPhg!aqhApU<4*7qJuGTrscc>Dzh&`<~p7^ILxj*8d}(YdQM-y_VUG
zm=)NX))FtqK56c!=+5lyKdIx~4OqXq-=gmsx)@{j_qX^Q_RW3*qwbp%C;g^t1O5Xr
C5K-R%
literal 0
HcmV?d00001
diff --git a/OptiScaler/shaders/magnifier/Magnifier_Common.h b/OptiScaler/shaders/magnifier/Magnifier_Common.h
index e435ef37..040bc76f 100644
--- a/OptiScaler/shaders/magnifier/Magnifier_Common.h
+++ b/OptiScaler/shaders/magnifier/Magnifier_Common.h
@@ -21,75 +21,86 @@ class Magnifier_Common
float Padding[3]; // Padding to maintain 16-byte alignment
};
+ const std::string shaderCode = R"(
+ #ifdef VK_MODE
+ cbuffer Params : register(b0, space0)
+ #else
+ cbuffer MagnifierCB : register(b0)
+ #endif
+ {
+ float2 Resolution; // Screen or texture resolution in pixels
+ float2 CursorPos; // Cursor position in pixel coordinates
+ float2 Offset; // Offset of the lens relative to the cursor (in pixels)
+ float Radius; // Radius of the magnifying glass (in pixels)
+ int ZoomFactor; // Integer scaling multiplier (e.g., 2, 3, 4)
+ float BorderThickness; // Thickness of the black border (in pixels)
+ float3 Padding; // Padding to maintain 16-byte alignment
+ };
+
+ #ifdef VK_MODE
+ [[vk::binding(1, 0)]]
+ #endif
+ Texture2D InTexture : register(t0);
+
+ #ifdef VK_MODE
+ [[vk::binding(2, 0)]]
+ #endif
+ RWTexture2D OutTexture : register(u0);
+
+ [numthreads(16, 16, 1)]
+ void CSMain(uint3 dispatchThreadId : SV_DispatchThreadID)
+ {
+ // 1. Boundary Guard: Ensure threads outside the texture dimensions do not execute
+ if (dispatchThreadId.x >= (uint) Resolution.x || dispatchThreadId.y >= (uint) Resolution.y)
+ {
+ return;
+ }
+
+ // 2. Determine the current pixel coordinate
+ int2 currentPixelInt = dispatchThreadId.xy;
+ float2 currentPixel = float2(currentPixelInt);
+
+ // 3. Calculate the center of the magnifying lens
+ float2 lensCenter = CursorPos + Offset;
+
+ // 4. Find the distance from the current pixel to the lens center
+ float2 vecToCenter = currentPixel - lensCenter;
+ float dist = length(vecToCenter);
+
+ float4 finalColor;
+
+ // 5. Outside the magnifier: Render the normal, unscaled image
+ if (dist > Radius)
+ {
+ finalColor = InTexture.Load(int3(currentPixelInt, 0));
+ }
+ // 6. Border: Render a black outline
+ else if (dist > Radius - BorderThickness)
+ {
+ finalColor = float4(0.0f, 0.0f, 0.0f, 1.0f); // Black border
+ }
+ // 7. Inside the magnifier: Apply integer scaling
+ else
+ {
+ int maxZoom = max(1, ZoomFactor); // Prevent division by zero
+ float2 scaledOffset = floor(vecToCenter / (float) maxZoom);
+
+ // Calculate the source pixel coordinate around the actual cursor position
+ int2 srcPixel = int2(CursorPos + scaledOffset);
+
+ // Clamp coordinates to ensure we don't sample outside the texture bounds
+ srcPixel = clamp(srcPixel, int2(0, 0), int2(Resolution) - int2(1, 1));
+
+ finalColor = InTexture.Load(int3(srcPixel, 0));
+ }
+
+ // 8. Write the final calculated pixel back to the UAV
+ OutTexture[currentPixelInt] = finalColor;
+ }
+ )";
+
void FilloutStruct(float Width, float Height, InternalMagnifierParams& InternalStruct);
public:
bool ShouldRun();
};
-
-static std::string shaderCode = R"(
-cbuffer MagnifierCB : register(b0)
-{
- float2 Resolution; // Screen or texture resolution in pixels
- float2 CursorPos; // Cursor position in pixel coordinates
- float2 Offset; // Offset of the lens relative to the cursor (in pixels)
- float Radius; // Radius of the magnifying glass (in pixels)
- int ZoomFactor; // Integer scaling multiplier (e.g., 2, 3, 4)
- float BorderThickness; // Thickness of the black border (in pixels)
- float3 Padding; // Padding to maintain 16-byte alignment
-};
-
-Texture2D InTexture : register(t0);
-RWTexture2D OutTexture : register(u0);
-
-[numthreads(16, 16, 1)]
-void CSMain(uint3 dispatchThreadId : SV_DispatchThreadID)
-{
- // 1. Boundary Guard: Ensure threads outside the texture dimensions do not execute
- if (dispatchThreadId.x >= (uint) Resolution.x || dispatchThreadId.y >= (uint) Resolution.y)
- {
- return;
- }
-
- // 2. Determine the current pixel coordinate
- int2 currentPixelInt = dispatchThreadId.xy;
- float2 currentPixel = float2(currentPixelInt);
-
- // 3. Calculate the center of the magnifying lens
- float2 lensCenter = CursorPos + Offset;
-
- // 4. Find the distance from the current pixel to the lens center
- float2 vecToCenter = currentPixel - lensCenter;
- float dist = length(vecToCenter);
-
- float4 finalColor;
-
- // 5. Outside the magnifier: Render the normal, unscaled image
- if (dist > Radius)
- {
- finalColor = InTexture.Load(int3(currentPixelInt, 0));
- }
- // 6. Border: Render a black outline
- else if (dist > Radius - BorderThickness)
- {
- finalColor = float4(0.0f, 0.0f, 0.0f, 1.0f); // Black border
- }
- // 7. Inside the magnifier: Apply integer scaling
- else
- {
- int maxZoom = max(1, ZoomFactor); // Prevent division by zero
- float2 scaledOffset = floor(vecToCenter / (float) maxZoom);
-
- // Calculate the source pixel coordinate around the actual cursor position
- int2 srcPixel = int2(CursorPos + scaledOffset);
-
- // Clamp coordinates to ensure we don't sample outside the texture bounds
- srcPixel = clamp(srcPixel, int2(0, 0), int2(Resolution) - int2(1, 1));
-
- finalColor = InTexture.Load(int3(srcPixel, 0));
- }
-
- // 8. Write the final calculated pixel back to the UAV
- OutTexture[currentPixelInt] = finalColor;
-}
-)";