Compare commits

...

13 Commits

Author SHA1 Message Date
GregoireLD
a19bb91041 GameDB: Add a new Ico version (#11103) 2025-04-18 13:33:51 -04:00
Filoppi
a545982a28 GS: Fix crash if CAS pipeline failed to compile (it'd crash when the user enables CAS, which is still enough of a good reason to make the whole rendering backend fail to initialize) 2025-04-18 19:11:11 +02:00
Filoppi
2109df04ca GS: Remove duplicate shader creation for RTA correction. The same shader would have been created just above. 2025-04-18 19:11:11 +02:00
Filoppi
f485cf8ebc GS: fix more badly named debug objects 2025-04-18 19:11:11 +02:00
Filoppi
bb48110f95 GS: Fix VK also naming the wrong pipelines 2025-04-18 19:11:11 +02:00
Filoppi
718adda749 GS: Fix DX12 setting the object names for the wrong pipelines (possibly causing random memory writes), also fix some bad naming 2025-04-18 19:11:11 +02:00
Filoppi
a170c7ccb1 GS: Fix DX12 m_color_copy shaders not applying the right RTA_CORRECTION offset (see the VK implementation, which is identical except for this issue) 2025-04-18 19:11:11 +02:00
Filoppi
fec3fe3b6b GS: Add DX11 shaders debug names 2025-04-18 19:11:11 +02:00
Filoppi
00f19c9777 GS: Fix displays that are currently unplugged (disabled) from throwing unnecessary warnings 2025-04-18 19:11:11 +02:00
Filoppi
93aae28593 GS: Polish spacing and comments 2025-04-18 19:11:11 +02:00
Filoppi
8be2b907b3 GS: Add actual HDR and HQ textures and rename the "HDR" textures to colclip (hw) given that's actually what they are (HDR was a very loose term for it) 2025-04-18 19:11:11 +02:00
Filoppi
fcca07765b GS: Clarify HW blends code a bit 2025-04-18 19:11:11 +02:00
EXtremeExploit
559e4e75eb GameDB: Add memcard filters for Mortal Kombat Armageddon Premium 2025-04-18 10:10:16 -04:00
30 changed files with 477 additions and 421 deletions

View File

@@ -4578,6 +4578,17 @@ SCED-55120:
SCED-55432:
name: "Buzz! Junior - Ace Racers [Demo]"
region: "PAL-M15"
SCES-00000:
name: "Ico [Preview]"
region: "PAL-M5"
compat: 5
clampModes:
eeClampMode: 2 # Otherwise freezes in various spots, check full intro.
vuClampMode: 1 # Otherwise camera does not focus correctly on main character.
gsHWFixes:
mipmap: 1
halfPixelOffset: 1 # Fixes effect misalignment.
moveHandler: "MV_Ico" # Fixes depth buffer post-processing.
SCES-50000:
name: "Ridge Racer V"
region: "PAL-M5"
@@ -69521,6 +69532,9 @@ SLUS-21410:
name: "Mortal Kombat - Armageddon"
region: "NTSC-U"
compat: 5
memcardFilters: # Saves from the non-Premium can be imported
- "SLUS-21410"
- "SLUS-21543"
SLUS-21411:
name: "M2 Rock"
region: "NTSC-U"
@@ -70163,6 +70177,9 @@ SLUS-21543:
name: "Mortal Kombat - Armageddon [Premium Edition]"
region: "NTSC-U"
compat: 5
memcardFilters: # Saves from the non-Premium can be imported
- "SLUS-21543"
- "SLUS-21410"
SLUS-21544:
name: "Fantastic 4 - Rise of Silver Surfer"
region: "NTSC-U"

View File

@@ -170,7 +170,7 @@ PS_OUTPUT ps_rta_decorrection(PS_INPUT input)
return output;
}
PS_OUTPUT ps_hdr_init(PS_INPUT input)
PS_OUTPUT ps_colclip_init(PS_INPUT input)
{
PS_OUTPUT output;
float4 value = sample_c(input.t);
@@ -178,7 +178,7 @@ PS_OUTPUT ps_hdr_init(PS_INPUT input)
return output;
}
PS_OUTPUT ps_hdr_resolve(PS_INPUT input)
PS_OUTPUT ps_colclip_resolve(PS_INPUT input)
{
PS_OUTPUT output;
float4 value = sample_c(input.t);

View File

@@ -55,7 +55,7 @@
#define PS_CHANNEL_FETCH 0
#define PS_TALES_OF_ABYSS_HLE 0
#define PS_URBAN_CHAOS_HLE 0
#define PS_HDR 0
#define PS_COLCLIP_HW 0
#define PS_RTA_CORRECTION 0
#define PS_RTA_SRC_CORRECTION 0
#define PS_COLCLIP 0
@@ -799,7 +799,7 @@ void ps_fbmask(inout float4 C, float2 pos_xy)
{
if (PS_FBMASK)
{
float multi = PS_HDR ? 65535.0f : 255.0f;
float multi = PS_COLCLIP_HW ? 65535.0f : 255.0f;
float4 RT = trunc(RtTexture.Load(int3(pos_xy, 0)) * multi + 0.1f);
C = (float4)(((uint4)C & ~FbMask) | ((uint4)RT & FbMask));
}
@@ -843,13 +843,13 @@ void ps_color_clamp_wrap(inout float3 C)
C += 7.0f; // Need to round up, not down since the shader will invert
// Standard Clamp
if (PS_COLCLIP == 0 && PS_HDR == 0)
if (PS_COLCLIP == 0 && PS_COLCLIP_HW == 0)
C = clamp(C, (float3)0.0f, (float3)255.0f);
// In 16 bits format, only 5 bits of color are used. It impacts shadows computation of Castlevania
if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && (PS_BLEND_MIX == 0 || PS_DITHER))
C = (float3)((int3)C & (int3)0xF8);
else if (PS_COLCLIP == 1 || PS_HDR == 1)
else if (PS_COLCLIP == 1 || PS_COLCLIP_HW == 1)
C = (float3)((int3)C & (int3)0xFF);
}
else if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && PS_BLEND_MIX == 0 && PS_BLEND_HW == 0)
@@ -898,7 +898,7 @@ 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;
float color_multi = PS_HDR ? 65535.0f : 255.0f;
float color_multi = PS_COLCLIP_HW ? 65535.0f : 255.0f;
float3 Cd = trunc(RT.rgb * color_multi + 0.1f);
float3 Cs = Color.rgb;
@@ -1157,7 +1157,7 @@ PS_OUTPUT ps_main(PS_INPUT input)
#if !PS_NO_COLOR
output.c0.a = PS_RTA_CORRECTION ? C.a / 128.0f : C.a / 255.0f;
output.c0.rgb = PS_HDR ? float3(C.rgb / 65535.0f) : C.rgb / 255.0f;
output.c0.rgb = PS_COLCLIP_HW ? float3(C.rgb / 65535.0f) : C.rgb / 255.0f;
#if !PS_NO_COLOR1
output.c1 = alpha_blend;
#endif

View File

@@ -348,16 +348,16 @@ void ps_rta_decorrection()
}
#endif
#ifdef ps_hdr_init
void ps_hdr_init()
#ifdef ps_colclip_init
void ps_colclip_init()
{
vec4 value = sample_c();
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
}
#endif
#ifdef ps_hdr_resolve
void ps_hdr_resolve()
#ifdef ps_colclip_resolve
void ps_colclip_resolve()
{
vec4 value = sample_c();
SV_Target0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);

View File

@@ -707,7 +707,7 @@ void ps_fbmask(inout vec4 C)
{
// FIXME do I need special case for 16 bits
#if PS_FBMASK
#if PS_HDR == 1
#if PS_COLCLIP_HW == 1
vec4 RT = trunc(sample_from_rt() * 65535.0f);
#else
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
@@ -757,7 +757,7 @@ void ps_color_clamp_wrap(inout vec3 C)
#endif
// Correct the Color value based on the output format
#if PS_COLCLIP == 0 && PS_HDR == 0
#if PS_COLCLIP == 0 && PS_COLCLIP_HW == 0
// Standard Clamp
C = clamp(C, vec3(0.0f), vec3(255.0f));
#endif
@@ -771,7 +771,7 @@ void ps_color_clamp_wrap(inout vec3 C)
#if PS_DST_FMT == FMT_16 && PS_DITHER < 3 && (PS_BLEND_MIX == 0 || PS_DITHER)
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
C = vec3(ivec3(C) & ivec3(0xF8));
#elif PS_COLCLIP == 1 || PS_HDR == 1
#elif PS_COLCLIP == 1 || PS_COLCLIP_HW == 1
C = vec3(ivec3(C) & ivec3(0xFF));
#endif
@@ -828,7 +828,7 @@ float As = As_rgba.a;
#endif
// Let the compiler do its jobs !
#if PS_HDR == 1
#if PS_COLCLIP_HW == 1
vec3 Cd = trunc(RT.rgb * 65535.0f);
#else
vec3 Cd = trunc(RT.rgb * 255.0f + 0.1f);
@@ -1125,7 +1125,7 @@ void ps_main()
#else
SV_Target0.a = C.a / 255.0f;
#endif
#if PS_HDR == 1
#if PS_COLCLIP_HW == 1
SV_Target0.rgb = vec3(C.rgb / 65535.0f);
#else
SV_Target0.rgb = C.rgb / 255.0f;

View File

@@ -148,16 +148,16 @@ void ps_rta_decorrection()
}
#endif
#ifdef ps_hdr_init
void ps_hdr_init()
#ifdef ps_colclip_init
void ps_colclip_init()
{
vec4 value = sample_c(v_tex);
o_col0 = vec4(roundEven(value.rgb * 255.0f) / 65535.0f, value.a);
}
#endif
#ifdef ps_hdr_resolve
void ps_hdr_resolve()
#ifdef ps_colclip_resolve
void ps_colclip_resolve()
{
vec4 value = sample_c(v_tex);
o_col0 = vec4(vec3(uvec3(value.rgb * 65535.5f) & 255u) / 255.0f, value.a);

View File

@@ -281,7 +281,7 @@ void main()
#define PS_CHANNEL_FETCH 0
#define PS_TALES_OF_ABYSS_HLE 0
#define PS_URBAN_CHAOS_HLE 0
#define PS_HDR 0
#define PS_COLCLIP_HW 0
#define PS_COLCLIP 0
#define PS_BLEND_A 0
#define PS_BLEND_B 0
@@ -974,7 +974,7 @@ void ps_fbmask(inout vec4 C)
{
#if PS_FBMASK
#if PS_HDR == 1
#if PS_COLCLIP_HW == 1
vec4 RT = trunc(sample_from_rt() * 65535.0f);
#else
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
@@ -1027,7 +1027,7 @@ void ps_color_clamp_wrap(inout vec3 C)
#endif
// Correct the Color value based on the output format
#if PS_COLCLIP == 0 && PS_HDR == 0
#if PS_COLCLIP == 0 && PS_COLCLIP_HW == 0
// Standard Clamp
C = clamp(C, vec3(0.0f), vec3(255.0f));
#endif
@@ -1041,7 +1041,7 @@ void ps_color_clamp_wrap(inout vec3 C)
#if PS_DST_FMT == FMT_16 && PS_DITHER != 3 && (PS_BLEND_MIX == 0 || PS_DITHER > 0)
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
C = vec3(ivec3(C) & ivec3(0xF8));
#elif PS_COLCLIP == 1 || PS_HDR == 1
#elif PS_COLCLIP == 1 || PS_COLCLIP_HW == 1
C = vec3(ivec3(C) & ivec3(0xFF));
#endif
@@ -1098,7 +1098,7 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
#endif
// Let the compiler do its jobs !
#if PS_HDR == 1
#if PS_COLCLIP_HW == 1
vec3 Cd = trunc(RT.rgb * 65535.0f);
#else
vec3 Cd = trunc(RT.rgb * 255.0f + 0.1f);
@@ -1390,7 +1390,7 @@ void main()
#else
o_col0.a = C.a / 255.0f;
#endif
#if PS_HDR == 1
#if PS_COLCLIP_HW == 1
o_col0.rgb = vec3(C.rgb / 65535.0f);
#else
o_col0.rgb = C.rgb / 255.0f;

View File

@@ -46,8 +46,8 @@ const char* shaderName(ShaderConvert value)
case ShaderConvert::DATM_0: return "ps_datm0";
case ShaderConvert::DATM_1_RTA_CORRECTION: return "ps_datm1_rta_correction";
case ShaderConvert::DATM_0_RTA_CORRECTION: return "ps_datm0_rta_correction";
case ShaderConvert::HDR_INIT: return "ps_hdr_init";
case ShaderConvert::HDR_RESOLVE: return "ps_hdr_resolve";
case ShaderConvert::COLCLIP_INIT: return "ps_colclip_init";
case ShaderConvert::COLCLIP_RESOLVE: return "ps_colclip_resolve";
case ShaderConvert::RTA_CORRECTION: return "ps_rta_correction";
case ShaderConvert::RTA_DECORRECTION: return "ps_rta_decorrection";
case ShaderConvert::TRANSPARENCY_FILTER: return "ps_filter_transparency";
@@ -103,7 +103,9 @@ const char* shaderName(PresentShader value)
enum class TextureLabel
{
ColorRT,
HDRRT,
ColorHQRT,
ColorHDRRT,
ColorClipRT,
U16RT,
U32RT,
DepthStencil,
@@ -127,8 +129,12 @@ static TextureLabel GetTextureLabel(GSTexture::Type type, GSTexture::Format form
{
case GSTexture::Format::Color:
return TextureLabel::ColorRT;
case GSTexture::Format::HDRColor:
return TextureLabel::HDRRT;
case GSTexture::Format::ColorHQ:
return TextureLabel::ColorHQRT;
case GSTexture::Format::ColorHDR:
return TextureLabel::ColorHDRRT;
case GSTexture::Format::ColorClip:
return TextureLabel::ColorClipRT;
case GSTexture::Format::UInt16:
return TextureLabel::U16RT;
case GSTexture::Format::UInt32:
@@ -149,6 +155,7 @@ static TextureLabel GetTextureLabel(GSTexture::Type type, GSTexture::Format form
case GSTexture::Format::BC2:
case GSTexture::Format::BC3:
case GSTexture::Format::BC7:
case GSTexture::Format::ColorHDR:
return TextureLabel::ReplacementTexture;
default:
return TextureLabel::Other;
@@ -163,14 +170,19 @@ static TextureLabel GetTextureLabel(GSTexture::Type type, GSTexture::Format form
}
}
// Debug names
static const char* TextureLabelString(TextureLabel label)
{
switch (label)
{
case TextureLabel::ColorRT:
return "Color RT";
case TextureLabel::HDRRT:
return "HDR RT";
case TextureLabel::ColorHQRT:
return "Color HQ RT";
case TextureLabel::ColorHDRRT:
return "Color HDR RT";
case TextureLabel::ColorClipRT:
return "Color Clip RT";
case TextureLabel::U16RT:
return "U16 RT";
case TextureLabel::U32RT:
@@ -904,6 +916,7 @@ bool GSHWDrawConfig::BlendState::IsEffective(ColorMaskSelector colormask) const
// clang-format off
// Maps PS2 blend modes to our best approximation of them with PC hardware
const std::array<HWBlend, 3*3*3*3> GSDevice::m_blendMap =
{{
{ BLEND_NO_REC , OP_ADD , CONST_ONE , CONST_ZERO} , // 0000: (Cs - Cs)*As + Cs ==> Cs

View File

@@ -22,8 +22,8 @@ enum class ShaderConvert
DATM_0,
DATM_1_RTA_CORRECTION,
DATM_0_RTA_CORRECTION,
HDR_INIT,
HDR_RESOLVE,
COLCLIP_INIT,
COLCLIP_RESOLVE,
RTA_CORRECTION,
RTA_DECORRECTION,
TRANSPARENCY_FILTER,
@@ -257,11 +257,15 @@ enum HWBlendFlags
BLEND_A_MAX = 0x8000, // Impossible blending uses coeff bigger than 1
};
// Determines the HW blend function for DX11/OGL
// Determines the HW blend function for the video backend
struct HWBlend
{
typedef u8 BlendOp; /*GSDevice::BlendOp*/
typedef u8 BlendFactor; /*GSDevice::BlendFactor*/
u16 flags;
u8 op, src, dst;
BlendOp op;
BlendFactor src, dst;
};
struct alignas(16) GSHWDrawConfig
@@ -354,12 +358,12 @@ struct alignas(16) GSHWDrawConfig
u32 blend_c : 2;
u32 blend_d : 2;
u32 fixed_one_a : 1;
u32 blend_hw : 3;
u32 blend_hw : 3; /*HWBlendType*/
u32 a_masked : 1;
u32 hdr : 1;
u32 colclip_hw : 1; // colclip (COLCLAMP off) emulation through HQ textures
u32 rta_correction : 1;
u32 rta_source_correction : 1;
u32 colclip : 1;
u32 colclip : 1; // COLCLAMP off (color blend outputs wrap around 0-255)
u32 blend_mix : 2;
u32 round_inv : 1; // Blending will invert the value, so rounding needs to go the other way
u32 pabe : 1;
@@ -631,26 +635,30 @@ struct alignas(16) GSHWDrawConfig
return true;
}
};
// For hardware rendering backends
struct BlendState
{
typedef u8 BlendOp; /*GSDevice::BlendOp*/
typedef u8 BlendFactor; /*GSDevice::BlendFactor*/
union
{
struct
{
u8 enable : 1;
u8 constant_enable : 1;
u8 op : 6;
u8 src_factor : 4;
u8 dst_factor : 4;
u8 src_factor_alpha : 4;
u8 dst_factor_alpha : 4;
bool enable : 1;
bool constant_enable : 1;
BlendOp op : 6;
BlendFactor src_factor : 4;
BlendFactor dst_factor : 4;
BlendFactor src_factor_alpha : 4;
BlendFactor dst_factor_alpha : 4;
u8 constant;
};
u32 key;
};
constexpr BlendState(): key(0) {}
constexpr BlendState(bool enable_, u8 src_factor_, u8 dst_factor_, u8 op_,
u8 src_alpha_factor_, u8 dst_alpha_factor_, bool constant_enable_, u8 constant_)
constexpr BlendState(bool enable_, BlendFactor src_factor_, BlendFactor dst_factor_, BlendOp op_,
BlendFactor src_alpha_factor_, BlendFactor dst_alpha_factor_, bool constant_enable_, u8 constant_)
: key(0)
{
enable = enable_;
@@ -675,7 +683,7 @@ struct alignas(16) GSHWDrawConfig
Full, ///< Full emulation (using barriers / ROV)
};
enum class HDRMode : u8
enum class ColClipMode : u8
{
NoModify = 0,
ConvertOnly = 1,
@@ -730,7 +738,7 @@ struct alignas(16) GSHWDrawConfig
struct BlendMultiPass
{
BlendState blend;
u8 blend_hw;
u8 blend_hw; /*HWBlendType*/
u8 dither;
bool enable;
};
@@ -742,9 +750,9 @@ struct alignas(16) GSHWDrawConfig
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;
ColClipMode colclip_mode;
GIFRegFRAME colclip_frame;
GSVector4i colclip_update_area; ///< Area in the framebuffer which colclip will modify;
};
class GSDevice : public GSAlignedClass<32>
@@ -865,7 +873,7 @@ protected:
GSTexture* m_target_tmp = nullptr;
GSTexture* m_current = nullptr;
GSTexture* m_cas = nullptr;
GSTexture* m_hdr_rt = nullptr; ///< Temp HDR texture
GSTexture* m_colclip_rt = nullptr; ///< Temp hw colclip texture
bool AcquireWindow(bool recreate_window);
@@ -890,9 +898,9 @@ public:
/// Returns a string containing current adapter in use.
const std::string& GetName() const { return m_name; }
GSTexture* GetHDRTexture() const { return m_hdr_rt; }
GSTexture* GetColorClipTexture() const { return m_colclip_rt; }
void SetHDRTexture(GSTexture* tex) { m_hdr_rt = tex; }
void SetColorClipTexture(GSTexture* tex) { m_colclip_rt = tex; }
/// Returns a string representing the specified API.
static const char* RenderAPIToString(RenderAPI api);

View File

@@ -66,7 +66,9 @@ const char* GSTexture::GetFormatName(Format format)
static constexpr const char* format_names[] = {
"Invalid",
"Color",
"HDRColor",
"ColorHQ",
"ColorHDR",
"ColorClip",
"DepthStencil",
"UNorm8",
"UInt16",
@@ -90,7 +92,9 @@ u32 GSTexture::GetCompressedBytesPerBlock(Format format)
static constexpr u32 bytes_per_block[] = {
1, // Invalid
4, // Color/RGBA8
8, // HDRColor/RGBA16
4, // ColorHQ/RGB10A2
8, // ColorHDR/RGBA16F
8, // ColorClip/RGBA16
4, // DepthStencil
1, // UNorm8/R8
2, // UInt16/R16UI
@@ -99,7 +103,7 @@ u32 GSTexture::GetCompressedBytesPerBlock(Format format)
8, // BC1 - 16 pixels in 64 bits
16, // BC2 - 16 pixels in 128 bits
16, // BC3 - 16 pixels in 128 bits
16, // BC4 - 16 pixels in 128 bits
16, // BC7 - 16 pixels in 128 bits
};
return bytes_per_block[static_cast<u32>(format)];

View File

@@ -22,15 +22,17 @@ public:
Invalid = 0,
RenderTarget = 1,
DepthStencil,
Texture,
RWTexture,
Texture, // Generic texture (usually is color textures loaded by the game)
RWTexture, // UAV
};
enum class Format : u8
{
Invalid = 0, ///< Used for initialization
Color, ///< Standard (RGBA8) color texture
HDRColor, ///< Color texture with more bits for colclip emulation (RGBA16Unorm)
Color, ///< Standard (RGBA8) color texture (used to store most of PS2's textures)
ColorHQ, ///< High quality (RGB10A2) color texture (no proper alpha)
ColorHDR, ///< High dynamic range (RGBA16F) color texture
ColorClip, ///< Color texture with more bits for colclip (wrap) emulation, given that blending requires 9bpc (RGBA16Unorm)
DepthStencil, ///< Depth stencil texture
UNorm8, ///< A8UNorm texture for paletted textures and the OSD font
UInt16, ///< UInt16 texture for reading back 16-bit depth
@@ -40,6 +42,7 @@ public:
BC2, ///< BC2, aka DXT2/3 compressed texture for replacements
BC3, ///< BC3, aka DXT4/5 compressed texture for replacements
BC7, ///< BC7, aka BPTC compressed texture for replacements
Last = BC7,
};
enum class State : u8

View File

@@ -87,6 +87,7 @@ std::vector<GSAdapterInfo> D3D::GetAdapterInfo(IDXGIFactory5* factory)
ai.max_upscale_multiplier = GSGetMaxUpscaleMultiplier(ai.max_texture_size);
wil::com_ptr_nothrow<IDXGIOutput> output;
// Only check the first output, which would be the primary display (if any is connected)
if (SUCCEEDED(hr = adapter->EnumOutputs(0, &output)))
{
UINT num_modes = 0;
@@ -111,7 +112,7 @@ std::vector<GSAdapterInfo> D3D::GetAdapterInfo(IDXGIFactory5* factory)
ERROR_LOG("GetDisplayModeList() failed: {:08X}", static_cast<unsigned>(hr));
}
}
else
else if (hr != DXGI_ERROR_NOT_FOUND)
{
ERROR_LOG("EnumOutputs() failed: {:08X}", static_cast<unsigned>(hr));
}
@@ -515,7 +516,7 @@ wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShader(D3D::ShaderType type, D3D_FEAT
}
static constexpr UINT flags_non_debug = D3DCOMPILE_OPTIMIZATION_LEVEL3;
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG | D3DCOMPILE_DEBUG_NAME_FOR_SOURCE;
wil::com_ptr_nothrow<ID3DBlob> blob;
wil::com_ptr_nothrow<ID3DBlob> error_blob;

View File

@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-3.0+
#include "GS/Renderers/DX11/D3D11ShaderCache.h"
#include "GS/Renderers/DX11/GSDevice11.h"
#include "GS/GS.h"
#include "Config.h"
@@ -300,6 +301,12 @@ wil::com_ptr_nothrow<ID3D11VertexShader> D3D11ShaderCache::GetVertexShader(ID3D1
return {};
}
const char* shader_name = entry_point; // Ideally we'd feed in a proper name
if (shader_name)
{
GSDevice11::SetD3DDebugObjectName(shader.get(), shader_name);
}
return shader;
}
@@ -320,6 +327,12 @@ bool D3D11ShaderCache::GetVertexShaderAndInputLayout(ID3D11Device* device, ID3D1
return {};
}
const char* shader_name = entry_point; // Ideally we'd feed in a proper name
if (shader_name)
{
GSDevice11::SetD3DDebugObjectName(actual_vs.get(), shader_name);
}
hr = device->CreateInputLayout(layout, layout_size, blob->GetBufferPointer(), blob->GetBufferSize(), il);
if (FAILED(hr))
{
@@ -348,6 +361,12 @@ wil::com_ptr_nothrow<ID3D11PixelShader> D3D11ShaderCache::GetPixelShader(ID3D11D
return {};
}
const char* shader_name = entry_point; // Ideally we'd feed in a proper name
if (shader_name)
{
GSDevice11::SetD3DDebugObjectName(shader.get(), shader_name);
}
return shader;
}
@@ -368,6 +387,12 @@ wil::com_ptr_nothrow<ID3D11ComputeShader> D3D11ShaderCache::GetComputeShader(ID3
return {};
}
const char* shader_name = entry_point; // Ideally we'd feed in a proper name
if (shader_name)
{
GSDevice11::SetD3DDebugObjectName(shader.get(), shader_name);
}
return shader;
}

View File

@@ -1307,7 +1307,6 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
else
{
ds = GSVector2i(m_window_info.surface_width, m_window_info.surface_height);
}
// om
@@ -1318,8 +1317,6 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
OMSetBlendState(bs, 0);
// ia
const float left = dRect.x * 2 / ds.x - 1.0f;
@@ -1336,7 +1333,6 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
};
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
IASetInputLayout(m_convert.il.get());
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
@@ -1345,7 +1341,6 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
VSSetShader(m_convert.vs.get(), nullptr);
// ps
PSSetShaderResource(0, sTex);
@@ -1382,8 +1377,6 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
OMSetDepthStencilState(m_convert.dss.get(), 0);
OMSetBlendState(m_convert.bs[D3D11_COLOR_WRITE_ENABLE_ALL].get(), 0);
// ia
const float left = dRect.x * 2 / ds.x - 1.0f;
@@ -1399,8 +1392,6 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
{GSVector4(right, bottom, 0.5f, 1.0f), GSVector2(sRect.z, sRect.w)},
};
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
IASetInputLayout(m_present.il.get());
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
@@ -1409,7 +1400,6 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
VSSetShader(m_present.vs.get(), nullptr);
// ps
PSSetShaderResource(0, sTex);
@@ -1748,7 +1738,7 @@ void GSDevice11::SetupPS(const PSSelector& sel, const GSHWDrawConfig::PSConstant
sm.AddMacro("PS_DST_FMT", sel.dst_fmt);
sm.AddMacro("PS_DEPTH_FMT", sel.depth_fmt);
sm.AddMacro("PS_PAL_FMT", sel.pal_fmt);
sm.AddMacro("PS_HDR", sel.hdr);
sm.AddMacro("PS_COLCLIP_HW", sel.colclip_hw);
sm.AddMacro("PS_RTA_CORRECTION", sel.rta_correction);
sm.AddMacro("PS_RTA_SRC_CORRECTION", sel.rta_source_correction);
sm.AddMacro("PS_COLCLIP", sel.colclip);
@@ -2182,8 +2172,6 @@ void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vert
//
DrawPrimitive();
//
}
void* GSDevice11::IAMapVertexBuffer(u32 stride, u32 count)
@@ -2521,43 +2509,43 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
GSTexture* hdr_rt = g_gs_device->GetHDRTexture();
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
if (hdr_rt)
if (colclip_rt)
{
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
{
const GSVector2i size = config.rt->GetSize();
const GSVector4 dRect(config.hdr_update_area);
const GSVector4 dRect(config.colclip_update_area);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
Recycle(colclip_rt);
g_gs_device->SetHDRTexture(nullptr);
g_gs_device->SetColorClipTexture(nullptr);
hdr_rt = nullptr;
colclip_rt = nullptr;
}
else
config.ps.hdr = 1;
config.ps.colclip_hw = 1;
}
if (config.ps.hdr)
if (config.ps.colclip_hw)
{
if (!hdr_rt)
if (!colclip_rt)
{
config.hdr_update_area = config.drawarea;
config.colclip_update_area = config.drawarea;
const GSVector4 dRect = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::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)
colclip_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip);
if (!colclip_rt)
return;
g_gs_device->SetHDRTexture(hdr_rt);
g_gs_device->SetColorClipTexture(colclip_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);
StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
}
@@ -2569,7 +2557,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
if (!primid_tex)
return;
StretchRect(hdr_rt ? hdr_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
StretchRect(colclip_rt ? colclip_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)
@@ -2585,7 +2573,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
};
SetupDATE(hdr_rt ? hdr_rt : config.rt, config.ds, vertices, config.datm);
SetupDATE(colclip_rt ? colclip_rt : config.rt, config.ds, vertices, config.datm);
}
if (config.vs.expand != GSHWDrawConfig::VSExpand::None)
@@ -2649,7 +2637,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(hdr_rt ? hdr_rt : config.rt, &rt_copy, config.drawarea);
CloneTexture(colclip_rt ? colclip_rt : config.rt, &rt_copy, config.drawarea);
if (rt_copy)
{
if (config.require_one_barrier)
@@ -2679,7 +2667,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
}
SetupOM(config.depth, OMBlendSelector(config.colormask, config.blend), config.blend.constant);
OMSetRenderTargets(hdr_rt ? hdr_rt : config.rt, config.ds, &config.scissor);
OMSetRenderTargets(colclip_rt ? colclip_rt : config.rt, config.ds, &config.scissor);
DrawIndexedPrimitive();
if (config.blend_multi_pass.enable)
@@ -2714,20 +2702,20 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
if (primid_tex)
Recycle(primid_tex);
if (hdr_rt)
if (colclip_rt)
{
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
if (config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve)
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve)
{
const GSVector2i size = config.rt->GetSize();
const GSVector4 dRect(config.hdr_update_area);
const GSVector4 dRect(config.colclip_update_area);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
Recycle(colclip_rt);
g_gs_device->SetHDRTexture(nullptr);
g_gs_device->SetColorClipTexture(nullptr);
}
}
}

View File

@@ -29,7 +29,9 @@ DXGI_FORMAT GSTexture11::GetDXGIFormat(Format format)
switch (format)
{
case GSTexture::Format::Color: return DXGI_FORMAT_R8G8B8A8_UNORM;
case GSTexture::Format::HDRColor: return DXGI_FORMAT_R16G16B16A16_UNORM;
case GSTexture::Format::ColorHQ: return DXGI_FORMAT_R10G10B10A2_UNORM;
case GSTexture::Format::ColorHDR: return DXGI_FORMAT_R16G16B16A16_FLOAT;
case GSTexture::Format::ColorClip: return DXGI_FORMAT_R16G16B16A16_UNORM;
case GSTexture::Format::DepthStencil: return DXGI_FORMAT_R32G8X24_TYPELESS;
case GSTexture::Format::UNorm8: return DXGI_FORMAT_A8_UNORM;
case GSTexture::Format::UInt16: return DXGI_FORMAT_R16_UINT;

View File

@@ -739,7 +739,9 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
return false;
}
CompileCASPipelines();
if (!CompileCASPipelines())
return false;
if (!CompileImGuiPipeline())
return false;
@@ -1265,13 +1267,17 @@ void GSDevice12::DrawIndexedPrimitive(int offset, int count)
void GSDevice12::LookupNativeFormat(GSTexture::Format format, DXGI_FORMAT* d3d_format, DXGI_FORMAT* srv_format,
DXGI_FORMAT* rtv_format, DXGI_FORMAT* dsv_format) const
{
static constexpr std::array<std::array<DXGI_FORMAT, 4>, static_cast<int>(GSTexture::Format::BC7) + 1>
static constexpr std::array<std::array<DXGI_FORMAT, 4>, static_cast<int>(GSTexture::Format::Last) + 1>
s_format_mapping = {{
{DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN}, // Invalid
{DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_UNKNOWN}, // Color
{DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM,
DXGI_FORMAT_UNKNOWN}, // ColorHQ
{DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_UNKNOWN}, // ColorHDR
{DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM,
DXGI_FORMAT_UNKNOWN}, // HDRColor
DXGI_FORMAT_UNKNOWN}, // ColorClip
{DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT}, // DepthStencil
{DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN}, // UNorm8
@@ -1424,9 +1430,10 @@ void GSDevice12::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
GL_PUSH("ColorCopy Red:%d Green:%d Blue:%d Alpha:%d", red, green, blue, alpha);
const u32 index = (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
int rta_offset = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
const bool allow_discard = (index == 0xf);
DoStretchRect(static_cast<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(dTex), dRect,
m_color_copy[index].get(), false, allow_discard);
m_color_copy[index + rta_offset].get(), false, allow_discard);
}
void GSDevice12::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
@@ -2520,13 +2527,6 @@ bool GSDevice12::CompileConvertPipelines()
// compile color copy pipelines
gpb.SetRenderTarget(0, DXGI_FORMAT_R8G8B8A8_UNORM);
gpb.SetDepthStencilFormat(DXGI_FORMAT_UNKNOWN);
ComPtr<ID3DBlob> ps(GetUtilityPixelShader(*shader, shaderName(i)));
if (!ps)
return false;
gpb.SetPixelShader(ps.get());
for (u32 j = 16; j < 32; j++)
{
pxAssert(!m_color_copy[j]);
@@ -2540,10 +2540,10 @@ bool GSDevice12::CompileConvertPipelines()
j & 1u, (j >> 1) & 1u, (j >> 2) & 1u, (j >> 3) & 1u));
}
}
else if (i == ShaderConvert::HDR_INIT || i == ShaderConvert::HDR_RESOLVE)
else if (i == ShaderConvert::COLCLIP_INIT || i == ShaderConvert::COLCLIP_RESOLVE)
{
const bool is_setup = i == ShaderConvert::HDR_INIT;
std::array<ComPtr<ID3D12PipelineState>, 2>& arr = is_setup ? m_hdr_setup_pipelines : m_hdr_finish_pipelines;
const bool is_setup = i == ShaderConvert::COLCLIP_INIT;
std::array<ComPtr<ID3D12PipelineState>, 2>& arr = is_setup ? m_colclip_setup_pipelines : m_colclip_finish_pipelines;
for (u32 ds = 0; ds < 2; ds++)
{
pxAssert(!arr[ds]);
@@ -2554,7 +2554,7 @@ bool GSDevice12::CompileConvertPipelines()
if (!arr[ds])
return false;
D3D12::SetObjectName(arr[ds].get(), TinyString::from_format("HDR {}/copy pipeline (ds={})", is_setup ? "setup" : "finish", ds));
D3D12::SetObjectName(arr[ds].get(), TinyString::from_format("ColorClip {}/copy pipeline (ds={})", is_setup ? "setup" : "finish", ds));
}
}
}
@@ -2598,8 +2598,8 @@ bool GSDevice12::CompilePresentPipelines()
return false;
}
ComPtr<ID3DBlob> m_convert_vs = GetUtilityVertexShader(*shader, "vs_main");
if (!m_convert_vs)
ComPtr<ID3DBlob> vs = GetUtilityVertexShader(*shader, "vs_main");
if (!vs)
return false;
D3D12::GraphicsPipelineBuilder gpb;
@@ -2607,7 +2607,7 @@ bool GSDevice12::CompilePresentPipelines()
AddUtilityVertexAttributes(gpb);
gpb.SetNoCullRasterizationState();
gpb.SetNoBlendingState();
gpb.SetVertexShader(m_convert_vs.get());
gpb.SetVertexShader(vs.get());
gpb.SetDepthState(false, false, D3D12_COMPARISON_FUNC_ALWAYS);
gpb.SetNoStencilState();
gpb.SetRenderTarget(0, DXGI_FORMAT_R8G8B8A8_UNORM);
@@ -2663,7 +2663,7 @@ bool GSDevice12::CompileInterlacePipelines()
if (!m_interlace[i])
return false;
D3D12::SetObjectName(m_convert[i].get(), TinyString::from_format("Interlace pipeline {}", static_cast<int>(i)));
D3D12::SetObjectName(m_interlace[i].get(), TinyString::from_format("Interlace pipeline {}", static_cast<int>(i)));
}
return true;
@@ -2700,7 +2700,7 @@ bool GSDevice12::CompileMergePipelines()
if (!m_merge[i])
return false;
D3D12::SetObjectName(m_convert[i].get(), TinyString::from_format("Merge pipeline {}", i));
D3D12::SetObjectName(m_merge[i].get(), TinyString::from_format("Merge pipeline {}", i));
}
return true;
@@ -2780,8 +2780,8 @@ void GSDevice12::DestroyResources()
m_color_copy = {};
m_present = {};
m_convert = {};
m_hdr_setup_pipelines = {};
m_hdr_finish_pipelines = {};
m_colclip_setup_pipelines = {};
m_colclip_finish_pipelines = {};
m_date_image_setup_pipelines = {};
m_fxaa_pipeline.reset();
m_shadeboost_pipeline.reset();
@@ -2897,7 +2897,7 @@ const ID3DBlob* GSDevice12::GetTFXPixelShader(const GSHWDrawConfig::PSSelector&
sm.AddMacro("PS_DST_FMT", sel.dst_fmt);
sm.AddMacro("PS_DEPTH_FMT", sel.depth_fmt);
sm.AddMacro("PS_PAL_FMT", sel.pal_fmt);
sm.AddMacro("PS_HDR", sel.hdr);
sm.AddMacro("PS_COLCLIP_HW", sel.colclip_hw);
sm.AddMacro("PS_RTA_CORRECTION", sel.rta_correction);
sm.AddMacro("PS_RTA_SRC_CORRECTION", sel.rta_source_correction);
sm.AddMacro("PS_COLCLIP", sel.colclip);
@@ -2955,7 +2955,7 @@ GSDevice12::ComPtr<ID3D12PipelineState> GSDevice12::CreateTFXPipeline(const Pipe
{
const GSTexture::Format format = IsDATEModePrimIDInit(p.ps.date) ?
GSTexture::Format::PrimID :
(p.ps.hdr ? GSTexture::Format::HDRColor : GSTexture::Format::Color);
(p.ps.colclip_hw ? GSTexture::Format::ColorClip : GSTexture::Format::Color);
DXGI_FORMAT native_format;
LookupNativeFormat(format, nullptr, nullptr, &native_format, nullptr);
@@ -3817,7 +3817,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
const bool stencil_DATE = (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne);
GSTexture12* hdr_rt = static_cast<GSTexture12*>(g_gs_device->GetHDRTexture());
GSTexture12* colclip_rt = static_cast<GSTexture12*>(g_gs_device->GetColorClipTexture());
GSTexture12* draw_rt = static_cast<GSTexture12*>(config.rt);
GSTexture12* draw_ds = static_cast<GSTexture12*>(config.ds);
GSTexture12* draw_rt_clone = nullptr;
@@ -3830,15 +3830,15 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
// figure out the pipeline
UpdateHWPipelineSelector(config);
// now blit the hdr texture back to the original target
if (hdr_rt)
// now blit the colclip texture back to the original target
if (colclip_rt)
{
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
{
GL_PUSH("Blit HDR back to RT");
GL_PUSH("Blit ColorClip back to RT");
EndRenderPass();
hdr_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
colclip_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
draw_rt = static_cast<GSTexture12*>(config.rt);
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
@@ -3850,19 +3850,19 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
draw_rt->GetUNormClearColor(), 0.0f, 0);
const GSVector4 sRect(GSVector4(config.hdr_update_area) / GSVector4(rtsize.x, rtsize.y).xyxy());
SetPipeline(m_hdr_finish_pipelines[pipe.ds].get());
SetUtilityTexture(hdr_rt, m_point_sampler_cpu);
DrawStretchRect(sRect, GSVector4(config.hdr_update_area), rtsize);
const GSVector4 sRect(GSVector4(config.colclip_update_area) / GSVector4(rtsize.x, rtsize.y).xyxy());
SetPipeline(m_colclip_finish_pipelines[pipe.ds].get());
SetUtilityTexture(colclip_rt, m_point_sampler_cpu);
DrawStretchRect(sRect, GSVector4(config.colclip_update_area), rtsize);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
g_gs_device->SetHDRTexture(nullptr);
Recycle(colclip_rt);
g_gs_device->SetColorClipTexture(nullptr);
}
else
{
draw_rt = hdr_rt;
pipe.ps.hdr = 1;
draw_rt = colclip_rt;
pipe.ps.colclip_hw = 1;
}
}
@@ -3903,7 +3903,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
if (config.require_one_barrier)
{
// requires a copy of the RT
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, hdr_rt ? GSTexture::Format::HDRColor : GSTexture::Format::Color, true));
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true));
if (draw_rt_clone)
{
EndRenderPass();
@@ -3917,19 +3917,19 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
}
}
// Switch to hdr target for colclip rendering
if (pipe.ps.hdr)
// Switch to colclip target for colclip hw rendering
if (pipe.ps.colclip_hw)
{
if (!hdr_rt)
if (!colclip_rt)
{
config.hdr_update_area = config.drawarea;
config.colclip_update_area = config.drawarea;
EndRenderPass();
hdr_rt = static_cast<GSTexture12*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor, false));
if (!hdr_rt)
colclip_rt = static_cast<GSTexture12*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false));
if (!colclip_rt)
{
Console.WriteLn("D3D12: Failed to allocate HDR render target, aborting draw.");
Console.WriteLn("D3D12: Failed to allocate ColorClip render target, aborting draw.");
if (date_image)
Recycle(date_image);
@@ -3937,17 +3937,17 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
return;
}
g_gs_device->SetHDRTexture(static_cast<GSTexture*>(hdr_rt));
g_gs_device->SetColorClipTexture(static_cast<GSTexture*>(colclip_rt));
// propagate clear value through if the hdr render is the first
// propagate clear value through if the colclip render is the first
if (draw_rt->GetState() == GSTexture::State::Cleared)
{
hdr_rt->SetState(GSTexture::State::Cleared);
hdr_rt->SetClearColor(draw_rt->GetClearColor());
colclip_rt->SetState(GSTexture::State::Cleared);
colclip_rt->SetClearColor(draw_rt->GetClearColor());
}
else if (draw_rt->GetState() == GSTexture::State::Dirty)
{
GL_PUSH_("HDR Render Target Setup");
GL_PUSH_("ColorClip Render Target Setup");
draw_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
}
@@ -3956,7 +3956,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
PSSetShaderResource(2, draw_rt, true);
}
draw_rt = hdr_rt;
draw_rt = colclip_rt;
}
// clear texture binding when it's bound to RT or DS
@@ -3966,11 +3966,10 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
PSSetShaderResource(0, nullptr, false);
}
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
if (m_in_render_pass && (m_current_render_target == draw_rt || m_current_depth_target == draw_ds))
{
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
// keep the depth even if doing HDR draws, because the next draw will probably re-enable depth
// keep the depth even if doing colclip hw draws, because the next draw will probably re-enable depth
if (!draw_rt && m_current_render_target && config.tex != m_current_render_target &&
m_current_render_target->GetSize() == draw_ds->GetSize())
{
@@ -3991,9 +3990,9 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
if (!m_in_render_pass)
{
GSVector4 clear_color = draw_rt ? draw_rt->GetUNormClearColor() : GSVector4::zero();
if (pipe.ps.hdr)
if (pipe.ps.colclip_hw)
{
// Denormalize clear color for HDR.
// Denormalize clear color for hw colclip.
clear_color *= GSVector4::cxpr(255.0f / 65535.0f, 255.0f / 65535.0f, 255.0f / 65535.0f, 1.0f);
}
BeginRenderPass(GetLoadOpForTexture(draw_rt),
@@ -4007,13 +4006,13 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
clear_color, draw_ds ? draw_ds->GetClearDepth() : 0.0f, 1);
}
// rt -> hdr blit if enabled
if (hdr_rt && (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
// rt -> colclip hw blit if enabled
if (colclip_rt && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
{
SetUtilityTexture(static_cast<GSTexture12*>(config.rt), m_point_sampler_cpu);
SetPipeline(m_hdr_setup_pipelines[pipe.ds].get());
SetPipeline(m_colclip_setup_pipelines[pipe.ds].get());
const GSVector4 drawareaf = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 drawareaf = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 sRect(drawareaf / GSVector4(rtsize.x, rtsize.y).xyxy());
DrawStretchRect(sRect, GSVector4(drawareaf), rtsize);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
@@ -4021,9 +4020,9 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
GL_POP();
}
// VB/IB upload, if we did DATE setup and it's not HDR this has already been done
// VB/IB upload, if we did DATE setup and it's not colclip hw this has already been done
SetPrimitiveTopology(s_primitive_topology_mapping[static_cast<u8>(config.topology)]);
if (!date_image || hdr_rt)
if (!date_image || colclip_rt)
UploadHWDrawVerticesAndIndices(config);
// now we can do the actual draw
@@ -4067,17 +4066,17 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
if (date_image)
Recycle(date_image);
// now blit the hdr texture back to the original target
if (hdr_rt)
// now blit the colclip texture back to the original target
if (colclip_rt)
{
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
if ((config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve))
if ((config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve))
{
GL_PUSH("Blit HDR back to RT");
GL_PUSH("Blit ColorClip back to RT");
EndRenderPass();
hdr_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
colclip_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
draw_rt = static_cast<GSTexture12*>(config.rt);
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
@@ -4089,14 +4088,14 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
draw_rt->GetUNormClearColor(), 0.0f, 0);
const GSVector4 sRect(GSVector4(config.hdr_update_area) / GSVector4(rtsize.x, rtsize.y).xyxy());
SetPipeline(m_hdr_finish_pipelines[pipe.ds].get());
SetUtilityTexture(hdr_rt, m_point_sampler_cpu);
DrawStretchRect(sRect, GSVector4(config.hdr_update_area), rtsize);
const GSVector4 sRect(GSVector4(config.colclip_update_area) / GSVector4(rtsize.x, rtsize.y).xyxy());
SetPipeline(m_colclip_finish_pipelines[pipe.ds].get());
SetUtilityTexture(colclip_rt, m_point_sampler_cpu);
DrawStretchRect(sRect, GSVector4(config.colclip_update_area), rtsize);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
g_gs_device->SetHDRTexture(nullptr);
Recycle(colclip_rt);
g_gs_device->SetColorClipTexture(nullptr);
}
}
}

View File

@@ -315,8 +315,8 @@ private:
std::array<ComPtr<ID3D12PipelineState>, 32> m_color_copy{};
std::array<ComPtr<ID3D12PipelineState>, 2> m_merge{};
std::array<ComPtr<ID3D12PipelineState>, NUM_INTERLACE_SHADERS> m_interlace{};
std::array<ComPtr<ID3D12PipelineState>, 2> m_hdr_setup_pipelines{}; // [depth]
std::array<ComPtr<ID3D12PipelineState>, 2> m_hdr_finish_pipelines{}; // [depth]
std::array<ComPtr<ID3D12PipelineState>, 2> m_colclip_setup_pipelines{}; // [depth]
std::array<ComPtr<ID3D12PipelineState>, 2> m_colclip_finish_pipelines{}; // [depth]
std::array<std::array<ComPtr<ID3D12PipelineState>, 4>, 2> m_date_image_setup_pipelines{}; // [depth][datm]
ComPtr<ID3D12PipelineState> m_fxaa_pipeline;
ComPtr<ID3D12PipelineState> m_shadeboost_pipeline;

View File

@@ -1135,7 +1135,7 @@ GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex, const
return g_texture_cache->GetTargetSize(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, valid_size.x, valid_size.y, can_expand);
}
bool GSRendererHW::NextDrawHDR() const
bool GSRendererHW::NextDrawColClip() const
{
const int get_next_ctx = (m_state_flush_reason == CONTEXTCHANGE) ? m_env.PRIM.CTXT : m_backed_up_ctx;
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
@@ -2438,31 +2438,31 @@ void GSRendererHW::Draw()
// I hate that I have to do this, but some games (like Pac-Man World Rally) troll us by causing a flush with degenerate triangles, so we don't have all available information about the next draw.
// So we have to check when the next draw happens if our frame has changed or if it's become recursive.
const bool has_HDR_texture = g_gs_device->GetHDRTexture() != nullptr;
if (!no_rt && has_HDR_texture && (m_conf.hdr_frame.FBP != m_cached_ctx.FRAME.FBP || m_conf.hdr_frame.Block() == m_cached_ctx.TEX0.TBP0))
const bool has_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
if (!no_rt && has_colclip_texture && (m_conf.colclip_frame.FBP != m_cached_ctx.FRAME.FBP || m_conf.colclip_frame.Block() == m_cached_ctx.TEX0.TBP0))
{
GIFRegTEX0 FRAME;
FRAME.TBP0 = m_conf.hdr_frame.Block();
FRAME.TBW = m_conf.hdr_frame.FBW;
FRAME.PSM = m_conf.hdr_frame.PSM;
FRAME.TBP0 = m_conf.colclip_frame.Block();
FRAME.TBW = m_conf.colclip_frame.FBW;
FRAME.PSM = m_conf.colclip_frame.PSM;
GSTextureCache::Target* old_rt = g_texture_cache->LookupTarget(FRAME, GSVector2i(1, 1), GetTextureScaleFactor(), GSTextureCache::RenderTarget, true,
fm, false, false, true, true, GSVector4i(0, 0, 1, 1), true, false, false);
if (old_rt)
{
GL_CACHE("Pre-draw resolve of HDR! Address: %x", FRAME.TBP0);
GSTexture* hdr_texture = g_gs_device->GetHDRTexture();
g_gs_device->StretchRect(hdr_texture, GSVector4(m_conf.hdr_update_area) / GSVector4(GSVector4i(hdr_texture->GetSize()).xyxy()), old_rt->m_texture, GSVector4(m_conf.hdr_update_area),
ShaderConvert::HDR_RESOLVE, false);
GL_CACHE("Pre-draw resolve of colclip! Address: %x", FRAME.TBP0);
GSTexture* colclip_texture = g_gs_device->GetColorClipTexture();
g_gs_device->StretchRect(colclip_texture, GSVector4(m_conf.colclip_update_area) / GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()), old_rt->m_texture, GSVector4(m_conf.colclip_update_area),
ShaderConvert::COLCLIP_RESOLVE, false);
g_gs_device->Recycle(hdr_texture);
g_gs_device->Recycle(colclip_texture);
g_gs_device->SetHDRTexture(nullptr);
g_gs_device->SetColorClipTexture(nullptr);
}
else
DevCon.Warning("Error resolving HDR texture for pre-draw resolve");
DevCon.Warning("Error resolving colclip texture for pre-draw resolve");
}
const bool draw_sprite_tex = PRIM->TME && (m_vt.m_primclass == GS_SPRITE_CLASS);
@@ -4267,12 +4267,12 @@ void GSRendererHW::Draw()
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
const bool writeback_HDR_texture = g_gs_device->GetHDRTexture() != nullptr;
if (writeback_HDR_texture)
const bool writeback_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
if (writeback_colclip_texture)
{
GSTexture* hdr_texture = g_gs_device->GetHDRTexture();
g_gs_device->StretchRect(hdr_texture, GSVector4(m_conf.hdr_update_area) / GSVector4(GSVector4i(hdr_texture->GetSize()).xyxy()), rt->m_texture, GSVector4(m_conf.hdr_update_area),
ShaderConvert::HDR_RESOLVE, false);
GSTexture* colclip_texture = g_gs_device->GetColorClipTexture();
g_gs_device->StretchRect(colclip_texture, GSVector4(m_conf.colclip_update_area) / GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()), rt->m_texture, GSVector4(m_conf.colclip_update_area),
ShaderConvert::COLCLIP_RESOLVE, false);
}
const u64 frame = g_perfmon.GetFrame();
@@ -5228,10 +5228,10 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
// Per pixel alpha blending.
const bool PABE = m_draw_env->PABE.PABE && GetAlphaMinMax().min < 128;
// HW blend can handle it, no need for sw or hdr colclip, Cd*Alpha or Cd*(1 - Alpha) where Alpha <= 128.
// HW blend can handle it, no need for sw or hw colclip, Cd*Alpha or Cd*(1 - Alpha) where Alpha <= 128.
bool color_dest_blend2 = !PABE && ((m_conf.ps.blend_a == 1 && m_conf.ps.blend_b == 2 && m_conf.ps.blend_d == 2) || (m_conf.ps.blend_a == 2 && m_conf.ps.blend_b == 1 && m_conf.ps.blend_d == 1)) &&
(alpha_eq_less_one || (alpha_c1_eq_less_max_one && new_rt_alpha_scale));
// HW blend can handle it, no need for sw or hdr colclip, Cs*Alpha + Cd*(1 - Alpha) or Cd*Alpha + Cs*(1 - Alpha) where Alpha <= 128.
// HW blend can handle it, no need for sw or hw colclip, Cs*Alpha + Cd*(1 - Alpha) or Cd*Alpha + Cs*(1 - Alpha) where Alpha <= 128.
bool blend_zero_to_one_range = !PABE && ((m_conf.ps.blend_a == 0 && m_conf.ps.blend_b == 1 && m_conf.ps.blend_d == 1) || (blend_flag & BLEND_MIX3)) &&
(alpha_eq_less_one || (alpha_c1_eq_less_max_one && new_rt_alpha_scale));
@@ -5382,36 +5382,35 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
// Color clip
if (COLCLAMP.CLAMP == 0)
{
bool has_HDR_texture = g_gs_device->GetHDRTexture() != nullptr;
bool has_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
// Don't know any game that resizes the RT mid HDR, but gotta be careful.
if (has_HDR_texture)
// Don't know any game that resizes the RT mid colclip, but gotta be careful.
if (has_colclip_texture)
{
GSTexture* hdr_texture = g_gs_device->GetHDRTexture();
GSTexture* colclip_texture = g_gs_device->GetColorClipTexture();
if (hdr_texture->GetSize() != rt->m_texture->GetSize())
if (colclip_texture->GetSize() != rt->m_texture->GetSize())
{
GL_CACHE("Pre-Blend resolve of colclip due to size change! Address: %x", rt->m_TEX0.TBP0);
g_gs_device->StretchRect(colclip_texture, GSVector4(m_conf.colclip_update_area) / GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()), rt->m_texture, GSVector4(m_conf.colclip_update_area),
ShaderConvert::COLCLIP_RESOLVE, false);
GL_CACHE("Pre-Blend resolve of HDR due to size change! Address: %x", rt->m_TEX0.TBP0);
g_gs_device->StretchRect(hdr_texture, GSVector4(m_conf.hdr_update_area) / GSVector4(GSVector4i(hdr_texture->GetSize()).xyxy()), rt->m_texture, GSVector4(m_conf.hdr_update_area),
ShaderConvert::HDR_RESOLVE, false);
g_gs_device->Recycle(colclip_texture);
g_gs_device->Recycle(hdr_texture);
g_gs_device->SetColorClipTexture(nullptr);
g_gs_device->SetHDRTexture(nullptr);
has_HDR_texture = false;
has_colclip_texture = false;
}
}
const bool free_colclip = !has_HDR_texture && (features.framebuffer_fetch || no_prim_overlap || blend_non_recursive);
const bool free_colclip = !has_colclip_texture && (features.framebuffer_fetch || no_prim_overlap || blend_non_recursive);
GL_DBG("COLCLIP Info (Blending: %u/%u/%u/%u, OVERLAP: %d)", m_conf.ps.blend_a, m_conf.ps.blend_b, m_conf.ps.blend_c, m_conf.ps.blend_d, m_prim_overlap);
if (color_dest_blend || color_dest_blend2 || blend_zero_to_one_range)
{
// No overflow, disable colclip.
GL_INS("COLCLIP mode DISABLED");
sw_blending = false;
m_conf.hdr_mode = (has_HDR_texture && !NextDrawHDR()) ? GSHWDrawConfig::HDRMode::ResolveOnly : GSHWDrawConfig::HDRMode::NoModify;
m_conf.colclip_mode = (has_colclip_texture && !NextDrawColClip()) ? GSHWDrawConfig::ColClipMode::ResolveOnly : GSHWDrawConfig::ColClipMode::NoModify;
}
else if (free_colclip)
{
@@ -5419,35 +5418,35 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
GL_INS("COLCLIP Free mode ENABLED");
m_conf.ps.colclip = 1;
sw_blending = true;
// Disable the HDR algo
// Disable the colclip hw algo
accumulation_blend = false;
blend_mix = false;
m_conf.hdr_mode = (has_HDR_texture && !NextDrawHDR()) ? GSHWDrawConfig::HDRMode::ResolveOnly : GSHWDrawConfig::HDRMode::NoModify;
m_conf.colclip_mode = (has_colclip_texture && !NextDrawColClip()) ? GSHWDrawConfig::ColClipMode::ResolveOnly : GSHWDrawConfig::ColClipMode::NoModify;
}
else if (accumulation_blend)
{
// A fast algo that requires 2 passes
GL_INS("COLCLIP Fast HDR mode ENABLED");
m_conf.ps.hdr = 1;
sw_blending = true; // Enable sw blending for the HDR algo
GL_INS("COLCLIP Fast HW mode ENABLED");
m_conf.ps.colclip_hw = 1;
sw_blending = true; // Enable sw blending for the colclip algo
m_conf.hdr_mode = has_HDR_texture ? (NextDrawHDR() ? GSHWDrawConfig::HDRMode::NoModify : GSHWDrawConfig::HDRMode::ResolveOnly) : (NextDrawHDR() ? GSHWDrawConfig::HDRMode::ConvertOnly : GSHWDrawConfig::HDRMode::ConvertAndResolve);
m_conf.colclip_mode = has_colclip_texture ? (NextDrawColClip() ? GSHWDrawConfig::ColClipMode::NoModify : GSHWDrawConfig::ColClipMode::ResolveOnly) : (NextDrawColClip() ? GSHWDrawConfig::ColClipMode::ConvertOnly : GSHWDrawConfig::ColClipMode::ConvertAndResolve);
}
else if (sw_blending)
{
// A slow algo that could requires several passes (barely used)
GL_INS("COLCLIP SW mode ENABLED");
m_conf.ps.colclip = 1;
m_conf.hdr_mode = (has_HDR_texture && !NextDrawHDR()) ? GSHWDrawConfig::HDRMode::ResolveOnly : GSHWDrawConfig::HDRMode::NoModify;
m_conf.colclip_mode = (has_colclip_texture && !NextDrawColClip()) ? GSHWDrawConfig::ColClipMode::ResolveOnly : GSHWDrawConfig::ColClipMode::NoModify;
}
else
{
GL_INS("COLCLIP HDR mode ENABLED");
m_conf.ps.hdr = 1;
m_conf.hdr_mode = has_HDR_texture ? (NextDrawHDR() ? GSHWDrawConfig::HDRMode::NoModify : GSHWDrawConfig::HDRMode::ResolveOnly) : (NextDrawHDR() ? GSHWDrawConfig::HDRMode::ConvertOnly : GSHWDrawConfig::HDRMode::ConvertAndResolve);
GL_INS("COLCLIP HW mode ENABLED");
m_conf.ps.colclip_hw = 1;
m_conf.colclip_mode = has_colclip_texture ? (NextDrawColClip() ? GSHWDrawConfig::ColClipMode::NoModify : GSHWDrawConfig::ColClipMode::ResolveOnly) : (NextDrawColClip() ? GSHWDrawConfig::ColClipMode::ConvertOnly : GSHWDrawConfig::ColClipMode::ConvertAndResolve);
}
m_conf.hdr_frame = m_cached_ctx.FRAME;
m_conf.colclip_frame = m_cached_ctx.FRAME;
}
// Per pixel alpha blending
@@ -5478,13 +5477,13 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
blend_mix = false;
m_conf.ps.pabe = 1;
// HDR mode should be disabled when doing sw blend, swap with sw colclip.
if (m_conf.ps.hdr)
// hw colclip mode should be disabled when doing sw blend, swap with sw colclip.
if (m_conf.ps.colclip_hw)
{
const bool has_HDR_texture = g_gs_device->GetHDRTexture() != nullptr;
m_conf.ps.hdr = 0;
const bool has_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
m_conf.ps.colclip_hw = 0;
m_conf.ps.colclip = 1;
m_conf.hdr_mode = has_HDR_texture ? GSHWDrawConfig::HDRMode::EarlyResolve : GSHWDrawConfig::HDRMode::NoModify;
m_conf.colclip_mode = has_colclip_texture ? GSHWDrawConfig::ColClipMode::EarlyResolve : GSHWDrawConfig::ColClipMode::NoModify;
}
}
else
@@ -5552,9 +5551,9 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
if (blend.op == GSDevice::OP_REV_SUBTRACT)
{
pxAssert(m_conf.ps.blend_a == 2);
if (m_conf.ps.hdr)
if (m_conf.ps.colclip_hw)
{
// HDR uses unorm, which is always positive
// HW colclip uses unorm, which is always positive
// Have the shader do the inversion, then clip to remove the negative
m_conf.blend.op = GSDevice::OP_ADD;
}
@@ -7405,7 +7404,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
m_conf.require_full_barrier = false;
}
// Multi-pass algorithms shouldn't be needed with full barrier and backends may not handle this correctly
pxAssert(!m_conf.require_full_barrier || !m_conf.ps.hdr);
pxAssert(!m_conf.require_full_barrier || !m_conf.ps.colclip_hw);
// Swap full barrier for one barrier when there's no overlap, or a texture shuffle.
if (m_conf.require_full_barrier && (m_prim_overlap == PRIM_OVERLAP_NO || m_conf.ps.shuffle))

View File

@@ -111,7 +111,7 @@ private:
void EmulateATST(float& AREF, GSHWDrawConfig::PSSelector& ps, bool pass_2);
void SetTCOffset();
bool NextDrawHDR() const;
bool NextDrawColClip() const;
bool IsPossibleChannelShuffle() const;
bool IsPageCopy() const;
bool NextDrawMatchesShuffle() const;

View File

@@ -465,7 +465,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
}
const GSDevice::FeatureSupport features(g_gs_device->Features());
if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1') || dxt10_format == 71)
if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1') || dxt10_format == 71 /*DXGI_FORMAT_BC1_UNORM*/)
{
info->format = GSTexture::Format::BC1;
info->block_size = 4;
@@ -473,7 +473,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
if (!features.dxt_textures)
return false;
}
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '2') || header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3') || dxt10_format == 74)
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '2') || header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3') || dxt10_format == 74 /*DXGI_FORMAT_BC2_UNORM*/)
{
info->format = GSTexture::Format::BC2;
info->block_size = 4;
@@ -481,7 +481,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
if (!features.dxt_textures)
return false;
}
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '4') || header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5') || dxt10_format == 77)
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '4') || header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5') || dxt10_format == 77 /*DXGI_FORMAT_BC3_UNORM*/)
{
info->format = GSTexture::Format::BC3;
info->block_size = 4;
@@ -489,7 +489,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
if (!features.dxt_textures)
return false;
}
else if (dxt10_format == 98)
else if (dxt10_format == 98 /*DXGI_FORMAT_BC7_UNORM*/)
{
info->format = GSTexture::Format::BC7;
info->block_size = 4;

View File

@@ -256,11 +256,9 @@ public:
MRCOwned<id<MTLRenderPipelineState>> m_clut_pipeline[2];
MRCOwned<id<MTLRenderPipelineState>> m_stencil_clear_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_primid_init_pipeline[2][4];
MRCOwned<id<MTLRenderPipelineState>> m_hdr_init_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_hdr_rta_init_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_hdr_clear_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_hdr_resolve_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_hdr_rta_resolve_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_colclip_init_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_colclip_clear_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_colclip_resolve_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_fxaa_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_shadeboost_pipeline;
MRCOwned<id<MTLRenderPipelineState>> m_imgui_pipeline;

View File

@@ -510,7 +510,9 @@ static constexpr MTLPixelFormat ConvertPixelFormat(GSTexture::Format format)
case GSTexture::Format::UInt16: return MTLPixelFormatR16Uint;
case GSTexture::Format::UNorm8: return MTLPixelFormatA8Unorm;
case GSTexture::Format::Color: return MTLPixelFormatRGBA8Unorm;
case GSTexture::Format::HDRColor: return MTLPixelFormatRGBA16Unorm;
case GSTexture::Format::ColorHQ: return MTLPixelFormatRGB10A2Unorm;
case GSTexture::Format::ColorHDR: return MTLPixelFormatRGBA16Float;
case GSTexture::Format::ColorClip: return MTLPixelFormatRGBA16Unorm;
case GSTexture::Format::DepthStencil: return MTLPixelFormatDepth32Float_Stencil8;
case GSTexture::Format::Invalid: return MTLPixelFormatInvalid;
case GSTexture::Format::BC1: return MTLPixelFormatBC1_RGBA;
@@ -1065,14 +1067,14 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
auto pdesc = [[MTLRenderPipelineDescriptor new] autorelease];
// FS Triangle Pipelines
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::Color);
m_hdr_resolve_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_hdr_resolve"), @"HDR Resolve");
m_colclip_resolve_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_colclip_resolve"), @"ColorClip Resolve");
m_fxaa_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_fxaa"), @"fxaa");
m_shadeboost_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_shadeboost"), @"shadeboost");
m_clut_pipeline[0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_convert_clut_4"), @"4-bit CLUT Update");
m_clut_pipeline[1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_convert_clut_8"), @"8-bit CLUT Update");
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::HDRColor);
m_hdr_init_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_hdr_init"), @"HDR Init");
m_hdr_clear_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_clear"), @"HDR Clear");
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::ColorClip);
m_colclip_init_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_colclip_init"), @"ColorClip Init");
m_colclip_clear_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_clear"), @"ColorClip Clear");
pdesc.colorAttachments[0].pixelFormat = MTLPixelFormatInvalid;
pdesc.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
m_datm_pipeline[0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_datm0"), @"datm0");
@@ -1116,8 +1118,8 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
case ShaderConvert::DATM_1_RTA_CORRECTION:
case ShaderConvert::CLUT_4:
case ShaderConvert::CLUT_8:
case ShaderConvert::HDR_INIT:
case ShaderConvert::HDR_RESOLVE:
case ShaderConvert::COLCLIP_INIT:
case ShaderConvert::COLCLIP_RESOLVE:
continue;
case ShaderConvert::FLOAT32_TO_32_BITS:
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::UInt32);
@@ -1174,7 +1176,7 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
m_present_pipeline[i] = MakePipeline(pdesc, vs_convert, LoadShader(name), [NSString stringWithFormat:@"present_%s", shaderName(conv) + 3]);
}
pdesc.colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm;
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::Color);
for (size_t i = 0; i < std::size(m_convert_pipeline_copy_mask); i++)
{
MTLColorWriteMask mask = MTLColorWriteMaskNone;
@@ -1852,7 +1854,7 @@ void GSDeviceMTL::MRESetHWPipelineState(GSHWDrawConfig::VSSelector vssel, GSHWDr
setFnConstantI(m_fn_constants, pssel.blend_d, GSMTLConstantIndex_PS_BLEND_D);
setFnConstantI(m_fn_constants, pssel.blend_hw, GSMTLConstantIndex_PS_BLEND_HW);
setFnConstantB(m_fn_constants, pssel.a_masked, GSMTLConstantIndex_PS_A_MASKED);
setFnConstantB(m_fn_constants, pssel.hdr, GSMTLConstantIndex_PS_HDR);
setFnConstantB(m_fn_constants, pssel.colclip_hw, GSMTLConstantIndex_PS_COLCLIP_HW);
setFnConstantB(m_fn_constants, pssel.rta_correction, GSMTLConstantIndex_PS_RTA_CORRECTION);
setFnConstantB(m_fn_constants, pssel.rta_source_correction, GSMTLConstantIndex_PS_RTA_SRC_CORRECTION);
setFnConstantB(m_fn_constants, pssel.colclip, GSMTLConstantIndex_PS_COLCLIP);
@@ -2142,53 +2144,53 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
GSTexture* stencil = nullptr;
GSTexture* primid_tex = nullptr;
GSTexture* rt = config.rt;
GSTexture* hdr_rt = g_gs_device->GetHDRTexture();
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
if (hdr_rt)
if (colclip_rt)
{
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
{
BeginRenderPass(@"HDR Resolve", config.rt, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
RenderCopy(hdr_rt, m_hdr_resolve_pipeline, config.hdr_update_area);
BeginRenderPass(@"ColorClip Resolve", config.rt, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
RenderCopy(colclip_rt, m_colclip_resolve_pipeline, config.colclip_update_area);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
Recycle(colclip_rt);
g_gs_device->SetHDRTexture(nullptr);
g_gs_device->SetColorClipTexture(nullptr);
hdr_rt = nullptr;
colclip_rt = nullptr;
}
else
config.ps.hdr = 1;
config.ps.colclip_hw = 1;
}
if (config.ps.hdr)
if (config.ps.colclip_hw)
{
if (!hdr_rt)
if (!colclip_rt)
{
config.hdr_update_area = config.drawarea;
config.colclip_update_area = config.drawarea;
GSVector2i size = config.rt->GetSize();
rt = hdr_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::HDRColor, false);
rt = colclip_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::ColorClip, false);
g_gs_device->SetHDRTexture(hdr_rt);
g_gs_device->SetColorClipTexture(colclip_rt);
const GSVector4i copy_rect = (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(size) : config.drawarea;
const GSVector4i copy_rect = (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(size) : config.drawarea;
switch (config.rt->GetState())
{
case GSTexture::State::Dirty:
BeginRenderPass(@"HDR Init", hdr_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
RenderCopy(config.rt, m_hdr_init_pipeline, copy_rect);
BeginRenderPass(@"ColorClip Init", colclip_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
RenderCopy(config.rt, m_colclip_init_pipeline, copy_rect);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
break;
case GSTexture::State::Cleared:
{
BeginRenderPass(@"HDR Clear", hdr_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
BeginRenderPass(@"ColorClip Clear", colclip_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
GSVector4 color = GSVector4::rgba32(config.rt->GetClearColor()) / GSVector4::cxpr(65535, 65535, 65535, 255);
[m_current_render.encoder setFragmentBytes:&color length:sizeof(color) atIndex:GSMTLBufferIndexUniforms];
RenderCopy(nullptr, m_hdr_clear_pipeline, copy_rect);
RenderCopy(nullptr, m_colclip_clear_pipeline, copy_rect);
break;
}
@@ -2197,7 +2199,7 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
}
}
rt = hdr_rt;
rt = colclip_rt;
}
switch (config.destination_alpha)
@@ -2284,19 +2286,19 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
SendHWDraw(config, mtlenc, index_buffer, index_buffer_offset);
}
if (hdr_rt)
if (colclip_rt)
{
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
if ((config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve))
if ((config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve))
{
BeginRenderPass(@"HDR Resolve", config.rt, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
RenderCopy(hdr_rt, m_hdr_resolve_pipeline, config.hdr_update_area);
BeginRenderPass(@"ColorClip Resolve", config.rt, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
RenderCopy(colclip_rt, m_colclip_resolve_pipeline, config.colclip_update_area);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
Recycle(colclip_rt);
g_gs_device->SetHDRTexture(nullptr);
g_gs_device->SetColorClipTexture(nullptr);
}
}

View File

@@ -192,7 +192,7 @@ enum GSMTLFnConstants
GSMTLConstantIndex_PS_BLEND_D,
GSMTLConstantIndex_PS_BLEND_HW,
GSMTLConstantIndex_PS_A_MASKED,
GSMTLConstantIndex_PS_HDR,
GSMTLConstantIndex_PS_COLCLIP_HW,
GSMTLConstantIndex_PS_RTA_CORRECTION,
GSMTLConstantIndex_PS_RTA_SRC_CORRECTION,
GSMTLConstantIndex_PS_COLCLIP,

View File

@@ -138,13 +138,13 @@ fragment float4 ps_rta_decorrection(ConvertShaderData data [[stage_in]], Convert
return float4(in.rgb, in.a * (128.25f / 255.0f));
}
fragment float4 ps_hdr_init(float4 p [[position]], DirectReadTextureIn<float> tex)
fragment float4 ps_colclip_init(float4 p [[position]], DirectReadTextureIn<float> tex)
{
float4 in = tex.read(p);
return float4(round(in.rgb * 255.f) / 65535.f, in.a);
}
fragment float4 ps_hdr_resolve(float4 p [[position]], DirectReadTextureIn<float> tex)
fragment float4 ps_colclip_resolve(float4 p [[position]], DirectReadTextureIn<float> tex)
{
float4 in = tex.read(p);
return float4(float3(uint3(in.rgb * 65535.5f) & 255) / 255.f, in.a);

View File

@@ -47,7 +47,7 @@ constant uint PS_BLEND_C [[function_constant(GSMTLConstantIndex_PS_BL
constant uint PS_BLEND_D [[function_constant(GSMTLConstantIndex_PS_BLEND_D)]];
constant uint PS_BLEND_HW [[function_constant(GSMTLConstantIndex_PS_BLEND_HW)]];
constant bool PS_A_MASKED [[function_constant(GSMTLConstantIndex_PS_A_MASKED)]];
constant bool PS_HDR [[function_constant(GSMTLConstantIndex_PS_HDR)]];
constant bool PS_COLCLIP_HW [[function_constant(GSMTLConstantIndex_PS_COLCLIP_HW)]];
constant bool PS_RTA_CORRECTION [[function_constant(GSMTLConstantIndex_PS_RTA_CORRECTION)]];
constant bool PS_RTA_SRC_CORRECTION [[function_constant(GSMTLConstantIndex_PS_RTA_SRC_CORRECTION)]];
constant bool PS_COLCLIP [[function_constant(GSMTLConstantIndex_PS_COLCLIP)]];
@@ -858,7 +858,7 @@ struct PSMain
{
if (PS_FBMASK)
{
float multi = PS_HDR ? 65535.0 : 255.5;
float multi = PS_COLCLIP_HW ? 65535.0 : 255.5;
C = float4((uint4(int4(C)) & (cb.fbmask ^ 0xff)) | (uint4(current_color * float4(multi, multi, multi, 255)) & cb.fbmask));
}
}
@@ -898,7 +898,7 @@ struct PSMain
C.rgb += 7.f; // Need to round up, not down since the shader will invert
// Correct the Color value based on the output format
if (PS_COLCLIP == 0 && PS_HDR == 0)
if (PS_COLCLIP == 0 && PS_COLCLIP_HW == 0)
C.rgb = clamp(C.rgb, 0.f, 255.f); // Standard Clamp
// FIXME rouding of negative float?
@@ -910,7 +910,7 @@ struct PSMain
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && (PS_BLEND_MIX == 0 || PS_DITHER))
C.rgb = float3(short3(C.rgb) & 0xF8);
else if (PS_COLCLIP == 1 || PS_HDR == 1)
else if (PS_COLCLIP == 1 || PS_COLCLIP_HW == 1)
C.rgb = float3(short3(C.rgb) & 0xFF);
}
else if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && PS_BLEND_MIX == 0 && PS_BLEND_HW == 0)
@@ -963,7 +963,7 @@ struct PSMain
current_color.a = float(denorm_rt.g & 0x80);
}
}
float multi = PS_HDR ? 65535.0 : 255.5;
float multi = PS_COLCLIP_HW ? 65535.0 : 255.5;
float3 Cd = trunc(current_color.rgb * multi);
float3 Cs = Color.rgb;
@@ -1205,7 +1205,7 @@ struct PSMain
if (PS_COLOR0)
{
out.c0.a = PS_RTA_CORRECTION ? C.a / 128.f : C.a / 255.f;
out.c0.rgb = PS_HDR ? float3(C.rgb / 65535.f) : C.rgb / 255.f;
out.c0.rgb = PS_COLCLIP_HW ? float3(C.rgb / 65535.f) : C.rgb / 255.f;
if (PS_AFAIL == 3 && !PS_COLOR1 && !atst_pass) // Doing RGB_ONLY without COLOR1
out.c0.a = current_color.a;
}

View File

@@ -1394,7 +1394,7 @@ std::string GSDeviceOGL::GetPSSource(const PSSelector& sel)
+ fmt::format("#define PS_READ16_SRC {}\n", sel.real16src)
+ fmt::format("#define PS_WRITE_RG {}\n", sel.write_rg)
+ fmt::format("#define PS_FBMASK {}\n", sel.fbmask)
+ fmt::format("#define PS_HDR {}\n", sel.hdr)
+ fmt::format("#define PS_COLCLIP_HW {}\n", sel.colclip_hw)
+ fmt::format("#define PS_RTA_CORRECTION {}\n", sel.rta_correction)
+ fmt::format("#define PS_RTA_SRC_CORRECTION {}\n", sel.rta_source_correction)
+ fmt::format("#define PS_DITHER {}\n", sel.dither)
@@ -2414,43 +2414,43 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
GSTexture* primid_texture = nullptr;
GSTexture* hdr_rt = g_gs_device->GetHDRTexture();
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
if (hdr_rt)
if (colclip_rt)
{
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
{
const GSVector2i size = config.rt->GetSize();
const GSVector4 dRect(config.hdr_update_area);
const GSVector4 dRect(config.colclip_update_area);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
Recycle(hdr_rt);
Recycle(colclip_rt);
g_gs_device->SetHDRTexture(nullptr);
g_gs_device->SetColorClipTexture(nullptr);
hdr_rt = nullptr;
colclip_rt = nullptr;
}
else
{
config.ps.hdr = 1;
config.ps.colclip_hw = 1;
}
}
if (config.ps.hdr)
if (config.ps.colclip_hw)
{
if (!hdr_rt)
if (!colclip_rt)
{
config.hdr_update_area = config.drawarea;
config.colclip_update_area = config.drawarea;
hdr_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor, false);
OMSetRenderTargets(hdr_rt, config.ds, nullptr);
colclip_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false);
OMSetRenderTargets(colclip_rt, config.ds, nullptr);
g_gs_device->SetHDRTexture(hdr_rt);
g_gs_device->SetColorClipTexture(colclip_rt);
const GSVector4 dRect = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
StretchRect(config.rt, sRect, hdr_rt, dRect, ShaderConvert::HDR_INIT, false);
StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false);
}
}
@@ -2461,7 +2461,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
case GSHWDrawConfig::DestinationAlphaMode::Full:
break; // No setup
case GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking:
primid_texture = InitPrimDateTexture(hdr_rt ? hdr_rt : config.rt, config.drawarea, config.datm);
primid_texture = InitPrimDateTexture(colclip_rt ? colclip_rt : config.rt, config.drawarea, config.datm);
break;
case GSHWDrawConfig::DestinationAlphaMode::StencilOne:
if (m_features.texture_barrier)
@@ -2481,7 +2481,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
{GSVector4(dst.x, dst.w, 0.0f, 0.0f), GSVector2(src.x, src.w)},
{GSVector4(dst.z, dst.w, 0.0f, 0.0f), GSVector2(src.z, src.w)},
};
SetupDATE(hdr_rt ? hdr_rt : config.rt, config.ds, vertices, config.datm);
SetupDATE(colclip_rt ? colclip_rt : config.rt, config.ds, vertices, config.datm);
}
}
@@ -2490,11 +2490,11 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
if (config.require_one_barrier && !m_features.texture_barrier)
{
// Requires a copy of the RT
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, hdr_rt ? GSTexture::Format::HDRColor : GSTexture::Format::Color, true);
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}",
config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
CopyRect(hdr_rt ? hdr_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
}
IASetVertexBuffer(config.verts, config.nverts);
@@ -2534,7 +2534,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
if (draw_rt_clone)
PSSetShaderResource(2, draw_rt_clone);
else if (config.require_one_barrier || config.require_full_barrier)
PSSetShaderResource(2, hdr_rt ? hdr_rt : config.rt);
PSSetShaderResource(2, colclip_rt ? colclip_rt : config.rt);
SetupSampler(config.sampler);
@@ -2622,7 +2622,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
}
// avoid changing framebuffer just to switch from rt+depth to rt and vice versa
GSTexture* draw_rt = hdr_rt ? hdr_rt : config.rt;
GSTexture* draw_rt = colclip_rt ? colclip_rt : config.rt;
GSTexture* draw_ds = config.ds;
if (!draw_rt && GLState::rt && GLState::ds == draw_ds && config.tex != GLState::rt &&
GLState::rt->GetSize() == draw_ds->GetSize())
@@ -2700,20 +2700,20 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
if (draw_rt_clone)
Recycle(draw_rt_clone);
if (hdr_rt)
if (colclip_rt)
{
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
if ((config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve))
if ((config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve))
{
const GSVector2i size = config.rt->GetSize();
const GSVector4 dRect(config.hdr_update_area);
const GSVector4 dRect(config.colclip_update_area);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
Recycle(hdr_rt);
Recycle(colclip_rt);
g_gs_device->SetHDRTexture(nullptr);
g_gs_device->SetColorClipTexture(nullptr);
}
}
}

View File

@@ -65,6 +65,8 @@ GSTextureOGL::GSTextureOGL(Type type, int width, int height, int levels, Format
// 4 channel normalized
case Format::Color:
case Format::ColorHQ:
case Format::ColorHDR:
gl_fmt = GL_RGBA8;
m_int_format = GL_RGBA;
m_int_type = GL_UNSIGNED_BYTE;
@@ -72,7 +74,7 @@ GSTextureOGL::GSTextureOGL(Type type, int width, int height, int levels, Format
break;
// 4 channel float
case Format::HDRColor:
case Format::ColorClip:
gl_fmt = GL_RGBA16;
m_int_format = GL_RGBA;
m_int_type = GL_UNSIGNED_SHORT;

View File

@@ -2104,7 +2104,8 @@ bool GSDeviceVK::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
return false;
}
CompileCASPipelines();
if (!CompileCASPipelines())
return false;
if (!CompileImGuiPipeline())
return false;
@@ -2715,10 +2716,12 @@ void GSDeviceVK::DrawIndexedPrimitive(int offset, int count)
VkFormat GSDeviceVK::LookupNativeFormat(GSTexture::Format format) const
{
static constexpr std::array<VkFormat, static_cast<int>(GSTexture::Format::BC7) + 1> s_format_mapping = {{
static constexpr std::array<VkFormat, static_cast<int>(GSTexture::Format::Last) + 1> s_format_mapping = {{
VK_FORMAT_UNDEFINED, // Invalid
VK_FORMAT_R8G8B8A8_UNORM, // Color
VK_FORMAT_R16G16B16A16_UNORM, // HDRColor
VK_FORMAT_A2B10G10R10_UNORM_PACK32, // ColorHQ
VK_FORMAT_R16G16B16A16_SFLOAT, // ColorHDR
VK_FORMAT_R16G16B16A16_UNORM, // ColorClip
VK_FORMAT_D32_SFLOAT_S8_UINT, // DepthStencil
VK_FORMAT_R8_UNORM, // UNorm8
VK_FORMAT_R16_UINT, // UInt16
@@ -3764,7 +3767,7 @@ bool GSDeviceVK::CreatePipelineLayouts()
plb.AddDescriptorSet(m_utility_ds_layout);
if ((m_utility_pipeline_layout = plb.Create(dev)) == VK_NULL_HANDLE)
return false;
Vulkan::SetObjectName(dev, m_utility_ds_layout, "Convert pipeline layout");
Vulkan::SetObjectName(dev, m_utility_pipeline_layout, "Convert pipeline layout");
//////////////////////////////////////////////////////////////////////////
// Draw/TFX Pipeline Layout
@@ -3820,14 +3823,14 @@ bool GSDeviceVK::CreateRenderPasses()
} while (0)
const VkFormat rt_format = LookupNativeFormat(GSTexture::Format::Color);
const VkFormat hdr_rt_format = LookupNativeFormat(GSTexture::Format::HDRColor);
const VkFormat colclip_rt_format = LookupNativeFormat(GSTexture::Format::ColorClip);
const VkFormat depth_format = LookupNativeFormat(GSTexture::Format::DepthStencil);
for (u32 rt = 0; rt < 2; rt++)
{
for (u32 ds = 0; ds < 2; ds++)
{
for (u32 hdr = 0; hdr < 2; hdr++)
for (u32 colclip = 0; colclip < 2; colclip++)
{
for (u32 stencil = 0; stencil < 2; stencil++)
{
@@ -3841,12 +3844,12 @@ bool GSDeviceVK::CreateRenderPasses()
opb++)
{
const VkFormat rp_rt_format =
(rt != 0) ? ((hdr != 0) ? hdr_rt_format : rt_format) : VK_FORMAT_UNDEFINED;
(rt != 0) ? ((colclip != 0) ? colclip_rt_format : rt_format) : VK_FORMAT_UNDEFINED;
const VkFormat rp_depth_format = (ds != 0) ? depth_format : VK_FORMAT_UNDEFINED;
const VkAttachmentLoadOp opc = (!stencil || !m_features.stencil_buffer) ?
VK_ATTACHMENT_LOAD_OP_DONT_CARE :
VK_ATTACHMENT_LOAD_OP_LOAD;
GET(m_tfx_render_pass[rt][ds][hdr][stencil][fbl][dsp][opa][opb], rp_rt_format,
GET(m_tfx_render_pass[rt][ds][colclip][stencil][fbl][dsp][opa][opb], rp_rt_format,
rp_depth_format, (fbl != 0), (dsp != 0), static_cast<VkAttachmentLoadOp>(opa),
static_cast<VkAttachmentLoadOp>(opb), static_cast<VkAttachmentLoadOp>(opc));
}
@@ -3999,15 +4002,7 @@ bool GSDeviceVK::CompileConvertPipelines()
}
else if (i == ShaderConvert::RTA_CORRECTION)
{
// compile color copy pipelines
gpb.SetRenderPass(m_utility_color_render_pass_discard, 0);
VkShaderModule ps = GetUtilityFragmentShader(*shader, shaderName(i));
if (ps == VK_NULL_HANDLE)
return false;
ScopedGuard ps_guard([this, &ps]() { vkDestroyShaderModule(m_device, ps, nullptr); });
gpb.SetFragmentShader(ps);
for (u32 j = 16; j < 32; j++)
{
pxAssert(!m_color_copy[j]);
@@ -4023,10 +4018,10 @@ bool GSDeviceVK::CompileConvertPipelines()
(j >> 1) & 1u, (j >> 2) & 1u, (j >> 3) & 1u);
}
}
else if (i == ShaderConvert::HDR_INIT || i == ShaderConvert::HDR_RESOLVE)
else if (i == ShaderConvert::COLCLIP_INIT || i == ShaderConvert::COLCLIP_RESOLVE)
{
const bool is_setup = i == ShaderConvert::HDR_INIT;
VkPipeline(&arr)[2][2] = *(is_setup ? &m_hdr_setup_pipelines : &m_hdr_finish_pipelines);
const bool is_setup = i == ShaderConvert::COLCLIP_INIT;
VkPipeline(&arr)[2][2] = *(is_setup ? &m_colclip_setup_pipelines : &m_colclip_finish_pipelines);
for (u32 ds = 0; ds < 2; ds++)
{
for (u32 fbl = 0; fbl < 2; fbl++)
@@ -4040,7 +4035,7 @@ bool GSDeviceVK::CompileConvertPipelines()
if (!arr[ds][fbl])
return false;
Vulkan::SetObjectName(m_device, arr[ds][fbl], "HDR %s/copy pipeline (ds=%u, fbl=%u)",
Vulkan::SetObjectName(m_device, arr[ds][fbl], "ColorClip %s/copy pipeline (ds=%u, fbl=%u)",
is_setup ? "setup" : "finish", i, ds, fbl);
}
}
@@ -4196,7 +4191,7 @@ bool GSDeviceVK::CompileInterlacePipelines()
if (!m_interlace[i])
return false;
Vulkan::SetObjectName(m_device, m_convert[i], "Interlace pipeline %d", i);
Vulkan::SetObjectName(m_device, m_interlace[i], "Interlace pipeline %d", i);
}
return true;
@@ -4248,7 +4243,7 @@ bool GSDeviceVK::CompileMergePipelines()
if (!m_merge[i])
return false;
Vulkan::SetObjectName(m_device, m_convert[i], "Merge pipeline %d", i);
Vulkan::SetObjectName(m_device, m_merge[i], "Merge pipeline %d", i);
}
return true;
@@ -4610,10 +4605,10 @@ void GSDeviceVK::DestroyResources()
{
for (u32 fbl = 0; fbl < 2; fbl++)
{
if (m_hdr_setup_pipelines[ds][fbl] != VK_NULL_HANDLE)
vkDestroyPipeline(m_device, m_hdr_setup_pipelines[ds][fbl], nullptr);
if (m_hdr_finish_pipelines[ds][fbl] != VK_NULL_HANDLE)
vkDestroyPipeline(m_device, m_hdr_finish_pipelines[ds][fbl], nullptr);
if (m_colclip_setup_pipelines[ds][fbl] != VK_NULL_HANDLE)
vkDestroyPipeline(m_device, m_colclip_setup_pipelines[ds][fbl], nullptr);
if (m_colclip_finish_pipelines[ds][fbl] != VK_NULL_HANDLE)
vkDestroyPipeline(m_device, m_colclip_finish_pipelines[ds][fbl], nullptr);
}
}
for (u32 ds = 0; ds < 2; ds++)
@@ -4782,7 +4777,7 @@ VkShaderModule GSDeviceVK::GetTFXFragmentShader(const GSHWDrawConfig::PSSelector
AddMacro(ss, "PS_READ16_SRC", sel.real16src);
AddMacro(ss, "PS_WRITE_RG", sel.write_rg);
AddMacro(ss, "PS_FBMASK", sel.fbmask);
AddMacro(ss, "PS_HDR", sel.hdr);
AddMacro(ss, "PS_COLCLIP_HW", sel.colclip_hw);
AddMacro(ss, "PS_RTA_CORRECTION", sel.rta_correction);
AddMacro(ss, "PS_RTA_SRC_CORRECTION", sel.rta_source_correction);
AddMacro(ss, "PS_DITHER", sel.dither);
@@ -4838,7 +4833,7 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p)
else
{
gpb.SetRenderPass(
GetTFXRenderPass(p.rt, p.ds, p.ps.hdr, p.dss.date,
GetTFXRenderPass(p.rt, p.ds, p.ps.colclip_hw, p.dss.date,
p.IsRTFeedbackLoop(), p.IsTestingAndSamplingDepth(),
p.rt ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
p.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
@@ -4967,7 +4962,7 @@ void GSDeviceVK::InitializeState()
Vulkan::SetObjectName(m_device, m_point_sampler, "Point sampler");
m_linear_sampler = GetSampler(GSHWDrawConfig::SamplerSelector::Linear());
if (m_linear_sampler)
Vulkan::SetObjectName(m_device, m_point_sampler, "Linear sampler");
Vulkan::SetObjectName(m_device, m_linear_sampler, "Linear sampler");
m_tfx_sampler_sel = GSHWDrawConfig::SamplerSelector::Point().key;
m_tfx_sampler = m_point_sampler;
@@ -5595,7 +5590,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
GSTextureVK* draw_rt = static_cast<GSTextureVK*>(config.rt);
GSTextureVK* draw_ds = static_cast<GSTextureVK*>(config.ds);
GSTextureVK* draw_rt_clone = nullptr;
GSTextureVK* hdr_rt = static_cast<GSTextureVK*>(g_gs_device->GetHDRTexture());
GSTextureVK* colclip_rt = static_cast<GSTextureVK*>(g_gs_device->GetColorClipTexture());
// stream buffer in first, in case we need to exec
SetVSConstantBuffer(config.cb_vs);
@@ -5621,11 +5616,11 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
GSTextureVK* date_image = nullptr;
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking)
{
// If we have a HDR in progress, we need to use the HDR texture, but we can't check this later as there's a chicken/egg problem with the pipe setup.
// If we have a colclip in progress, we need to use the colclip texture, but we can't check this later as there's a chicken/egg problem with the pipe setup.
GSTexture* backup_rt = config.rt;
if(hdr_rt)
config.rt = hdr_rt;
if(colclip_rt)
config.rt = colclip_rt;
date_image = SetupPrimitiveTrackingDATE(config);
if (!date_image)
@@ -5645,15 +5640,15 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
if (InRenderPass() && !pipe.IsRTFeedbackLoop() && (config.tex == m_current_render_target || config.tex == m_current_depth_target))
EndRenderPass();
// now blit the hdr texture back to the original target
if (hdr_rt)
// now blit the colclip texture back to the original target
if (colclip_rt)
{
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
{
GL_PUSH("Blit HDR back to RT");
GL_PUSH("Blit ColorClip back to RT");
EndRenderPass();
hdr_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
colclip_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
draw_rt = static_cast<GSTextureVK*>(config.rt);
OMSetRenderTargets(draw_rt, draw_ds, GSVector4i::loadh(rtsize), static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
@@ -5681,22 +5676,22 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
draw_rt->GetRect());
}
const GSVector4 drawareaf = GSVector4(config.hdr_update_area);
const GSVector4 drawareaf = GSVector4(config.colclip_update_area);
const GSVector4 sRect(drawareaf / GSVector4(rtsize).xyxy());
SetPipeline(m_hdr_finish_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
SetUtilityTexture(hdr_rt, m_point_sampler);
SetPipeline(m_colclip_finish_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
SetUtilityTexture(colclip_rt, m_point_sampler);
DrawStretchRect(sRect, drawareaf, rtsize);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
g_gs_device->SetHDRTexture(nullptr);
Recycle(colclip_rt);
g_gs_device->SetColorClipTexture(nullptr);
hdr_rt = nullptr;
colclip_rt = nullptr;
}
else
{
pipe.ps.hdr = 1;
draw_rt = hdr_rt;
pipe.ps.colclip_hw = 1;
draw_rt = colclip_rt;
}
}
@@ -5726,7 +5721,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
if (config.require_one_barrier && !m_features.texture_barrier)
{
// requires a copy of the RT
draw_rt_clone = static_cast<GSTextureVK*>(CreateTexture(rtsize.x, rtsize.y, 1, hdr_rt ? GSTexture::Format::HDRColor : GSTexture::Format::Color, true));
draw_rt_clone = static_cast<GSTextureVK*>(CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true));
if (draw_rt_clone)
{
EndRenderPass();
@@ -5739,17 +5734,17 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
}
}
// Switch to hdr target for colclip rendering
if (pipe.ps.hdr)
// Switch to colclip target for colclip hw rendering
if (pipe.ps.colclip_hw)
{
if (!hdr_rt)
if (!colclip_rt)
{
config.hdr_update_area = config.drawarea;
config.colclip_update_area = config.drawarea;
EndRenderPass();
hdr_rt = static_cast<GSTextureVK*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor, false));
if (!hdr_rt)
colclip_rt = static_cast<GSTextureVK*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false));
if (!colclip_rt)
{
Console.WriteLn("Failed to allocate HDR render target, aborting draw.");
Console.WriteLn("Failed to allocate ColorClip render target, aborting draw.");
if (date_image)
Recycle(date_image);
@@ -5757,13 +5752,13 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
GL_POP();
return;
}
g_gs_device->SetHDRTexture(static_cast<GSTexture*>(hdr_rt));
g_gs_device->SetColorClipTexture(static_cast<GSTexture*>(colclip_rt));
// propagate clear value through if the hdr render is the first
// propagate clear value through if the colclip render is the first
if (draw_rt->GetState() == GSTexture::State::Cleared)
{
hdr_rt->SetState(GSTexture::State::Cleared);
hdr_rt->SetClearColor(draw_rt->GetClearColor());
colclip_rt->SetState(GSTexture::State::Cleared);
colclip_rt->SetClearColor(draw_rt->GetClearColor());
// If depth is cleared, we need to commit it, because we're only going to draw to the active part of the FB.
if (draw_ds && draw_ds->GetState() == GSTexture::State::Cleared && !config.drawarea.eq(GSVector4i::loadh(rtsize)))
@@ -5771,7 +5766,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
}
else if (draw_rt->GetState() == GSTexture::State::Dirty)
{
GL_PUSH_("HDR Render Target Setup");
GL_PUSH_("ColorClip Render Target Setup");
draw_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
}
@@ -5779,7 +5774,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
if (config.require_one_barrier && !m_features.texture_barrier)
PSSetShaderResource(2, draw_rt, true);
}
draw_rt = hdr_rt;
draw_rt = colclip_rt;
}
// clear texture binding when it's bound to RT or DS.
@@ -5790,15 +5785,15 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
}
// render pass restart optimizations
if (hdr_rt && (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly))
if (colclip_rt && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly))
{
// HDR requires blitting.
// colclip hw requires blitting.
EndRenderPass();
}
else if (InRenderPass() && (m_current_render_target == draw_rt || m_current_depth_target == draw_ds))
{
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
// keep the depth even if doing HDR draws, because the next draw will probably re-enable depth
// keep the depth even if doing colclip hw draws, because the next draw will probably re-enable depth
if (!draw_rt && m_current_render_target && config.tex != m_current_render_target &&
m_current_render_target->GetSize() == draw_ds->GetSize())
{
@@ -5817,15 +5812,15 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
}
// We don't need the very first barrier if this is the first draw after switching to feedback loop,
// because the layout change in itself enforces the execution dependency. HDR needs a barrier between
// setup and the first draw to read it. TODO: Make HDR use subpasses instead.
// because the layout change in itself enforces the execution dependency. colclip hw needs a barrier between
// setup and the first draw to read it. TODO: Make colclip hw use subpasses instead.
// However, it turns out *not* doing this causes GPU resets on RDNA3, specifically Windows drivers.
// Despite the layout changing enforcing the execution dependency between previous draws and the first
// input attachment read, it still wants the region/fragment-local barrier...
const bool skip_first_barrier =
(draw_rt && draw_rt->GetLayout() != GSTextureVK::Layout::FeedbackLoop && !pipe.ps.hdr && !IsDeviceAMD());
(draw_rt && draw_rt->GetLayout() != GSTextureVK::Layout::FeedbackLoop && !pipe.ps.colclip_hw && !IsDeviceAMD());
OMSetRenderTargets(draw_rt, draw_ds, config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
if (pipe.IsRTFeedbackLoop())
@@ -5843,14 +5838,14 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
{
const VkAttachmentLoadOp rt_op = GetLoadOpForTexture(draw_rt);
const VkAttachmentLoadOp ds_op = GetLoadOpForTexture(draw_ds);
const VkRenderPass rp = GetTFXRenderPass(pipe.rt, pipe.ds, pipe.ps.hdr,
const VkRenderPass rp = GetTFXRenderPass(pipe.rt, pipe.ds, pipe.ps.colclip_hw,
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil, pipe.IsRTFeedbackLoop(),
pipe.IsTestingAndSamplingDepth(), rt_op, ds_op);
const bool is_clearing_rt = (rt_op == VK_ATTACHMENT_LOAD_OP_CLEAR || ds_op == VK_ATTACHMENT_LOAD_OP_CLEAR);
// Only draw to the active area of the HDR target. Except when depth is cleared, we need to use the full
// Only draw to the active area of the colclip hw target. Except when depth is cleared, we need to use the full
// buffer size, otherwise it'll only clear the draw part of the depth buffer.
const GSVector4i render_area = (pipe.ps.hdr && (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve) && ds_op != VK_ATTACHMENT_LOAD_OP_CLEAR) ? config.drawarea :
const GSVector4i render_area = (pipe.ps.colclip_hw && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && ds_op != VK_ATTACHMENT_LOAD_OP_CLEAR) ? config.drawarea :
GSVector4i::loadh(rtsize);
if (is_clearing_rt)
@@ -5861,9 +5856,9 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
if (draw_rt)
{
GSVector4 clear_color = draw_rt->GetUNormClearColor();
if (pipe.ps.hdr)
if (pipe.ps.colclip_hw)
{
// Denormalize clear color for HDR.
// Denormalize clear color for hw colclip.
clear_color *= GSVector4::cxpr(255.0f / 65535.0f, 255.0f / 65535.0f, 255.0f / 65535.0f, 1.0f);
}
GSVector4::store<true>(&cvs[cv_count++].color, clear_color);
@@ -5888,14 +5883,14 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
vkCmdClearAttachments(m_current_command_buffer, 1, &ca, 1, &rc);
}
// rt -> hdr blit if enabled
if (hdr_rt && (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
// rt -> colclip hw blit if enabled
if (colclip_rt && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
{
OMSetRenderTargets(draw_rt, draw_ds, GSVector4i::loadh(rtsize), static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
SetUtilityTexture(static_cast<GSTextureVK*>(config.rt), m_point_sampler);
SetPipeline(m_hdr_setup_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
SetPipeline(m_colclip_setup_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
const GSVector4 drawareaf = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 drawareaf = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 sRect(drawareaf / GSVector4(rtsize).xyxy());
DrawStretchRect(sRect, drawareaf, rtsize);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
@@ -5904,8 +5899,8 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
OMSetRenderTargets(draw_rt, draw_ds, config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
}
// VB/IB upload, if we did DATE setup and it's not HDR this has already been done
if (!date_image || hdr_rt)
// VB/IB upload, if we did DATE setup and it's not colclip hw this has already been done
if (!date_image || colclip_rt)
UploadHWDrawVerticesAndIndices(config);
// now we can do the actual draw
@@ -5955,21 +5950,21 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
if (date_image)
Recycle(date_image);
// now blit the hdr texture back to the original target
if (hdr_rt)
// now blit the colclip texture back to the original target
if (colclip_rt)
{
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
if ((config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve))
if ((config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve))
{
GL_PUSH("Blit HDR back to RT");
GL_PUSH("Blit ColorClip back to RT");
EndRenderPass();
hdr_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
colclip_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
draw_rt = static_cast<GSTextureVK*>(config.rt);
OMSetRenderTargets(draw_rt, draw_ds, (config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly) ? GSVector4i::loadh(rtsize) : config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
OMSetRenderTargets(draw_rt, draw_ds, (config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly) ? GSVector4i::loadh(rtsize) : config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
// if this target was cleared and never drawn to, perform the clear as part of the resolve here.
if (draw_rt->GetState() == GSTexture::State::Cleared)
@@ -5994,19 +5989,19 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
draw_rt->GetRect());
}
const GSVector4 drawareaf = GSVector4(config.hdr_update_area);
const GSVector4 drawareaf = GSVector4(config.colclip_update_area);
const GSVector4 sRect(drawareaf / GSVector4(rtsize).xyxy());
SetPipeline(m_hdr_finish_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
SetUtilityTexture(hdr_rt, m_point_sampler);
SetPipeline(m_colclip_finish_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
SetUtilityTexture(colclip_rt, m_point_sampler);
DrawStretchRect(sRect, drawareaf, rtsize);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(hdr_rt);
g_gs_device->SetHDRTexture(nullptr);
Recycle(colclip_rt);
g_gs_device->SetColorClipTexture(nullptr);
}
}
config.hdr_mode = GSHWDrawConfig::HDRMode::NoModify;
config.colclip_mode = GSHWDrawConfig::ColClipMode::NoModify;
}
void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe)

View File

@@ -394,8 +394,8 @@ private:
std::array<VkPipeline, 32> m_color_copy{};
std::array<VkPipeline, 2> m_merge{};
std::array<VkPipeline, NUM_INTERLACE_SHADERS> m_interlace{};
VkPipeline m_hdr_setup_pipelines[2][2] = {}; // [depth][feedback_loop]
VkPipeline m_hdr_finish_pipelines[2][2] = {}; // [depth][feedback_loop]
VkPipeline m_colclip_setup_pipelines[2][2] = {}; // [depth][feedback_loop]
VkPipeline m_colclip_finish_pipelines[2][2] = {}; // [depth][feedback_loop]
VkRenderPass m_date_image_setup_render_passes[2][2] = {}; // [depth][clear]
VkPipeline m_date_image_setup_pipelines[2][4] = {}; // [depth][datm]
VkPipeline m_fxaa_pipeline = {};
@@ -415,7 +415,7 @@ private:
VkRenderPass m_date_setup_render_pass = VK_NULL_HANDLE;
VkRenderPass m_swap_chain_render_pass = VK_NULL_HANDLE;
VkRenderPass m_tfx_render_pass[2][2][2][3][2][2][3][3] = {}; // [rt][ds][hdr][date][fbl][dsp][rt_op][ds_op]
VkRenderPass m_tfx_render_pass[2][2][2][3][2][2][3][3] = {}; // [rt][ds][colclip][date][fbl][dsp][rt_op][ds_op]
VkDescriptorSetLayout m_cas_ds_layout = VK_NULL_HANDLE;
VkPipelineLayout m_cas_pipeline_layout = VK_NULL_HANDLE;
@@ -486,10 +486,10 @@ public:
/// Returns true if Vulkan is suitable as a default for the devices in the system.
static bool IsSuitableDefaultRenderer();
__fi VkRenderPass GetTFXRenderPass(bool rt, bool ds, bool hdr, bool stencil, bool fbl, bool dsp,
__fi VkRenderPass GetTFXRenderPass(bool rt, bool ds, bool colclip, bool stencil, bool fbl, bool dsp,
VkAttachmentLoadOp rt_op, VkAttachmentLoadOp ds_op) const
{
return m_tfx_render_pass[rt][ds][hdr][stencil][fbl][dsp][rt_op][ds_op];
return m_tfx_render_pass[rt][ds][colclip][stencil][fbl][dsp][rt_op][ds_op];
}
__fi VkSampler GetPointSampler() const { return m_point_sampler; }
__fi VkSampler GetLinearSampler() const { return m_linear_sampler; }

View File

@@ -3,4 +3,4 @@
/// Version number for GS and other shaders. Increment whenever any of the contents of the
/// shaders change, to invalidate the cache.
static constexpr u32 SHADER_CACHE_VERSION = 62;
static constexpr u32 SHADER_CACHE_VERSION = 63;