Merge pull request #10290 from OatmealDome/m1-earlyz-bug
DriverDetails: Add broken discard with early-Z bug on Apple Silicon GPUs
This commit is contained in:
commit
c42392c565
|
@ -132,53 +132,65 @@ static VkPipelineDepthStencilStateCreateInfo GetVulkanDepthStencilState(const De
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static VkPipelineColorBlendAttachmentState GetVulkanAttachmentBlendState(const BlendingState& state)
|
static VkPipelineColorBlendAttachmentState
|
||||||
|
GetVulkanAttachmentBlendState(const BlendingState& state, AbstractPipelineUsage usage)
|
||||||
{
|
{
|
||||||
VkPipelineColorBlendAttachmentState vk_state = {};
|
VkPipelineColorBlendAttachmentState vk_state = {};
|
||||||
vk_state.blendEnable = static_cast<VkBool32>(state.blendenable);
|
|
||||||
vk_state.colorBlendOp = state.subtract ? VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_ADD;
|
|
||||||
vk_state.alphaBlendOp = state.subtractAlpha ? VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_ADD;
|
|
||||||
|
|
||||||
bool use_dual_source =
|
bool use_dual_source =
|
||||||
state.usedualsrc && g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
|
state.usedualsrc && g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
|
||||||
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) || state.dstalpha);
|
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) || state.dstalpha);
|
||||||
|
bool use_shader_blend = !use_dual_source && state.usedualsrc && state.dstalpha &&
|
||||||
|
g_ActiveConfig.backend_info.bSupportsFramebufferFetch;
|
||||||
|
|
||||||
if (use_dual_source)
|
if (use_shader_blend || (usage == AbstractPipelineUsage::GX &&
|
||||||
|
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z)))
|
||||||
{
|
{
|
||||||
static constexpr std::array<VkBlendFactor, 8> src_factors = {
|
vk_state.blendEnable = VK_FALSE;
|
||||||
{VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_DST_COLOR,
|
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_SRC1_ALPHA,
|
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_DST_ALPHA,
|
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}};
|
|
||||||
static constexpr std::array<VkBlendFactor, 8> dst_factors = {
|
|
||||||
{VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_COLOR,
|
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_SRC1_ALPHA,
|
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_DST_ALPHA,
|
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}};
|
|
||||||
|
|
||||||
vk_state.srcColorBlendFactor = src_factors[u32(state.srcfactor.Value())];
|
|
||||||
vk_state.srcAlphaBlendFactor = src_factors[u32(state.srcfactoralpha.Value())];
|
|
||||||
vk_state.dstColorBlendFactor = dst_factors[u32(state.dstfactor.Value())];
|
|
||||||
vk_state.dstAlphaBlendFactor = dst_factors[u32(state.dstfactoralpha.Value())];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static constexpr std::array<VkBlendFactor, 8> src_factors = {
|
vk_state.blendEnable = static_cast<VkBool32>(state.blendenable);
|
||||||
{VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_DST_COLOR,
|
vk_state.colorBlendOp = state.subtract ? VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_ADD;
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_SRC_ALPHA,
|
vk_state.alphaBlendOp = state.subtractAlpha ? VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_ADD;
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA,
|
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}};
|
|
||||||
|
|
||||||
static constexpr std::array<VkBlendFactor, 8> dst_factors = {
|
if (use_dual_source)
|
||||||
{VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_COLOR,
|
{
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_SRC_ALPHA,
|
static constexpr std::array<VkBlendFactor, 8> src_factors = {
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA,
|
{VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_DST_COLOR,
|
||||||
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}};
|
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_SRC1_ALPHA,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_DST_ALPHA,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}};
|
||||||
|
static constexpr std::array<VkBlendFactor, 8> dst_factors = {
|
||||||
|
{VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_COLOR,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_SRC1_ALPHA,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_DST_ALPHA,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}};
|
||||||
|
|
||||||
vk_state.srcColorBlendFactor = src_factors[u32(state.srcfactor.Value())];
|
vk_state.srcColorBlendFactor = src_factors[u32(state.srcfactor.Value())];
|
||||||
vk_state.srcAlphaBlendFactor = src_factors[u32(state.srcfactoralpha.Value())];
|
vk_state.srcAlphaBlendFactor = src_factors[u32(state.srcfactoralpha.Value())];
|
||||||
vk_state.dstColorBlendFactor = dst_factors[u32(state.dstfactor.Value())];
|
vk_state.dstColorBlendFactor = dst_factors[u32(state.dstfactor.Value())];
|
||||||
vk_state.dstAlphaBlendFactor = dst_factors[u32(state.dstfactoralpha.Value())];
|
vk_state.dstAlphaBlendFactor = dst_factors[u32(state.dstfactoralpha.Value())];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static constexpr std::array<VkBlendFactor, 8> src_factors = {
|
||||||
|
{VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_DST_COLOR,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}};
|
||||||
|
|
||||||
|
static constexpr std::array<VkBlendFactor, 8> dst_factors = {
|
||||||
|
{VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_COLOR,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}};
|
||||||
|
|
||||||
|
vk_state.srcColorBlendFactor = src_factors[u32(state.srcfactor.Value())];
|
||||||
|
vk_state.srcAlphaBlendFactor = src_factors[u32(state.srcfactoralpha.Value())];
|
||||||
|
vk_state.dstColorBlendFactor = dst_factors[u32(state.dstfactor.Value())];
|
||||||
|
vk_state.dstAlphaBlendFactor = dst_factors[u32(state.dstfactoralpha.Value())];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.colorupdate)
|
if (state.colorupdate)
|
||||||
|
@ -338,7 +350,7 @@ std::unique_ptr<VKPipeline> VKPipeline::Create(const AbstractPipelineConfig& con
|
||||||
VkPipelineDepthStencilStateCreateInfo depth_stencil_state =
|
VkPipelineDepthStencilStateCreateInfo depth_stencil_state =
|
||||||
GetVulkanDepthStencilState(config.depth_state);
|
GetVulkanDepthStencilState(config.depth_state);
|
||||||
VkPipelineColorBlendAttachmentState blend_attachment_state =
|
VkPipelineColorBlendAttachmentState blend_attachment_state =
|
||||||
GetVulkanAttachmentBlendState(config.blending_state);
|
GetVulkanAttachmentBlendState(config.blending_state, config.usage);
|
||||||
VkPipelineColorBlendStateCreateInfo blend_state =
|
VkPipelineColorBlendStateCreateInfo blend_state =
|
||||||
GetVulkanColorBlendState(config.blending_state, &blend_attachment_state, 1);
|
GetVulkanColorBlendState(config.blending_state, &blend_attachment_state, 1);
|
||||||
|
|
||||||
|
|
|
@ -371,6 +371,13 @@ void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalD
|
||||||
// with depth clamping. Fall back to inverted depth range for these.
|
// with depth clamping. Fall back to inverted depth range for these.
|
||||||
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_REVERSED_DEPTH_RANGE))
|
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_REVERSED_DEPTH_RANGE))
|
||||||
config->backend_info.bSupportsReversedDepthRange = false;
|
config->backend_info.bSupportsReversedDepthRange = false;
|
||||||
|
|
||||||
|
// Calling discard when early depth test is enabled can break on some Apple Silicon GPU drivers.
|
||||||
|
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z))
|
||||||
|
{
|
||||||
|
// We will use shader blending, so disable hardware dual source blending.
|
||||||
|
config->backend_info.bSupportsDualSourceBlend = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanContext::PopulateBackendInfoMultisampleModes(
|
void VulkanContext::PopulateBackendInfoMultisampleModes(
|
||||||
|
@ -922,6 +929,11 @@ void VulkanContext::InitDriverDetails()
|
||||||
vendor = DriverDetails::VENDOR_IMGTEC;
|
vendor = DriverDetails::VENDOR_IMGTEC;
|
||||||
driver = DriverDetails::DRIVER_IMGTEC;
|
driver = DriverDetails::DRIVER_IMGTEC;
|
||||||
}
|
}
|
||||||
|
else if (device_name.find("Apple") != std::string::npos)
|
||||||
|
{
|
||||||
|
vendor = DriverDetails::VENDOR_APPLE;
|
||||||
|
driver = DriverDetails::DRIVER_PORTABILITY;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(VIDEO, "Unknown Vulkan driver vendor, please report it to us.");
|
WARN_LOG_FMT(VIDEO, "Unknown Vulkan driver vendor, please report it to us.");
|
||||||
|
|
|
@ -140,6 +140,8 @@ constexpr BugInfo m_known_bugs[] = {
|
||||||
-1.0, -1.0, true},
|
-1.0, -1.0, true},
|
||||||
{API_VULKAN, OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM, Family::UNKNOWN, BUG_PRIMITIVE_RESTART,
|
{API_VULKAN, OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM, Family::UNKNOWN, BUG_PRIMITIVE_RESTART,
|
||||||
-1.0, -1.0, true},
|
-1.0, -1.0, true},
|
||||||
|
{API_VULKAN, OS_OSX, VENDOR_APPLE, DRIVER_PORTABILITY, Family::UNKNOWN,
|
||||||
|
BUG_BROKEN_DISCARD_WITH_EARLY_Z, -1.0, -1.0, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::map<Bug, BugInfo> m_bugs;
|
static std::map<Bug, BugInfo> m_bugs;
|
||||||
|
|
|
@ -43,6 +43,7 @@ enum Vendor
|
||||||
VENDOR_TEGRA,
|
VENDOR_TEGRA,
|
||||||
VENDOR_VIVANTE,
|
VENDOR_VIVANTE,
|
||||||
VENDOR_MESA,
|
VENDOR_MESA,
|
||||||
|
VENDOR_APPLE,
|
||||||
VENDOR_UNKNOWN
|
VENDOR_UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -318,7 +319,15 @@ enum Bug
|
||||||
// BUG: Multi-threaded shader pre-compilation sometimes crashes
|
// BUG: Multi-threaded shader pre-compilation sometimes crashes
|
||||||
// Used primarily in Videoconfig.cpp's GetNumAutoShaderPreCompilerThreads()
|
// Used primarily in Videoconfig.cpp's GetNumAutoShaderPreCompilerThreads()
|
||||||
// refer to https://github.com/dolphin-emu/dolphin/pull/9414 for initial validation coverage
|
// refer to https://github.com/dolphin-emu/dolphin/pull/9414 for initial validation coverage
|
||||||
BUG_BROKEN_MULTITHREADED_SHADER_PRECOMPILATION
|
BUG_BROKEN_MULTITHREADED_SHADER_PRECOMPILATION,
|
||||||
|
|
||||||
|
// BUG: Some driver and Apple Silicon GPU combinations have problems with fragment discard when
|
||||||
|
// early depth test is enabled. Discarded fragments may appear corrupted (Super Mario Sunshine,
|
||||||
|
// Sonic Adventure 2: Battle, Phantasy Star Online Epsiodes 1 & 2, etc).
|
||||||
|
// Affected devices: Apple Silicon GPUs of Apple family 4 and newer.
|
||||||
|
// Started version: -1
|
||||||
|
// Ended version: -1
|
||||||
|
BUG_BROKEN_DISCARD_WITH_EARLY_Z,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initializes our internal vendor, device family, and driver version
|
// Initializes our internal vendor, device family, and driver version
|
||||||
|
|
|
@ -321,7 +321,9 @@ PixelShaderUid GetPixelShaderUid()
|
||||||
BlendingState state = {};
|
BlendingState state = {};
|
||||||
state.Generate(bpmem);
|
state.Generate(bpmem);
|
||||||
|
|
||||||
if (state.usedualsrc && state.dstalpha && g_ActiveConfig.backend_info.bSupportsFramebufferFetch &&
|
if (((state.usedualsrc && state.dstalpha) ||
|
||||||
|
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z)) &&
|
||||||
|
g_ActiveConfig.backend_info.bSupportsFramebufferFetch &&
|
||||||
!g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
|
!g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
|
||||||
{
|
{
|
||||||
uid_data->blend_enable = state.blendenable;
|
uid_data->blend_enable = state.blendenable;
|
||||||
|
@ -944,10 +946,15 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
|
||||||
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) ||
|
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) ||
|
||||||
uid_data->useDstAlpha);
|
uid_data->useDstAlpha);
|
||||||
const bool use_shader_blend =
|
const bool use_shader_blend =
|
||||||
!use_dual_source && uid_data->useDstAlpha && host_config.backend_shader_framebuffer_fetch;
|
!use_dual_source &&
|
||||||
|
(uid_data->useDstAlpha ||
|
||||||
|
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z)) &&
|
||||||
|
host_config.backend_shader_framebuffer_fetch;
|
||||||
const bool use_shader_logic_op = !host_config.backend_logic_op && uid_data->logic_op_enable &&
|
const bool use_shader_logic_op = !host_config.backend_logic_op && uid_data->logic_op_enable &&
|
||||||
host_config.backend_shader_framebuffer_fetch;
|
host_config.backend_shader_framebuffer_fetch;
|
||||||
const bool use_framebuffer_fetch = use_shader_blend || use_shader_logic_op;
|
const bool use_framebuffer_fetch =
|
||||||
|
use_shader_blend || use_shader_logic_op ||
|
||||||
|
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z);
|
||||||
|
|
||||||
if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
|
if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
|
@ -1869,9 +1876,23 @@ static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_dat
|
||||||
// ZCOMPLOC HACK:
|
// ZCOMPLOC HACK:
|
||||||
if (!uid_data->alpha_test_use_zcomploc_hack)
|
if (!uid_data->alpha_test_use_zcomploc_hack)
|
||||||
{
|
{
|
||||||
out.Write("\t\tdiscard;\n");
|
#ifdef __APPLE__
|
||||||
if (api_type == APIType::D3D)
|
if (uid_data->forced_early_z &&
|
||||||
|
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z))
|
||||||
|
{
|
||||||
|
// Instead of using discard, fetch the framebuffer's color value and use it as the output
|
||||||
|
// for this fragment.
|
||||||
|
out.Write("\t\t{} = float4(initial_ocol0.xyz, 1.0);\n",
|
||||||
|
use_dual_source ? "real_ocol0" : "ocol0");
|
||||||
out.Write("\t\treturn;\n");
|
out.Write("\t\treturn;\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
out.Write("\t\tdiscard;\n");
|
||||||
|
if (api_type == APIType::D3D)
|
||||||
|
out.Write("\t\treturn;\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write("\t}}\n");
|
out.Write("\t}}\n");
|
||||||
|
@ -2018,8 +2039,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
"float3(1,1,1);", // ONE
|
"float3(1,1,1);", // ONE
|
||||||
"initial_ocol0.rgb;", // DSTCLR
|
"initial_ocol0.rgb;", // DSTCLR
|
||||||
"float3(1,1,1) - initial_ocol0.rgb;", // INVDSTCLR
|
"float3(1,1,1) - initial_ocol0.rgb;", // INVDSTCLR
|
||||||
"ocol1.aaa;", // SRCALPHA
|
"src_color.aaa;", // SRCALPHA
|
||||||
"float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA
|
"float3(1,1,1) - src_color.aaa;", // INVSRCALPHA
|
||||||
"initial_ocol0.aaa;", // DSTALPHA
|
"initial_ocol0.aaa;", // DSTALPHA
|
||||||
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
||||||
};
|
};
|
||||||
|
@ -2028,8 +2049,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
"1.0;", // ONE
|
"1.0;", // ONE
|
||||||
"initial_ocol0.a;", // DSTCLR
|
"initial_ocol0.a;", // DSTCLR
|
||||||
"1.0 - initial_ocol0.a;", // INVDSTCLR
|
"1.0 - initial_ocol0.a;", // INVDSTCLR
|
||||||
"ocol1.a;", // SRCALPHA
|
"src_color.a;", // SRCALPHA
|
||||||
"1.0 - ocol1.a;", // INVSRCALPHA
|
"1.0 - src_color.a;", // INVSRCALPHA
|
||||||
"initial_ocol0.a;", // DSTALPHA
|
"initial_ocol0.a;", // DSTALPHA
|
||||||
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
||||||
};
|
};
|
||||||
|
@ -2038,8 +2059,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
"float3(1,1,1);", // ONE
|
"float3(1,1,1);", // ONE
|
||||||
"ocol0.rgb;", // SRCCLR
|
"ocol0.rgb;", // SRCCLR
|
||||||
"float3(1,1,1) - ocol0.rgb;", // INVSRCCLR
|
"float3(1,1,1) - ocol0.rgb;", // INVSRCCLR
|
||||||
"ocol1.aaa;", // SRCALHA
|
"src_color.aaa;", // SRCALHA
|
||||||
"float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA
|
"float3(1,1,1) - src_color.aaa;", // INVSRCALPHA
|
||||||
"initial_ocol0.aaa;", // DSTALPHA
|
"initial_ocol0.aaa;", // DSTALPHA
|
||||||
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
||||||
};
|
};
|
||||||
|
@ -2048,12 +2069,14 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
"1.0;", // ONE
|
"1.0;", // ONE
|
||||||
"ocol0.a;", // SRCCLR
|
"ocol0.a;", // SRCCLR
|
||||||
"1.0 - ocol0.a;", // INVSRCCLR
|
"1.0 - ocol0.a;", // INVSRCCLR
|
||||||
"ocol1.a;", // SRCALPHA
|
"src_color.a;", // SRCALPHA
|
||||||
"1.0 - ocol1.a;", // INVSRCALPHA
|
"1.0 - src_color.a;", // INVSRCALPHA
|
||||||
"initial_ocol0.a;", // DSTALPHA
|
"initial_ocol0.a;", // DSTALPHA
|
||||||
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
||||||
};
|
};
|
||||||
out.Write("\tfloat4 blend_src;\n");
|
out.Write("\tfloat4 src_color = {};\n"
|
||||||
|
"\tfloat4 blend_src;",
|
||||||
|
uid_data->useDstAlpha ? "ocol1" : "ocol0");
|
||||||
out.Write("\tblend_src.rgb = {}\n", blend_src_factor[uid_data->blend_src_factor]);
|
out.Write("\tblend_src.rgb = {}\n", blend_src_factor[uid_data->blend_src_factor]);
|
||||||
out.Write("\tblend_src.a = {}\n", blend_src_factor_alpha[uid_data->blend_src_factor_alpha]);
|
out.Write("\tblend_src.a = {}\n", blend_src_factor_alpha[uid_data->blend_src_factor_alpha]);
|
||||||
out.Write("\tfloat4 blend_dst;\n");
|
out.Write("\tfloat4 blend_dst;\n");
|
||||||
|
|
|
@ -57,7 +57,9 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
||||||
const bool use_shader_blend = !use_dual_source && host_config.backend_shader_framebuffer_fetch;
|
const bool use_shader_blend = !use_dual_source && host_config.backend_shader_framebuffer_fetch;
|
||||||
const bool use_shader_logic_op =
|
const bool use_shader_logic_op =
|
||||||
!host_config.backend_logic_op && host_config.backend_shader_framebuffer_fetch;
|
!host_config.backend_logic_op && host_config.backend_shader_framebuffer_fetch;
|
||||||
const bool use_framebuffer_fetch = use_shader_blend || use_shader_logic_op;
|
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;
|
||||||
|
@ -1007,8 +1009,21 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
||||||
out.Write(" depth = float(zbuffer_zCoord) / 16777216.0;\n");
|
out.Write(" depth = float(zbuffer_zCoord) / 16777216.0;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write(" // Alpha Test\n"
|
out.Write(" // Alpha Test\n");
|
||||||
" if (bpmem_alphaTest != 0u) {{\n"
|
|
||||||
|
if (early_depth && DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z))
|
||||||
|
{
|
||||||
|
// Instead of using discard, fetch the framebuffer's color value and use it as the output
|
||||||
|
// for this fragment.
|
||||||
|
out.Write(" #define discard_fragment {{ {} = float4(initial_ocol0.xyz, 1.0); return; }}\n",
|
||||||
|
use_shader_blend ? "real_ocol0" : "ocol0");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.Write(" #define discard_fragment discard\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
out.Write(" if (bpmem_alphaTest != 0u) {{\n"
|
||||||
" bool comp0 = alphaCompare(TevResult.a, " I_ALPHA ".r, {});\n",
|
" bool comp0 = alphaCompare(TevResult.a, " I_ALPHA ".r, {});\n",
|
||||||
BitfieldExtract<&AlphaTest::comp0>("bpmem_alphaTest"));
|
BitfieldExtract<&AlphaTest::comp0>("bpmem_alphaTest"));
|
||||||
out.Write(" bool comp1 = alphaCompare(TevResult.a, " I_ALPHA ".g, {});\n",
|
out.Write(" bool comp1 = alphaCompare(TevResult.a, " I_ALPHA ".g, {});\n",
|
||||||
|
@ -1019,13 +1034,13 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
||||||
" switch ({}) {{\n",
|
" switch ({}) {{\n",
|
||||||
BitfieldExtract<&AlphaTest::logic>("bpmem_alphaTest"));
|
BitfieldExtract<&AlphaTest::logic>("bpmem_alphaTest"));
|
||||||
out.Write(" case 0u: // AND\n"
|
out.Write(" case 0u: // AND\n"
|
||||||
" if (comp0 && comp1) break; else discard; break;\n"
|
" if (comp0 && comp1) break; else discard_fragment; break;\n"
|
||||||
" case 1u: // OR\n"
|
" case 1u: // OR\n"
|
||||||
" if (comp0 || comp1) break; else discard; break;\n"
|
" if (comp0 || comp1) break; else discard_fragment; break;\n"
|
||||||
" case 2u: // XOR\n"
|
" case 2u: // XOR\n"
|
||||||
" if (comp0 != comp1) break; else discard; break;\n"
|
" if (comp0 != comp1) break; else discard_fragment; break;\n"
|
||||||
" case 3u: // XNOR\n"
|
" case 3u: // XNOR\n"
|
||||||
" if (comp0 == comp1) break; else discard; break;\n"
|
" if (comp0 == comp1) break; else discard_fragment; break;\n"
|
||||||
" }}\n"
|
" }}\n"
|
||||||
" }}\n"
|
" }}\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
@ -1194,8 +1209,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
||||||
"blend_src.rgb = float3(1,1,1);", // ONE
|
"blend_src.rgb = float3(1,1,1);", // ONE
|
||||||
"blend_src.rgb = initial_ocol0.rgb;", // DSTCLR
|
"blend_src.rgb = initial_ocol0.rgb;", // DSTCLR
|
||||||
"blend_src.rgb = float3(1,1,1) - initial_ocol0.rgb;", // INVDSTCLR
|
"blend_src.rgb = float3(1,1,1) - initial_ocol0.rgb;", // INVDSTCLR
|
||||||
"blend_src.rgb = ocol1.aaa;", // SRCALPHA
|
"blend_src.rgb = src_color.aaa;", // SRCALPHA
|
||||||
"blend_src.rgb = float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA
|
"blend_src.rgb = float3(1,1,1) - src_color.aaa;", // INVSRCALPHA
|
||||||
"blend_src.rgb = initial_ocol0.aaa;", // DSTALPHA
|
"blend_src.rgb = initial_ocol0.aaa;", // DSTALPHA
|
||||||
"blend_src.rgb = float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
"blend_src.rgb = float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
||||||
};
|
};
|
||||||
|
@ -1204,8 +1219,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
||||||
"blend_src.a = 1.0;", // ONE
|
"blend_src.a = 1.0;", // ONE
|
||||||
"blend_src.a = initial_ocol0.a;", // DSTCLR
|
"blend_src.a = initial_ocol0.a;", // DSTCLR
|
||||||
"blend_src.a = 1.0 - initial_ocol0.a;", // INVDSTCLR
|
"blend_src.a = 1.0 - initial_ocol0.a;", // INVDSTCLR
|
||||||
"blend_src.a = ocol1.a;", // SRCALPHA
|
"blend_src.a = src_color.a;", // SRCALPHA
|
||||||
"blend_src.a = 1.0 - ocol1.a;", // INVSRCALPHA
|
"blend_src.a = 1.0 - src_color.a;", // INVSRCALPHA
|
||||||
"blend_src.a = initial_ocol0.a;", // DSTALPHA
|
"blend_src.a = initial_ocol0.a;", // DSTALPHA
|
||||||
"blend_src.a = 1.0 - initial_ocol0.a;", // INVDSTALPHA
|
"blend_src.a = 1.0 - initial_ocol0.a;", // INVDSTALPHA
|
||||||
};
|
};
|
||||||
|
@ -1214,8 +1229,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
||||||
"blend_dst.rgb = float3(1,1,1);", // ONE
|
"blend_dst.rgb = float3(1,1,1);", // ONE
|
||||||
"blend_dst.rgb = ocol0.rgb;", // SRCCLR
|
"blend_dst.rgb = ocol0.rgb;", // SRCCLR
|
||||||
"blend_dst.rgb = float3(1,1,1) - ocol0.rgb;", // INVSRCCLR
|
"blend_dst.rgb = float3(1,1,1) - ocol0.rgb;", // INVSRCCLR
|
||||||
"blend_dst.rgb = ocol1.aaa;", // SRCALHA
|
"blend_dst.rgb = src_color.aaa;", // SRCALHA
|
||||||
"blend_dst.rgb = float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA
|
"blend_dst.rgb = float3(1,1,1) - src_color.aaa;", // INVSRCALPHA
|
||||||
"blend_dst.rgb = initial_ocol0.aaa;", // DSTALPHA
|
"blend_dst.rgb = initial_ocol0.aaa;", // DSTALPHA
|
||||||
"blend_dst.rgb = float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
"blend_dst.rgb = float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
||||||
};
|
};
|
||||||
|
@ -1224,13 +1239,19 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
||||||
"blend_dst.a = 1.0;", // ONE
|
"blend_dst.a = 1.0;", // ONE
|
||||||
"blend_dst.a = ocol0.a;", // SRCCLR
|
"blend_dst.a = ocol0.a;", // SRCCLR
|
||||||
"blend_dst.a = 1.0 - ocol0.a;", // INVSRCCLR
|
"blend_dst.a = 1.0 - ocol0.a;", // INVSRCCLR
|
||||||
"blend_dst.a = ocol1.a;", // SRCALPHA
|
"blend_dst.a = src_color.a;", // SRCALPHA
|
||||||
"blend_dst.a = 1.0 - ocol1.a;", // INVSRCALPHA
|
"blend_dst.a = 1.0 - src_color.a;", // INVSRCALPHA
|
||||||
"blend_dst.a = initial_ocol0.a;", // DSTALPHA
|
"blend_dst.a = initial_ocol0.a;", // DSTALPHA
|
||||||
"blend_dst.a = 1.0 - initial_ocol0.a;", // INVDSTALPHA
|
"blend_dst.a = 1.0 - initial_ocol0.a;", // INVDSTALPHA
|
||||||
};
|
};
|
||||||
|
|
||||||
out.Write(" if (blend_enable) {{\n"
|
out.Write(" if (blend_enable) {{\n"
|
||||||
|
" float4 src_color;\n"
|
||||||
|
" if (bpmem_dstalpha != 0u) {{\n"
|
||||||
|
" src_color = ocol1;\n"
|
||||||
|
" }} else {{\n"
|
||||||
|
" src_color = ocol0;\n"
|
||||||
|
" }}"
|
||||||
" float4 blend_src;\n");
|
" float4 blend_src;\n");
|
||||||
WriteSwitch(out, api_type, "blend_src_factor", blendSrcFactor, 4, true);
|
WriteSwitch(out, api_type, "blend_src_factor", blendSrcFactor, 4, true);
|
||||||
WriteSwitch(out, api_type, "blend_src_factor_alpha", blendSrcFactorAlpha, 4, true);
|
WriteSwitch(out, api_type, "blend_src_factor_alpha", blendSrcFactorAlpha, 4, true);
|
||||||
|
|
Loading…
Reference in New Issue