GPU/HW: Fix mask bit when rendering with transparency and no DSB

Fixes some sprites in Bloody Roar on Mali GPUs.
This commit is contained in:
Connor McLaughlin 2021-02-06 20:05:57 +10:00
parent 011df33fc4
commit 837fb6128b
6 changed files with 69 additions and 48 deletions

View File

@ -1168,7 +1168,7 @@ void GPU_HW::FlushRender()
m_batch_ubo_dirty = false;
}
if (m_batch.NeedsTwoPassRendering())
if (NeedsTwoPassRendering())
{
m_renderer_stats.num_batches += 2;
DrawBatchVertices(BatchRenderMode::OnlyOpaque, m_batch_base_vertex, vertex_count);

View File

@ -102,14 +102,6 @@ protected:
bool check_mask_before_draw;
bool use_depth_buffer;
// We need two-pass rendering when using BG-FG blending and texturing, as the transparency can be enabled
// on a per-pixel basis, and the opaque pixels shouldn't be blended at all.
bool NeedsTwoPassRendering() const
{
return transparency_mode == GPUTransparencyMode::BackgroundMinusForeground &&
texture_mode != GPUTextureMode::Disabled;
}
// Returns the render mode for this batch.
BatchRenderMode GetRenderMode() const
{
@ -254,6 +246,15 @@ protected:
return true;
}
/// We need two-pass rendering when using BG-FG blending and texturing, as the transparency can be enabled
/// on a per-pixel basis, and the opaque pixels shouldn't be blended at all.
bool NeedsTwoPassRendering() const
{
return (m_batch.transparency_mode == GPUTransparencyMode::BackgroundMinusForeground &&
m_batch.texture_mode != GPUTextureMode::Disabled) ||
(m_batch.transparency_mode != GPUTransparencyMode::Disabled && !m_supports_dual_source_blend);
}
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override;
void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override;

View File

@ -361,8 +361,6 @@ void GPU_HW_OpenGL::SetCapabilities(HostDisplay* host_display)
m_supports_dual_source_blend =
(max_dual_source_draw_buffers > 0) &&
(GLAD_GL_VERSION_3_3 || GLAD_GL_ARB_blend_func_extended || GLAD_GL_EXT_blend_func_extended);
if (!m_supports_dual_source_blend)
Log_WarningPrintf("Dual-source blending is not supported, this may break some mask effects.");
m_supports_geometry_shaders =
GLAD_GL_VERSION_3_2 || GLAD_GL_ARB_geometry_shader4 || GLAD_GL_OES_geometry_shader || GLAD_GL_ES_VERSION_3_2;
@ -754,9 +752,19 @@ void GPU_HW_OpenGL::SetBlendMode()
GL_FUNC_REVERSE_SUBTRACT :
GL_FUNC_ADD,
GL_FUNC_ADD);
if (m_supports_dual_source_blend)
{
glBlendFuncSeparate(GL_ONE, m_supports_dual_source_blend ? GL_SRC1_ALPHA : GL_SRC_ALPHA, GL_ONE, GL_ZERO);
}
else
{
const float factor =
(m_current_transparency_mode == GPUTransparencyMode::HalfBackgroundPlusHalfForeground) ? 0.5f : 1.0f;
glBlendFuncSeparate(GL_ONE, GL_CONSTANT_ALPHA, GL_ONE, GL_ZERO);
glBlendColor(0.0f, 0.0f, 0.0f, factor);
}
}
else
{
glDisable(GL_BLEND);
}

View File

@ -939,12 +939,12 @@ float4 SampleFromVRAM(uint4 texpage, float2 coords)
o_col0 = float4(color, oalpha);
o_col1 = float4(0.0, 0.0, 0.0, u_dst_alpha_factor / ialpha);
#else
o_col0 = float4(color, u_dst_alpha_factor / ialpha);
o_col0 = float4(color, oalpha);
#endif
#if !PGXP_DEPTH
#if !PGXP_DEPTH
o_depth = oalpha * v_pos.z;
#endif
#endif
}
else
{
@ -952,24 +952,16 @@ float4 SampleFromVRAM(uint4 texpage, float2 coords)
discard;
#endif
#if TRANSPARENCY_ONLY_OPAQUE
// We don't output the second color here because it's not used (except for filtering).
o_col0 = float4(color, oalpha);
#if USE_DUAL_SOURCE
o_col1 = float4(0.0, 0.0, 0.0, 1.0 - ialpha);
#endif
#else
#if USE_DUAL_SOURCE
o_col0 = float4(color, oalpha);
o_col1 = float4(0.0, 0.0, 0.0, 1.0 - ialpha);
#else
o_col0 = float4(color, 1.0 - ialpha);
#endif
o_col0 = float4(color, oalpha);
#endif
#if !PGXP_DEPTH
#if !PGXP_DEPTH
o_depth = oalpha * v_pos.z;
#endif
#endif
}
#else
// Non-transparency won't enable blending so we can write the mask here regardless.
@ -979,9 +971,9 @@ float4 SampleFromVRAM(uint4 texpage, float2 coords)
o_col1 = float4(0.0, 0.0, 0.0, 1.0 - ialpha);
#endif
#if !PGXP_DEPTH
#if !PGXP_DEPTH
o_depth = oalpha * v_pos.z;
#endif
#endif
#endif
}
)";

View File

@ -174,7 +174,8 @@ void GPU_HW_Vulkan::ResetGraphicsAPIState()
EndRenderPass();
if (m_host_display->GetDisplayTextureHandle() == &m_vram_texture)
m_vram_texture.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_vram_texture.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
void GPU_HW_Vulkan::RestoreGraphicsAPIState()
@ -522,9 +523,9 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
!m_vram_read_texture.Create(texture_width, texture_height, 1, 1, texture_format, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) ||
!m_display_texture.Create(GPU_MAX_DISPLAY_WIDTH * m_resolution_scale,
GPU_MAX_DISPLAY_HEIGHT * m_resolution_scale, 1, 1, texture_format,
VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
!m_display_texture.Create(GPU_MAX_DISPLAY_WIDTH * m_resolution_scale, GPU_MAX_DISPLAY_HEIGHT * m_resolution_scale,
1, 1, texture_format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) ||
!m_vram_readback_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, 1, 1, texture_format, VK_SAMPLE_COUNT_1_BIT,
@ -923,10 +924,11 @@ bool GPU_HW_Vulkan::CompilePipelines()
(static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque)) ||
m_texture_filtering != GPUTextureFilter::Nearest)
{
if (m_supports_dual_source_blend)
{
gpbuilder.SetBlendAttachment(
0, true, VK_BLEND_FACTOR_ONE,
m_supports_dual_source_blend ? VK_BLEND_FACTOR_SRC1_ALPHA : VK_BLEND_FACTOR_SRC_ALPHA,
0, true, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC1_ALPHA,
(static_cast<GPUTransparencyMode>(transparency_mode) ==
GPUTransparencyMode::BackgroundMinusForeground &&
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
@ -935,6 +937,24 @@ bool GPU_HW_Vulkan::CompilePipelines()
VK_BLEND_OP_ADD,
VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD);
}
else
{
const float factor = (static_cast<GPUTransparencyMode>(transparency_mode) ==
GPUTransparencyMode::HalfBackgroundPlusHalfForeground) ?
0.5f :
1.0f;
gpbuilder.SetBlendAttachment(
0, true, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_CONSTANT_ALPHA,
(static_cast<GPUTransparencyMode>(transparency_mode) ==
GPUTransparencyMode::BackgroundMinusForeground &&
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque) ?
VK_BLEND_OP_REVERSE_SUBTRACT :
VK_BLEND_OP_ADD,
VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD);
gpbuilder.SetBlendConstants(0.0f, 0.0f, 0.0f, factor);
}
}
gpbuilder.SetDynamicViewportAndScissorState();

View File

@ -1,4 +1,4 @@
#pragma once
#include "types.h"
static constexpr u32 SHADER_CACHE_VERSION = 1;
static constexpr u32 SHADER_CACHE_VERSION = 2;