mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
Depth of Field scaling fix. (#22)
* Initial DoF fix experiments. * Implement proper DoF weighting & add quality options. Co-authored-by: Dario <dariosamo@gmail.com> * Change auto resolutions, remove from options menu. * Precompile pipelines for the custom gaussian blur shaders. --------- Co-authored-by: Dario <dariosamo@gmail.com>
This commit is contained in:
parent
8c44d62ed9
commit
4bd8d10d61
10 changed files with 212 additions and 3 deletions
|
|
@ -284,6 +284,10 @@ function(compile_pixel_shader FILE_PATH)
|
|||
endfunction()
|
||||
|
||||
compile_vertex_shader(copy_vs)
|
||||
compile_pixel_shader(gaussian_blur_3x3)
|
||||
compile_pixel_shader(gaussian_blur_5x5)
|
||||
compile_pixel_shader(gaussian_blur_7x7)
|
||||
compile_pixel_shader(gaussian_blur_9x9)
|
||||
compile_pixel_shader(gamma_correction_ps)
|
||||
compile_pixel_shader(imgui_ps)
|
||||
compile_vertex_shader(imgui_vs)
|
||||
|
|
|
|||
71
UnleashedRecomp/gpu/shader/gaussian_blur.hlsli
Normal file
71
UnleashedRecomp/gpu/shader/gaussian_blur.hlsli
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#include "../../../thirdparty/ShaderRecomp/ShaderRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
||||
#define g_ViewportSize vk::RawBufferLoad<float4>(g_PushConstants.PixelShaderConstants + 384, 0x10)
|
||||
#define g_offsets(INDEX) select((INDEX) < 74, vk::RawBufferLoad<float4>(g_PushConstants.PixelShaderConstants + (150 + min(INDEX, 73)) * 16, 0x10), 0.0)
|
||||
#define g_weights vk::RawBufferLoad<float4>(g_PushConstants.PixelShaderConstants + 2656, 0x10)
|
||||
|
||||
#define s0_Texture2DDescriptorIndex vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 0)
|
||||
#define s0_SamplerDescriptorIndex vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 192)
|
||||
|
||||
#else
|
||||
|
||||
cbuffer PixelShaderConstants : register(b1, space4)
|
||||
{
|
||||
float4 g_ViewportSize : packoffset(c24);
|
||||
float4 g_offsets[2] : packoffset(c150);
|
||||
#define g_offsets(INDEX) select((INDEX) < 74, g_offsets[min(INDEX, 73)], 0.0)
|
||||
float4 g_weights : packoffset(c166);
|
||||
};
|
||||
|
||||
cbuffer SharedConstants : register(b2, space4)
|
||||
{
|
||||
uint s0_Texture2DDescriptorIndex : packoffset(c0.x);
|
||||
uint s0_SamplerDescriptorIndex : packoffset(c12.x);
|
||||
DEFINE_SHARED_CONSTANTS();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __INTELLISENSE__
|
||||
#define KERNEL_SIZE 5
|
||||
#endif
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
float ComputeWeight(float x)
|
||||
{
|
||||
float std = 0.952;
|
||||
return exp(-(x * x) / (2.0 * std * std)) / (std * sqrt(2.0 * PI));
|
||||
}
|
||||
|
||||
float4 main(in float4 iPosition : SV_Position, in float4 iTexCoord0 : TEXCOORD0) : SV_Target
|
||||
{
|
||||
Texture2D<float4> texture = g_Texture2DDescriptorHeap[s0_Texture2DDescriptorIndex];
|
||||
SamplerState samplerState = g_SamplerDescriptorHeap[s0_SamplerDescriptorIndex];
|
||||
|
||||
float scale = g_ViewportSize.y / 360.0;
|
||||
|
||||
float2 offsets[3];
|
||||
offsets[0] = g_offsets(0).xy * scale;
|
||||
offsets[1] = g_offsets(0).zw * scale;
|
||||
offsets[2] = g_offsets(1).xy * scale;
|
||||
|
||||
float4 color = 0.0;
|
||||
float weightSum = 0.0;
|
||||
|
||||
[unroll]
|
||||
for (int i = 0; i < KERNEL_SIZE; i++)
|
||||
{
|
||||
float step = i / float(KERNEL_SIZE - 1);
|
||||
float scaled = step * 2;
|
||||
float2 offset = lerp(offsets[int(scaled)], offsets[min(int(scaled) + 1, 2)], frac(scaled));
|
||||
float offsetScale = 1.0 / 0.75;
|
||||
float weight = ComputeWeight(lerp(-offsetScale, offsetScale, step));
|
||||
color += texture.Sample(samplerState, iTexCoord0.xy + offset) * weight;
|
||||
weightSum += weight;
|
||||
}
|
||||
|
||||
return color / weightSum;
|
||||
}
|
||||
2
UnleashedRecomp/gpu/shader/gaussian_blur_3x3.hlsl
Normal file
2
UnleashedRecomp/gpu/shader/gaussian_blur_3x3.hlsl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#define KERNEL_SIZE 3
|
||||
#include "gaussian_blur.hlsli"
|
||||
2
UnleashedRecomp/gpu/shader/gaussian_blur_5x5.hlsl
Normal file
2
UnleashedRecomp/gpu/shader/gaussian_blur_5x5.hlsl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#define KERNEL_SIZE 5
|
||||
#include "gaussian_blur.hlsli"
|
||||
2
UnleashedRecomp/gpu/shader/gaussian_blur_7x7.hlsl
Normal file
2
UnleashedRecomp/gpu/shader/gaussian_blur_7x7.hlsl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#define KERNEL_SIZE 7
|
||||
#include "gaussian_blur.hlsli"
|
||||
2
UnleashedRecomp/gpu/shader/gaussian_blur_9x9.hlsl
Normal file
2
UnleashedRecomp/gpu/shader/gaussian_blur_9x9.hlsl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#define KERNEL_SIZE 9
|
||||
#include "gaussian_blur.hlsli"
|
||||
|
|
@ -34,6 +34,14 @@
|
|||
#include "../../thirdparty/ShaderRecomp/ShaderRecomp/shader_common.h"
|
||||
#include "shader/copy_vs.hlsl.dxil.h"
|
||||
#include "shader/copy_vs.hlsl.spirv.h"
|
||||
#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
|
||||
#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
|
||||
#include "shader/gaussian_blur_5x5.hlsl.dxil.h"
|
||||
#include "shader/gaussian_blur_5x5.hlsl.spirv.h"
|
||||
#include "shader/gaussian_blur_7x7.hlsl.dxil.h"
|
||||
#include "shader/gaussian_blur_7x7.hlsl.spirv.h"
|
||||
#include "shader/gaussian_blur_9x9.hlsl.dxil.h"
|
||||
#include "shader/gaussian_blur_9x9.hlsl.spirv.h"
|
||||
#include "shader/gamma_correction_ps.hlsl.dxil.h"
|
||||
#include "shader/gamma_correction_ps.hlsl.spirv.h"
|
||||
#include "shader/imgui_ps.hlsl.dxil.h"
|
||||
|
|
@ -1025,6 +1033,17 @@ static const std::pair<GuestRenderState, void*> g_setRenderStateFunctions[] =
|
|||
|
||||
static std::unique_ptr<RenderPipeline> g_resolveMsaaDepthPipelines[3];
|
||||
|
||||
enum
|
||||
{
|
||||
GAUSSIAN_BLUR_3X3,
|
||||
GAUSSIAN_BLUR_5X5,
|
||||
GAUSSIAN_BLUR_7X7,
|
||||
GAUSSIAN_BLUR_9X9,
|
||||
GAUSSIAN_BLUR_COUNT
|
||||
};
|
||||
|
||||
static std::unique_ptr<GuestShader> g_gaussianBlurShaders[GAUSSIAN_BLUR_COUNT];
|
||||
|
||||
#define CREATE_SHADER(NAME) \
|
||||
g_device->createShader( \
|
||||
g_vulkan ? g_##NAME##_spirv : g_##NAME##_dxil, \
|
||||
|
|
@ -1416,6 +1435,14 @@ void Video::CreateHostDevice()
|
|||
g_resolveMsaaDepthPipelines[i] = g_device->createGraphicsPipeline(desc);
|
||||
}
|
||||
|
||||
for (auto& shader : g_gaussianBlurShaders)
|
||||
shader = std::make_unique<GuestShader>(ResourceType::PixelShader);
|
||||
|
||||
g_gaussianBlurShaders[GAUSSIAN_BLUR_3X3]->shader = CREATE_SHADER(gaussian_blur_3x3);
|
||||
g_gaussianBlurShaders[GAUSSIAN_BLUR_5X5]->shader = CREATE_SHADER(gaussian_blur_5x5);
|
||||
g_gaussianBlurShaders[GAUSSIAN_BLUR_7X7]->shader = CREATE_SHADER(gaussian_blur_7x7);
|
||||
g_gaussianBlurShaders[GAUSSIAN_BLUR_9X9]->shader = CREATE_SHADER(gaussian_blur_9x9);
|
||||
|
||||
CreateImGuiBackend();
|
||||
|
||||
auto gammaCorrectionShader = CREATE_SHADER(gamma_correction_ps);
|
||||
|
|
@ -3844,7 +3871,53 @@ static void SetPixelShader(GuestDevice* device, GuestShader* shader)
|
|||
|
||||
static void ProcSetPixelShader(const RenderCommand& cmd)
|
||||
{
|
||||
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.pixelShader, cmd.setPixelShader.shader);
|
||||
GuestShader* shader = cmd.setPixelShader.shader;
|
||||
if (shader != nullptr &&
|
||||
shader->shaderCacheEntry != nullptr &&
|
||||
shader->shaderCacheEntry->hash == 0x4294510C775F4EE8)
|
||||
{
|
||||
size_t shaderIndex = GAUSSIAN_BLUR_3X3;
|
||||
|
||||
switch (Config::DepthOfFieldQuality)
|
||||
{
|
||||
case EDepthOfFieldQuality::Low:
|
||||
shaderIndex = GAUSSIAN_BLUR_3X3;
|
||||
break;
|
||||
|
||||
case EDepthOfFieldQuality::Medium:
|
||||
shaderIndex = GAUSSIAN_BLUR_5X5;
|
||||
break;
|
||||
|
||||
case EDepthOfFieldQuality::High:
|
||||
shaderIndex = GAUSSIAN_BLUR_7X7;
|
||||
break;
|
||||
|
||||
case EDepthOfFieldQuality::Ultra:
|
||||
shaderIndex = GAUSSIAN_BLUR_9X9;
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
size_t height = round(g_swapChain->getHeight() * Config::ResolutionScale);
|
||||
|
||||
// Use the middle point between resolutions to have the transition less noticable.
|
||||
if (height >= ((2160 + 1440) / 2))
|
||||
shaderIndex = GAUSSIAN_BLUR_9X9;
|
||||
else if (height >= ((1440 + 1080) / 2))
|
||||
shaderIndex = GAUSSIAN_BLUR_7X7;
|
||||
else if (height >= ((1080 + 720) / 2))
|
||||
shaderIndex = GAUSSIAN_BLUR_5X5;
|
||||
else
|
||||
shaderIndex = GAUSSIAN_BLUR_3X3;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shader = g_gaussianBlurShaders[shaderIndex].get();
|
||||
}
|
||||
|
||||
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.pixelShader, shader);
|
||||
}
|
||||
|
||||
static std::thread g_renderThread([]
|
||||
|
|
@ -5391,9 +5464,24 @@ static void ModelConsumerThread()
|
|||
EnqueueGraphicsPipelineCompilation(msaaPipelineState, emptyHolderPair, "Precompiled Pipeline MSAA");
|
||||
}
|
||||
|
||||
// Compile the custom gaussian blur shaders that we pass to the game.
|
||||
if (pipelineState.pixelShader != nullptr &&
|
||||
pipelineState.pixelShader->shaderCacheEntry != nullptr &&
|
||||
pipelineState.pixelShader->shaderCacheEntry->hash == 0x4294510C775F4EE8)
|
||||
{
|
||||
for (auto& shader : g_gaussianBlurShaders)
|
||||
{
|
||||
pipelineState.pixelShader = shader.get();
|
||||
SanitizePipelineState(pipelineState);
|
||||
EnqueueGraphicsPipelineCompilation(pipelineState, emptyHolderPair, "Precompiled Gaussian Blur Pipeline");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SanitizePipelineState(pipelineState);
|
||||
EnqueueGraphicsPipelineCompilation(pipelineState, emptyHolderPair, "Precompiled Pipeline");
|
||||
}
|
||||
}
|
||||
|
||||
g_pendingPipelineStateCache = false;
|
||||
--g_pendingDataCount;
|
||||
|
|
|
|||
|
|
@ -309,6 +309,25 @@ CONFIG_DEFINE_ENUM_LOCALE(EGITextureFiltering)
|
|||
}
|
||||
};
|
||||
|
||||
CONFIG_DEFINE_LOCALE(DepthOfFieldQuality)
|
||||
{
|
||||
{ ELanguage::English, { "Depth of Field Quality", "[PLACEHOLDER]" } }
|
||||
};
|
||||
|
||||
CONFIG_DEFINE_ENUM_LOCALE(EDepthOfFieldQuality)
|
||||
{
|
||||
{
|
||||
ELanguage::English,
|
||||
{
|
||||
{ EDepthOfFieldQuality::Auto, { "AUTO", "" } },
|
||||
{ EDepthOfFieldQuality::Low, { "LOW", "" } },
|
||||
{ EDepthOfFieldQuality::Medium, { "MEDIUM", "" } },
|
||||
{ EDepthOfFieldQuality::High, { "HIGH", "" } },
|
||||
{ EDepthOfFieldQuality::Ultra, { "ULTRA", "" } },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CONFIG_DEFINE_LOCALE(MotionBlur)
|
||||
{
|
||||
{ ELanguage::English, { "Motion Blur", "Use per-object motion blur and radial blur." } }
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ public:
|
|||
CONFIG_DEFINE("Video", size_t, AnisotropicFiltering, 16);
|
||||
CONFIG_DEFINE_ENUM_LOCALISED("Video", EShadowResolution, ShadowResolution, EShadowResolution::x4096);
|
||||
CONFIG_DEFINE_ENUM_LOCALISED("Video", EGITextureFiltering, GITextureFiltering, EGITextureFiltering::Bicubic);
|
||||
CONFIG_DEFINE_ENUM_LOCALISED("Video", EDepthOfFieldQuality, DepthOfFieldQuality, EDepthOfFieldQuality::Auto);
|
||||
CONFIG_DEFINE_LOCALISED("Video", bool, MotionBlur, true);
|
||||
CONFIG_DEFINE_LOCALISED("Video", bool, XboxColourCorrection, false);
|
||||
CONFIG_DEFINE_ENUM_LOCALISED("Video", EMovieScaleMode, MovieScaleMode, EMovieScaleMode::Fit);
|
||||
|
|
|
|||
|
|
@ -192,6 +192,24 @@ CONFIG_DEFINE_ENUM_TEMPLATE(EGITextureFiltering)
|
|||
{ "Bicubic", EGITextureFiltering::Bicubic }
|
||||
};
|
||||
|
||||
enum class EDepthOfFieldQuality : uint32_t
|
||||
{
|
||||
Auto,
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
Ultra
|
||||
};
|
||||
|
||||
CONFIG_DEFINE_ENUM_TEMPLATE(EDepthOfFieldQuality)
|
||||
{
|
||||
{ "Auto", EDepthOfFieldQuality::Auto },
|
||||
{ "Low", EDepthOfFieldQuality::Low },
|
||||
{ "Medium", EDepthOfFieldQuality::Medium },
|
||||
{ "High", EDepthOfFieldQuality::High },
|
||||
{ "Ultra", EDepthOfFieldQuality::Ultra }
|
||||
};
|
||||
|
||||
enum class EMovieScaleMode : uint32_t
|
||||
{
|
||||
Stretch,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue