mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
VideoCommon: Always use fbfetch in ubershaders if available
Reduce the number of different pipelines needed. Also works around drivers that break when you combine fbfetch with dual source blending
This commit is contained in:
@ -743,9 +743,17 @@ static GXUberPipelineUid ApplyDriverBugs(const GXUberPipelineUid& in)
|
|||||||
{
|
{
|
||||||
GXUberPipelineUid out;
|
GXUberPipelineUid out;
|
||||||
memcpy(&out, &in, sizeof(out)); // Copy padding
|
memcpy(&out, &in, sizeof(out)); // Copy padding
|
||||||
if (!g_ActiveConfig.backend_info.bSupportsDualSourceBlend ||
|
if (g_ActiveConfig.backend_info.bSupportsFramebufferFetch)
|
||||||
(DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) &&
|
{
|
||||||
!out.blending_state.RequiresDualSrc()))
|
// Always blend in shader
|
||||||
|
out.blending_state.hex = 0;
|
||||||
|
out.blending_state.colorupdate = in.blending_state.colorupdate.Value();
|
||||||
|
out.blending_state.alphaupdate = in.blending_state.alphaupdate.Value();
|
||||||
|
out.ps_uid.GetUidData()->no_dual_src = true;
|
||||||
|
}
|
||||||
|
else if (!g_ActiveConfig.backend_info.bSupportsDualSourceBlend ||
|
||||||
|
(DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) &&
|
||||||
|
!out.blending_state.RequiresDualSrc()))
|
||||||
{
|
{
|
||||||
out.blending_state.usedualsrc = false;
|
out.blending_state.usedualsrc = false;
|
||||||
out.ps_uid.GetUidData()->no_dual_src = true;
|
out.ps_uid.GetUidData()->no_dual_src = true;
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "VideoCommon/UberShaderPixel.h"
|
#include "VideoCommon/UberShaderPixel.h"
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
|
||||||
#include "VideoCommon/BPMemory.h"
|
#include "VideoCommon/BPMemory.h"
|
||||||
#include "VideoCommon/DriverDetails.h"
|
#include "VideoCommon/DriverDetails.h"
|
||||||
#include "VideoCommon/NativeVertexFormat.h"
|
#include "VideoCommon/NativeVertexFormat.h"
|
||||||
@ -39,8 +41,11 @@ void ClearUnusedPixelShaderUidBits(APIType api_type, const ShaderHostConfig& hos
|
|||||||
{
|
{
|
||||||
pixel_ubershader_uid_data* const uid_data = uid->GetUidData();
|
pixel_ubershader_uid_data* const uid_data = uid->GetUidData();
|
||||||
|
|
||||||
|
// With fbfetch, ubershaders always blend using that and don't use dual src
|
||||||
|
if (host_config.backend_shader_framebuffer_fetch || !host_config.backend_dual_source_blend)
|
||||||
|
uid_data->no_dual_src = 1;
|
||||||
// Dual source is always enabled in the shader if this bug is not present
|
// Dual source is always enabled in the shader if this bug is not present
|
||||||
if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING))
|
else if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING))
|
||||||
uid_data->no_dual_src = 0;
|
uid_data->no_dual_src = 0;
|
||||||
|
|
||||||
// OpenGL and Vulkan convert implicitly normalized color outputs to their uint representation.
|
// OpenGL and Vulkan convert implicitly normalized color outputs to their uint representation.
|
||||||
@ -57,20 +62,17 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||||||
const bool msaa = host_config.msaa;
|
const bool msaa = host_config.msaa;
|
||||||
const bool ssaa = host_config.ssaa;
|
const bool ssaa = host_config.ssaa;
|
||||||
const bool stereo = host_config.stereo;
|
const bool stereo = host_config.stereo;
|
||||||
|
const bool use_framebuffer_fetch = host_config.backend_shader_framebuffer_fetch;
|
||||||
const bool use_dual_source = host_config.backend_dual_source_blend && !uid_data->no_dual_src;
|
const bool use_dual_source = host_config.backend_dual_source_blend && !uid_data->no_dual_src;
|
||||||
const bool use_shader_blend = !host_config.backend_dual_source_blend &&
|
|
||||||
host_config.backend_shader_framebuffer_fetch;
|
|
||||||
const bool use_shader_logic_op =
|
|
||||||
!host_config.backend_logic_op && host_config.backend_shader_framebuffer_fetch;
|
|
||||||
const bool use_framebuffer_fetch =
|
|
||||||
use_shader_blend || use_shader_logic_op ||
|
|
||||||
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z);
|
|
||||||
const bool early_depth = uid_data->early_depth != 0;
|
const bool early_depth = uid_data->early_depth != 0;
|
||||||
const bool per_pixel_depth = uid_data->per_pixel_depth != 0;
|
const bool per_pixel_depth = uid_data->per_pixel_depth != 0;
|
||||||
const bool bounding_box = host_config.bounding_box;
|
const bool bounding_box = host_config.bounding_box;
|
||||||
const u32 numTexgen = uid_data->num_texgens;
|
const u32 numTexgen = uid_data->num_texgens;
|
||||||
ShaderCode out;
|
ShaderCode out;
|
||||||
|
|
||||||
|
ASSERT_MSG(VIDEO, !(use_dual_source && use_framebuffer_fetch),
|
||||||
|
"If you're using framebuffer fetch, you shouldn't need dual source blend!");
|
||||||
|
|
||||||
out.Write("// {}\n", *uid_data);
|
out.Write("// {}\n", *uid_data);
|
||||||
WriteBitfieldExtractHeader(out, api_type, host_config);
|
WriteBitfieldExtractHeader(out, api_type, host_config);
|
||||||
WritePixelShaderCommonHeader(out, api_type, host_config, bounding_box);
|
WritePixelShaderCommonHeader(out, api_type, host_config, bounding_box);
|
||||||
@ -84,9 +86,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||||||
{
|
{
|
||||||
if (use_dual_source)
|
if (use_dual_source)
|
||||||
{
|
{
|
||||||
out.Write("FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 0) out vec4 {};\n"
|
out.Write("FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 0) out vec4 ocol0;\n"
|
||||||
"FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 1) out vec4 ocol1;\n",
|
"FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 1) out vec4 ocol1;\n");
|
||||||
use_framebuffer_fetch ? "real_ocol0" : "ocol0");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -525,12 +526,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||||||
// intermediate value with multiple reads & modifications, so we pull out the "real" output
|
// intermediate value with multiple reads & modifications, so we pull out the "real" output
|
||||||
// value above and use a temporary for calculations, then set the output value once at the
|
// value above and use a temporary for calculations, then set the output value once at the
|
||||||
// end of the shader.
|
// end of the shader.
|
||||||
out.Write(" float4 ocol0;\n");
|
out.Write(" float4 ocol0;\n"
|
||||||
}
|
" float4 ocol1;\n");
|
||||||
|
|
||||||
if (use_shader_blend)
|
|
||||||
{
|
|
||||||
out.Write(" float4 ocol1;\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (host_config.backend_geometry_shaders && stereo)
|
if (host_config.backend_geometry_shaders && stereo)
|
||||||
@ -948,8 +945,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||||||
{
|
{
|
||||||
// Instead of using discard, fetch the framebuffer's color value and use it as the output
|
// Instead of using discard, fetch the framebuffer's color value and use it as the output
|
||||||
// for this fragment.
|
// for this fragment.
|
||||||
out.Write(" #define discard_fragment {{ {} = float4(initial_ocol0.xyz, 1.0); return; }}\n",
|
out.Write(
|
||||||
use_shader_blend ? "real_ocol0" : "ocol0");
|
" #define discard_fragment {{ real_ocol0 = float4(initial_ocol0.xyz, 1.0); return; }}\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1060,7 +1057,7 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||||||
" }}\n"
|
" }}\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
|
||||||
if (use_shader_logic_op)
|
if (use_framebuffer_fetch)
|
||||||
{
|
{
|
||||||
static constexpr std::array<const char*, 16> logic_op_mode{
|
static constexpr std::array<const char*, 16> logic_op_mode{
|
||||||
"int4(0, 0, 0, 0)", // CLEAR
|
"int4(0, 0, 0, 0)", // CLEAR
|
||||||
@ -1117,7 +1114,7 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||||||
" ocol0.a = float(TevResult.a >> 2) / 63.0;\n"
|
" ocol0.a = float(TevResult.a >> 2) / 63.0;\n"
|
||||||
" \n");
|
" \n");
|
||||||
|
|
||||||
if (use_dual_source || use_shader_blend)
|
if (use_dual_source || use_framebuffer_fetch)
|
||||||
{
|
{
|
||||||
out.Write(" // Dest alpha override (dual source blending)\n"
|
out.Write(" // Dest alpha override (dual source blending)\n"
|
||||||
" // Colors will be blended against the alpha from ocol1 and\n"
|
" // Colors will be blended against the alpha from ocol1 and\n"
|
||||||
@ -1133,7 +1130,7 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||||||
" }}\n");
|
" }}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_shader_blend)
|
if (use_framebuffer_fetch)
|
||||||
{
|
{
|
||||||
using Common::EnumMap;
|
using Common::EnumMap;
|
||||||
|
|
||||||
@ -1212,10 +1209,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||||||
" real_ocol0 = ocol0;\n"
|
" real_ocol0 = ocol0;\n"
|
||||||
" }}\n");
|
" }}\n");
|
||||||
}
|
}
|
||||||
else if (use_framebuffer_fetch)
|
|
||||||
{
|
|
||||||
out.Write(" real_ocol0 = ocol0;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
out.Write("}}\n"
|
out.Write("}}\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
Reference in New Issue
Block a user