Skip to content

Commit

Permalink
GS/HW: Reduce number of copies for HDR
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Feb 1, 2025
1 parent df7646f commit 0321db3
Show file tree
Hide file tree
Showing 12 changed files with 614 additions and 256 deletions.
6 changes: 4 additions & 2 deletions bin/resources/shaders/dx11/tfx.fx
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,8 @@ void ps_fbmask(inout float4 C, float2 pos_xy)
{
if (PS_FBMASK)
{
float4 RT = trunc(RtTexture.Load(int3(pos_xy, 0)) * 255.0f + 0.1f);
float multi = PS_HDR ? 65535.0f : 255.0f;
float4 RT = trunc(RtTexture.Load(int3(pos_xy, 0)) * multi + 0.1f);
C = (float4)(((uint4)C & ~FbMask) | ((uint4)RT & FbMask));
}
}
Expand Down Expand Up @@ -895,7 +896,8 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
}

float Ad = PS_RTA_CORRECTION ? trunc(RT.a * 128.0f + 0.1f) / 128.0f : trunc(RT.a * 255.0f + 0.1f) / 128.0f;
float3 Cd = trunc(RT.rgb * 255.0f + 0.1f);
float color_multi = PS_HDR ? 65535.0f : 255.0f;
float3 Cd = trunc(RT.rgb * color_multi + 0.1f);
float3 Cs = Color.rgb;

float3 A = (PS_BLEND_A == 0) ? Cs : ((PS_BLEND_A == 1) ? Cd : (float3)0.0f);
Expand Down
12 changes: 10 additions & 2 deletions bin/resources/shaders/opengl/tfx_fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,11 @@ void ps_fbmask(inout vec4 C)
{
// FIXME do I need special case for 16 bits
#if PS_FBMASK
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
#if PS_HDR == 1
vec4 RT = trunc(fetch_rt() * 65535.0f);
#else
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
#endif
C = vec4((uvec4(C) & ~FbMask) | (uvec4(RT) & FbMask));
#endif
}
Expand Down Expand Up @@ -823,7 +827,11 @@ float As = As_rgba.a;
#endif

// Let the compiler do its jobs !
vec3 Cd = trunc(RT.rgb * 255.0f + 0.1f);
#if PS_HDR == 1
vec3 Cd = trunc(RT.rgb * 65535.0f);
#else
vec3 Cd = trunc(RT.rgb * 255.0f + 0.1f);
#endif
vec3 Cs = Color.rgb;

#if PS_BLEND_A == 0
Expand Down
11 changes: 10 additions & 1 deletion bin/resources/shaders/vulkan/tfx.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,12 @@ vec4 ps_color()
void ps_fbmask(inout vec4 C)
{
#if PS_FBMASK
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);

#if PS_HDR == 1
vec4 RT = trunc(sample_from_rt() * 65535.0f);
#else
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
#endif
C = vec4((uvec4(C) & ~FbMask) | (uvec4(RT) & FbMask));
#endif
}
Expand Down Expand Up @@ -1090,7 +1095,11 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
#endif

// Let the compiler do its jobs !
#if PS_HDR == 1
vec3 Cd = trunc(RT.rgb * 65535.0f);
#else
vec3 Cd = trunc(RT.rgb * 255.0f + 0.1f);
#endif
vec3 Cs = Color.rgb;

#if PS_BLEND_A == 0
Expand Down
20 changes: 20 additions & 0 deletions pcsx2/GS/Renderers/Common/GSDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "GS/GS.h"
#include "GS/Renderers/Common/GSFastList.h"
#include "GS/Renderers/Common/GSTexture.h"
#include "GS/Renderers/Vulkan/GSTextureVK.h"
#include "GS/Renderers/Common/GSVertex.h"
#include "GS/GSAlignedClass.h"
#include "GS/GSExtra.h"
Expand Down Expand Up @@ -674,6 +675,15 @@ struct alignas(16) GSHWDrawConfig
Full, ///< Full emulation (using barriers / ROV)
};

enum class HDRMode : u8
{
NoModify = 0,
ConvertOnly = 1,
ResolveOnly = 2,
ConvertAndResolve = 3,
EarlyResolve = 4
};

GSTexture* rt; ///< Render target
GSTexture* ds; ///< Depth stencil
GSTexture* tex; ///< Source texture
Expand Down Expand Up @@ -730,6 +740,11 @@ struct alignas(16) GSHWDrawConfig

VSConstantBuffer cb_vs;
PSConstantBuffer cb_ps;

// These are here as they need to be preserved between draws, and the state clear only does up to the constant buffers.
HDRMode hdr_mode;
GIFRegFRAME hdr_frame;
GSVector4i hdr_update_area; ///< Area in the framebuffer which HDR will modify;
};

class GSDevice : public GSAlignedClass<32>
Expand Down Expand Up @@ -850,6 +865,7 @@ class GSDevice : public GSAlignedClass<32>
GSTexture* m_target_tmp = nullptr;
GSTexture* m_current = nullptr;
GSTexture* m_cas = nullptr;
GSTexture* m_hdr_rt = nullptr; ///< Temp HDR texture

bool AcquireWindow(bool recreate_window);

Expand All @@ -874,6 +890,10 @@ class GSDevice : public GSAlignedClass<32>
/// Returns a string containing current adapter in use.
const std::string& GetName() const { return m_name; }

GSTexture* GetHDRTexture() const { return m_hdr_rt; }

void SetHDRTexture(GSTexture* tex) { m_hdr_rt = tex; }

/// Returns a string representing the specified API.
static const char* RenderAPIToString(RenderAPI api);

Expand Down
81 changes: 57 additions & 24 deletions pcsx2/GS/Renderers/DX11/GSDevice11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2521,14 +2521,55 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)

GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();

GSTexture* hdr_rt = g_gs_device->GetHDRTexture();

if (hdr_rt)
{
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
{
const GSVector2i size = config.rt->GetSize();
const GSVector4 dRect(config.hdr_update_area);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);

g_gs_device->SetHDRTexture(nullptr);

hdr_rt = nullptr;
}
else
config.ps.hdr = 1;
}

if (config.ps.hdr)
{
if (!hdr_rt)
{
config.hdr_update_area = config.drawarea;

const GSVector4 dRect = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
hdr_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor);
if (!hdr_rt)
return;

g_gs_device->SetHDRTexture(hdr_rt);
// Warning: StretchRect must be called before BeginScene otherwise
// vertices will be overwritten. Trust me you don't want to do that.
StretchRect(config.rt, sRect, hdr_rt, dRect, ShaderConvert::HDR_INIT, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
}

GSTexture* primid_tex = nullptr;
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking)
{
primid_tex = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::PrimID, false);
if (!primid_tex)
return;

StretchRect(config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
StretchRect(hdr_rt ? hdr_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
primid_tex, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(config.datm)].get(), nullptr, false);
}
else if (config.destination_alpha != GSHWDrawConfig::DestinationAlphaMode::Off)
Expand All @@ -2544,22 +2585,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
};

SetupDATE(config.rt, config.ds, vertices, config.datm);
}

GSTexture* hdr_rt = nullptr;
if (config.ps.hdr)
{
const GSVector4 dRect(config.drawarea);
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
hdr_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor);
if (!hdr_rt)
return;

// Warning: StretchRect must be called before BeginScene otherwise
// vertices will be overwritten. Trust me you don't want to do that.
StretchRect(config.rt, sRect, hdr_rt, dRect, ShaderConvert::HDR_INIT, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
SetupDATE(hdr_rt ? hdr_rt : config.rt, config.ds, vertices, config.datm);
}

if (config.vs.expand != GSHWDrawConfig::VSExpand::None)
Expand Down Expand Up @@ -2623,7 +2649,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
// Do not always bind the rt when it's not needed,
// only bind it when effects use it such as fbmask emulation currently
// because we copy the frame buffer and it is quite slow.
CloneTexture(config.rt, &rt_copy, config.drawarea);
CloneTexture(hdr_rt ? hdr_rt : config.rt, &rt_copy, config.drawarea);
if (rt_copy)
{
if (config.require_one_barrier)
Expand Down Expand Up @@ -2690,11 +2716,18 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)

if (hdr_rt)
{
const GSVector2i size = config.rt->GetSize();
const GSVector4 dRect(config.drawarea);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);

if (config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve)
{
const GSVector2i size = config.rt->GetSize();
const GSVector4 dRect(config.hdr_update_area);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);

g_gs_device->SetHDRTexture(nullptr);
}
}
}
Loading

0 comments on commit 0321db3

Please sign in to comment.