Merge pull request #4577 from degasus/videocommon

OGL/Vulkan: Drop destination alpha pass.
This commit is contained in:
Markus Wick 2017-01-04 20:05:26 +01:00 committed by GitHub
commit 389f8297c3
33 changed files with 79 additions and 202 deletions

View File

@ -551,9 +551,9 @@ void PixelShaderCache::Shutdown()
g_ps_disk_cache.Close(); g_ps_disk_cache.Close();
} }
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode) bool PixelShaderCache::SetShader()
{ {
PixelShaderUid uid = GetPixelShaderUid(dstAlphaMode); PixelShaderUid uid = GetPixelShaderUid();
// Check if the shader is already set // Check if the shader is already set
if (last_entry) if (last_entry)

View File

@ -9,8 +9,6 @@
#include "VideoCommon/PixelShaderGen.h" #include "VideoCommon/PixelShaderGen.h"
enum DSTALPHA_MODE;
namespace DX11 namespace DX11
{ {
class PixelShaderCache class PixelShaderCache
@ -19,7 +17,7 @@ public:
static void Init(); static void Init();
static void Clear(); static void Clear();
static void Shutdown(); static void Shutdown();
static bool SetShader(DSTALPHA_MODE dstAlphaMode); // TODO: Should be renamed to LoadShader static bool SetShader(); // TODO: Should be renamed to LoadShader
static bool InsertByteCode(const PixelShaderUid& uid, const void* bytecode, static bool InsertByteCode(const PixelShaderUid& uid, const void* bytecode,
unsigned int bytecodelen); unsigned int bytecodelen);

View File

@ -940,8 +940,12 @@ void Renderer::RestoreAPIState()
BPFunctions::SetScissor(); BPFunctions::SetScissor();
} }
void Renderer::ApplyState(bool bUseDstAlpha) void Renderer::ApplyState()
{ {
// TODO: Refactor this logic here.
bool bUseDstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
gx_state.blend.use_dst_alpha = bUseDstAlpha; gx_state.blend.use_dst_alpha = bUseDstAlpha;
D3D::stateman->PushBlendState(gx_state_cache.Get(gx_state.blend)); D3D::stateman->PushBlendState(gx_state_cache.Get(gx_state.blend));
D3D::stateman->PushDepthState(gx_state_cache.Get(gx_state.zmode)); D3D::stateman->PushDepthState(gx_state_cache.Get(gx_state.zmode));

View File

@ -29,7 +29,7 @@ public:
bool IsFullscreen() const override; bool IsFullscreen() const override;
// TODO: Fix confusing names (see ResetAPIState and RestoreAPIState) // TODO: Fix confusing names (see ResetAPIState and RestoreAPIState)
void ApplyState(bool bUseDstAlpha) override; void ApplyState() override;
void RestoreState() override; void RestoreState() override;
void ApplyCullDisable(); void ApplyCullDisable();

View File

@ -147,9 +147,9 @@ void VertexManager::Draw(u32 stride)
static_cast<Renderer*>(g_renderer.get())->RestoreCull(); static_cast<Renderer*>(g_renderer.get())->RestoreCull();
} }
void VertexManager::vFlush(bool useDstAlpha) void VertexManager::vFlush()
{ {
if (!PixelShaderCache::SetShader(useDstAlpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE)) if (!PixelShaderCache::SetShader())
{ {
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR, true, { printf("Fail to set pixel shader\n"); }); GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR, true, { printf("Fail to set pixel shader\n"); });
return; return;
@ -179,7 +179,7 @@ void VertexManager::vFlush(bool useDstAlpha)
PrepareDrawBuffers(stride); PrepareDrawBuffers(stride);
VertexLoaderManager::GetCurrentVertexFormat()->SetupVertexPointers(); VertexLoaderManager::GetCurrentVertexFormat()->SetupVertexPointers();
g_renderer->ApplyState(useDstAlpha); g_renderer->ApplyState();
Draw(stride); Draw(stride);

View File

@ -25,7 +25,7 @@ private:
void PrepareDrawBuffers(u32 stride); void PrepareDrawBuffers(u32 stride);
void Draw(u32 stride); void Draw(u32 stride);
// temp // temp
void vFlush(bool useDstAlpha) override; void vFlush() override;
u32 m_vertexDrawOffset; u32 m_vertexDrawOffset;
u32 m_indexDrawOffset; u32 m_indexDrawOffset;

View File

@ -920,8 +920,12 @@ void Renderer::RestoreAPIState()
static bool s_previous_use_dst_alpha = false; static bool s_previous_use_dst_alpha = false;
static D3DVertexFormat* s_previous_vertex_format = nullptr; static D3DVertexFormat* s_previous_vertex_format = nullptr;
void Renderer::ApplyState(bool use_dst_alpha) void Renderer::ApplyState()
{ {
// TODO: Refactor this logic here.
bool use_dst_alpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
if (use_dst_alpha != s_previous_use_dst_alpha) if (use_dst_alpha != s_previous_use_dst_alpha)
{ {
s_previous_use_dst_alpha = use_dst_alpha; s_previous_use_dst_alpha = use_dst_alpha;

View File

@ -27,7 +27,7 @@ public:
void SetViewport() override; void SetViewport() override;
// TODO: Fix confusing names (see ResetAPIState and RestoreAPIState) // TODO: Fix confusing names (see ResetAPIState and RestoreAPIState)
void ApplyState(bool use_dst_alpha) override; void ApplyState() override;
void RestoreState() override; void RestoreState() override;
void ApplyCullDisable(); void ApplyCullDisable();

View File

@ -132,12 +132,12 @@ void ShaderCache::Shutdown()
s_vs_disk_cache.Close(); s_vs_disk_cache.Close();
} }
void ShaderCache::LoadAndSetActiveShaders(DSTALPHA_MODE ps_dst_alpha_mode, u32 gs_primitive_type) void ShaderCache::LoadAndSetActiveShaders(u32 gs_primitive_type)
{ {
SetCurrentPrimitiveTopology(gs_primitive_type); SetCurrentPrimitiveTopology(gs_primitive_type);
GeometryShaderUid gs_uid = GetGeometryShaderUid(gs_primitive_type); GeometryShaderUid gs_uid = GetGeometryShaderUid(gs_primitive_type);
PixelShaderUid ps_uid = GetPixelShaderUid(ps_dst_alpha_mode); PixelShaderUid ps_uid = GetPixelShaderUid();
VertexShaderUid vs_uid = GetVertexShaderUid(); VertexShaderUid vs_uid = GetVertexShaderUid();
bool gs_changed = gs_uid != s_last_geometry_shader_uid; bool gs_changed = gs_uid != s_last_geometry_shader_uid;
@ -156,7 +156,7 @@ void ShaderCache::LoadAndSetActiveShaders(DSTALPHA_MODE ps_dst_alpha_mode, u32 g
if (ps_changed) if (ps_changed)
{ {
HandlePSUIDChange(ps_uid, ps_dst_alpha_mode); HandlePSUIDChange(ps_uid);
} }
if (vs_changed) if (vs_changed)
@ -219,7 +219,7 @@ void ShaderCache::HandleGSUIDChange(GeometryShaderUid gs_uid, u32 gs_primitive_t
} }
} }
void ShaderCache::HandlePSUIDChange(PixelShaderUid ps_uid, DSTALPHA_MODE ps_dst_alpha_mode) void ShaderCache::HandlePSUIDChange(PixelShaderUid ps_uid)
{ {
s_last_pixel_shader_uid = ps_uid; s_last_pixel_shader_uid = ps_uid;

View File

@ -19,7 +19,7 @@ public:
static void Clear(); static void Clear();
static void Shutdown(); static void Shutdown();
static void LoadAndSetActiveShaders(DSTALPHA_MODE ps_dst_alpha_mode, u32 gs_primitive_type); static void LoadAndSetActiveShaders(u32 gs_primitive_type);
template <class UidType, class ShaderCacheType> template <class UidType, class ShaderCacheType>
static D3D12_SHADER_BYTECODE InsertByteCode(const UidType& uid, ShaderCacheType* shader_cache, static D3D12_SHADER_BYTECODE InsertByteCode(const UidType& uid, ShaderCacheType* shader_cache,
@ -43,7 +43,7 @@ private:
static void SetCurrentPrimitiveTopology(u32 gs_primitive_type); static void SetCurrentPrimitiveTopology(u32 gs_primitive_type);
static void HandleGSUIDChange(GeometryShaderUid gs_uid, u32 gs_primitive_type); static void HandleGSUIDChange(GeometryShaderUid gs_uid, u32 gs_primitive_type);
static void HandlePSUIDChange(PixelShaderUid ps_uid, DSTALPHA_MODE ps_dst_alpha_mode); static void HandlePSUIDChange(PixelShaderUid ps_uid);
static void HandleVSUIDChange(VertexShaderUid vs_uid); static void HandleVSUIDChange(VertexShaderUid vs_uid);
}; };
} }

View File

@ -135,10 +135,9 @@ void VertexManager::Draw(u32 stride)
INCSTAT(stats.thisFrame.numDrawCalls); INCSTAT(stats.thisFrame.numDrawCalls);
} }
void VertexManager::vFlush(bool use_dst_alpha) void VertexManager::vFlush()
{ {
ShaderCache::LoadAndSetActiveShaders(use_dst_alpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, ShaderCache::LoadAndSetActiveShaders(m_current_primitive_type);
m_current_primitive_type);
if (g_ActiveConfig.backend_info.bSupportsBBox && BoundingBox::active) if (g_ActiveConfig.backend_info.bSupportsBBox && BoundingBox::active)
BBox::Invalidate(); BBox::Invalidate();
@ -147,7 +146,7 @@ void VertexManager::vFlush(bool use_dst_alpha)
PrepareDrawBuffers(stride); PrepareDrawBuffers(stride);
g_renderer->ApplyState(use_dst_alpha); g_renderer->ApplyState();
Draw(stride); Draw(stride);

View File

@ -29,7 +29,7 @@ protected:
private: private:
void PrepareDrawBuffers(u32 stride); void PrepareDrawBuffers(u32 stride);
void Draw(u32 stride); void Draw(u32 stride);
void vFlush(bool use_dst_alpha) override; void vFlush() override;
u32 m_vertex_draw_offset; u32 m_vertex_draw_offset;
u32 m_index_draw_offset; u32 m_index_draw_offset;

View File

@ -33,9 +33,9 @@ void ShaderCache<Uid>::Clear()
} }
template <typename Uid> template <typename Uid>
bool ShaderCache<Uid>::SetShader(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type) bool ShaderCache<Uid>::SetShader(u32 primitive_type)
{ {
Uid uid = GetUid(dst_alpha_mode, primitive_type, APIType::OpenGL); Uid uid = GetUid(primitive_type, APIType::OpenGL);
// Check if the shader is already set // Check if the shader is already set
if (m_last_entry) if (m_last_entry)

View File

@ -22,10 +22,10 @@ public:
virtual ~ShaderCache(); virtual ~ShaderCache();
void Clear(); void Clear();
bool SetShader(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type); bool SetShader(u32 primitive_type);
protected: protected:
virtual Uid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, APIType api_type) = 0; virtual Uid GetUid(u32 primitive_type, APIType api_type) = 0;
virtual ShaderCode GenerateCode(APIType api_type, Uid uid) = 0; virtual ShaderCode GenerateCode(APIType api_type, Uid uid) = 0;
private: private:
@ -40,8 +40,7 @@ public:
static std::unique_ptr<VertexShaderCache> s_instance; static std::unique_ptr<VertexShaderCache> s_instance;
protected: protected:
VertexShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, VertexShaderUid GetUid(u32 primitive_type, APIType api_type) override
APIType api_type) override
{ {
return GetVertexShaderUid(); return GetVertexShaderUid();
} }
@ -57,8 +56,7 @@ public:
static std::unique_ptr<GeometryShaderCache> s_instance; static std::unique_ptr<GeometryShaderCache> s_instance;
protected: protected:
GeometryShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, GeometryShaderUid GetUid(u32 primitive_type, APIType api_type) override
APIType api_type) override
{ {
return GetGeometryShaderUid(primitive_type); return GetGeometryShaderUid(primitive_type);
} }
@ -74,9 +72,9 @@ public:
static std::unique_ptr<PixelShaderCache> s_instance; static std::unique_ptr<PixelShaderCache> s_instance;
protected: protected:
PixelShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, APIType api_type) override PixelShaderUid GetUid(u32 primitive_type, APIType api_type) override
{ {
return GetPixelShaderUid(dst_alpha_mode); return GetPixelShaderUid();
} }
ShaderCode GenerateCode(APIType api_type, PixelShaderUid uid) override ShaderCode GenerateCode(APIType api_type, PixelShaderUid uid) override
{ {

View File

@ -40,14 +40,11 @@ void VertexManager::ResetBuffer(u32 stride)
IndexGenerator::Start(&m_local_i_buffer[0]); IndexGenerator::Start(&m_local_i_buffer[0]);
} }
void VertexManager::vFlush(bool use_dst_alpha) void VertexManager::vFlush()
{ {
VertexShaderCache::s_instance->SetShader( VertexShaderCache::s_instance->SetShader(m_current_primitive_type);
use_dst_alpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, m_current_primitive_type); GeometryShaderCache::s_instance->SetShader(m_current_primitive_type);
GeometryShaderCache::s_instance->SetShader( PixelShaderCache::s_instance->SetShader(m_current_primitive_type);
use_dst_alpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, m_current_primitive_type);
PixelShaderCache::s_instance->SetShader(
use_dst_alpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, m_current_primitive_type);
} }
} // namespace } // namespace

View File

@ -21,7 +21,7 @@ protected:
void ResetBuffer(u32 stride) override; void ResetBuffer(u32 stride) override;
private: private:
void vFlush(bool use_dst_alpha) override; void vFlush() override;
std::vector<u8> m_local_v_buffer; std::vector<u8> m_local_v_buffer;
std::vector<u16> m_local_i_buffer; std::vector<u16> m_local_i_buffer;
}; };

View File

@ -174,10 +174,10 @@ void ProgramShaderCache::UploadConstants()
} }
} }
SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 primitive_type) SHADER* ProgramShaderCache::SetShader(u32 primitive_type)
{ {
SHADERUID uid; SHADERUID uid;
GetShaderId(&uid, dstAlphaMode, primitive_type); GetShaderId(&uid, primitive_type);
// Check if the shader is already set // Check if the shader is already set
if (last_entry) if (last_entry)
@ -388,9 +388,9 @@ GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const std::string& c
return result; return result;
} }
void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 primitive_type) void ProgramShaderCache::GetShaderId(SHADERUID* uid, u32 primitive_type)
{ {
uid->puid = GetPixelShaderUid(dstAlphaMode); uid->puid = GetPixelShaderUid();
uid->vuid = GetVertexShaderUid(); uid->vuid = GetVertexShaderUid();
uid->guid = GetGeometryShaderUid(primitive_type); uid->guid = GetGeometryShaderUid(primitive_type);
} }

View File

@ -62,8 +62,8 @@ public:
}; };
static PCacheEntry GetShaderProgram(); static PCacheEntry GetShaderProgram();
static SHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 primitive_type); static SHADER* SetShader(u32 primitive_type);
static void GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 primitive_type); static void GetShaderId(SHADERUID* uid, u32 primitive_type);
static bool CompileShader(SHADER& shader, const std::string& vcode, const std::string& pcode, static bool CompileShader(SHADER& shader, const std::string& vcode, const std::string& pcode,
const std::string& gcode = ""); const std::string& gcode = "");

View File

@ -136,7 +136,7 @@ void VertexManager::Draw(u32 stride)
static_cast<Renderer*>(g_renderer.get())->SetGenerationMode(); static_cast<Renderer*>(g_renderer.get())->SetGenerationMode();
} }
void VertexManager::vFlush(bool useDstAlpha) void VertexManager::vFlush()
{ {
GLVertexFormat* nativeVertexFmt = (GLVertexFormat*)VertexLoaderManager::GetCurrentVertexFormat(); GLVertexFormat* nativeVertexFmt = (GLVertexFormat*)VertexLoaderManager::GetCurrentVertexFormat();
u32 stride = nativeVertexFmt->GetVertexStride(); u32 stride = nativeVertexFmt->GetVertexStride();
@ -149,19 +149,7 @@ void VertexManager::vFlush(bool useDstAlpha)
PrepareDrawBuffers(stride); PrepareDrawBuffers(stride);
// Makes sure we can actually do Dual source blending ProgramShaderCache::SetShader(m_current_primitive_type);
bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
// If host supports GL_ARB_blend_func_extended, we can do dst alpha in
// the same pass as regular rendering.
if (useDstAlpha && dualSourcePossible)
{
ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, m_current_primitive_type);
}
else
{
ProgramShaderCache::SetShader(DSTALPHA_NONE, m_current_primitive_type);
}
// upload global constants // upload global constants
ProgramShaderCache::UploadConstants(); ProgramShaderCache::UploadConstants();
@ -171,38 +159,6 @@ void VertexManager::vFlush(bool useDstAlpha)
Draw(stride); Draw(stride);
// If the GPU does not support dual-source blending, we can approximate the effect by drawing
// the object a second time, with the write mask set to alpha only using a shader that outputs
// the destination/constant alpha value (which would normally be SRC_COLOR.a).
//
// This is also used when logic ops and destination alpha is enabled, since we can't enable
// blending and logic ops concurrently.
bool logic_op_enabled = (bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable &&
GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL);
if (useDstAlpha && (!dualSourcePossible || logic_op_enabled))
{
ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS, m_current_primitive_type);
// only update alpha
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glDisable(GL_BLEND);
if (logic_op_enabled)
glDisable(GL_COLOR_LOGIC_OP);
Draw(stride);
// restore color mask
g_renderer->SetColorMask();
if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
glEnable(GL_BLEND);
if (logic_op_enabled)
glEnable(GL_COLOR_LOGIC_OP);
}
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS) if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
{ {

View File

@ -41,7 +41,7 @@ protected:
private: private:
void Draw(u32 stride); void Draw(u32 stride);
void vFlush(bool useDstAlpha) override; void vFlush() override;
void PrepareDrawBuffers(u32 stride); void PrepareDrawBuffers(u32 stride);
// Alternative buffers in CPU memory for primatives we are going to discard. // Alternative buffers in CPU memory for primatives we are going to discard.

View File

@ -54,7 +54,7 @@ void SWVertexLoader::ResetBuffer(u32 stride)
IndexGenerator::Start(GetIndexBuffer()); IndexGenerator::Start(GetIndexBuffer());
} }
void SWVertexLoader::vFlush(bool useDstAlpha) void SWVertexLoader::vFlush()
{ {
DebugUtil::OnObjectBegin(); DebugUtil::OnObjectBegin();

View File

@ -25,7 +25,7 @@ protected:
void ResetBuffer(u32 stride) override; void ResetBuffer(u32 stride) override;
u16* GetIndexBuffer() { return &LocalIBuffer[0]; } u16* GetIndexBuffer() { return &LocalIBuffer[0]; }
private: private:
void vFlush(bool useDstAlpha) override; void vFlush() override;
std::vector<u8> LocalVBuffer; std::vector<u8> LocalVBuffer;
std::vector<u16> LocalIBuffer; std::vector<u16> LocalIBuffer;

View File

@ -1218,7 +1218,7 @@ void Renderer::ResizeSwapChain()
OnSwapChainResized(); OnSwapChainResized();
} }
void Renderer::ApplyState(bool bUseDstAlpha) void Renderer::ApplyState()
{ {
} }

View File

@ -52,7 +52,7 @@ public:
void ReinterpretPixelData(unsigned int convtype) override; void ReinterpretPixelData(unsigned int convtype) override;
void ApplyState(bool bUseDstAlpha) override; void ApplyState() override;
void ResetAPIState() override; void ResetAPIState() override;
void RestoreAPIState() override; void RestoreAPIState() override;

View File

@ -304,10 +304,10 @@ void StateTracker::SetBlendState(const BlendState& state)
m_dirty_flags |= DIRTY_FLAG_PIPELINE; m_dirty_flags |= DIRTY_FLAG_PIPELINE;
} }
bool StateTracker::CheckForShaderChanges(u32 gx_primitive_type, DSTALPHA_MODE dstalpha_mode) bool StateTracker::CheckForShaderChanges(u32 gx_primitive_type)
{ {
VertexShaderUid vs_uid = GetVertexShaderUid(); VertexShaderUid vs_uid = GetVertexShaderUid();
PixelShaderUid ps_uid = GetPixelShaderUid(dstalpha_mode); PixelShaderUid ps_uid = GetPixelShaderUid();
bool changed = false; bool changed = false;
@ -340,16 +340,6 @@ bool StateTracker::CheckForShaderChanges(u32 gx_primitive_type, DSTALPHA_MODE ds
changed = true; changed = true;
} }
if (m_dstalpha_mode != dstalpha_mode)
{
// Switching to/from alpha pass requires a pipeline change, since the blend state
// is overridden in the destination alpha pass.
if (m_dstalpha_mode == DSTALPHA_ALPHA_PASS || dstalpha_mode == DSTALPHA_ALPHA_PASS)
changed = true;
m_dstalpha_mode = dstalpha_mode;
}
if (changed) if (changed)
m_dirty_flags |= DIRTY_FLAG_PIPELINE; m_dirty_flags |= DIRTY_FLAG_PIPELINE;
@ -881,22 +871,6 @@ void StateTracker::EndClearRenderPass()
EndRenderPass(); EndRenderPass();
} }
PipelineInfo StateTracker::GetAlphaPassPipelineConfig(const PipelineInfo& info) const
{
PipelineInfo temp_info = info;
// Skip depth writes for this pass. The results will be the same, so no
// point in overwriting depth values with the same value.
temp_info.depth_stencil_state.write_enable = VK_FALSE;
// Only allow alpha writes, and disable blending.
temp_info.blend_state.blend_enable = VK_FALSE;
temp_info.blend_state.logic_op_enable = VK_FALSE;
temp_info.blend_state.write_mask = VK_COLOR_COMPONENT_A_BIT;
return temp_info;
}
VkPipeline StateTracker::GetPipelineAndCacheUID(const PipelineInfo& info) VkPipeline StateTracker::GetPipelineAndCacheUID(const PipelineInfo& info)
{ {
auto result = g_object_cache->GetPipelineWithCacheResult(info); auto result = g_object_cache->GetPipelineWithCacheResult(info);
@ -915,17 +889,7 @@ bool StateTracker::UpdatePipeline()
return false; return false;
// Grab a new pipeline object, this can fail. // Grab a new pipeline object, this can fail.
// We have to use a different blend state for the alpha pass of the dstalpha fallback. m_pipeline_object = GetPipelineAndCacheUID(m_pipeline_state);
if (m_dstalpha_mode == DSTALPHA_ALPHA_PASS)
{
// We need to retain the existing state, since we don't want to break the next draw.
PipelineInfo temp_info = GetAlphaPassPipelineConfig(m_pipeline_state);
m_pipeline_object = GetPipelineAndCacheUID(temp_info);
}
else
{
m_pipeline_object = GetPipelineAndCacheUID(m_pipeline_state);
}
m_dirty_flags |= DIRTY_FLAG_PIPELINE_BINDING; m_dirty_flags |= DIRTY_FLAG_PIPELINE_BINDING;
return m_pipeline_object != VK_NULL_HANDLE; return m_pipeline_object != VK_NULL_HANDLE;

View File

@ -58,7 +58,7 @@ public:
void SetDepthStencilState(const DepthStencilState& state); void SetDepthStencilState(const DepthStencilState& state);
void SetBlendState(const BlendState& state); void SetBlendState(const BlendState& state);
bool CheckForShaderChanges(u32 gx_primitive_type, DSTALPHA_MODE dstalpha_mode); bool CheckForShaderChanges(u32 gx_primitive_type);
void UpdateVertexShaderConstants(); void UpdateVertexShaderConstants();
void UpdateGeometryShaderConstants(); void UpdateGeometryShaderConstants();
@ -172,9 +172,6 @@ private:
// If not, ends the render pass if it is a clear render pass. // If not, ends the render pass if it is a clear render pass.
bool IsViewportWithinRenderArea() const; bool IsViewportWithinRenderArea() const;
// Gets a pipeline state that can be used to draw the alpha pass with constant alpha enabled.
PipelineInfo GetAlphaPassPipelineConfig(const PipelineInfo& info) const;
// Obtains a Vulkan pipeline object for the specified pipeline configuration. // Obtains a Vulkan pipeline object for the specified pipeline configuration.
// Also adds this pipeline configuration to the UID cache if it is not present already. // Also adds this pipeline configuration to the UID cache if it is not present already.
VkPipeline GetPipelineAndCacheUID(const PipelineInfo& info); VkPipeline GetPipelineAndCacheUID(const PipelineInfo& info);
@ -205,7 +202,6 @@ private:
// pipeline state // pipeline state
PipelineInfo m_pipeline_state = {}; PipelineInfo m_pipeline_state = {};
DSTALPHA_MODE m_dstalpha_mode = DSTALPHA_NONE;
VkPipeline m_pipeline_object = VK_NULL_HANDLE; VkPipeline m_pipeline_object = VK_NULL_HANDLE;
// shader bindings // shader bindings

View File

@ -124,7 +124,7 @@ void VertexManager::ResetBuffer(u32 stride)
static_cast<u32>(m_index_stream_buffer->GetCurrentOffset() / sizeof(u16)); static_cast<u32>(m_index_stream_buffer->GetCurrentOffset() / sizeof(u16));
} }
void VertexManager::vFlush(bool use_dst_alpha) void VertexManager::vFlush()
{ {
const VertexFormat* vertex_format = const VertexFormat* vertex_format =
static_cast<VertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat()); static_cast<VertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat());
@ -153,13 +153,8 @@ void VertexManager::vFlush(bool use_dst_alpha)
break; break;
} }
// Can we do single-pass dst alpha?
DSTALPHA_MODE dstalpha_mode = DSTALPHA_NONE;
if (use_dst_alpha && g_vulkan_context->SupportsDualSourceBlend())
dstalpha_mode = DSTALPHA_DUAL_SOURCE_BLEND;
// Check for any shader stage changes // Check for any shader stage changes
StateTracker::GetInstance()->CheckForShaderChanges(m_current_primitive_type, dstalpha_mode); StateTracker::GetInstance()->CheckForShaderChanges(m_current_primitive_type);
// Update any changed constants // Update any changed constants
StateTracker::GetInstance()->UpdateVertexShaderConstants(); StateTracker::GetInstance()->UpdateVertexShaderConstants();
@ -202,27 +197,6 @@ void VertexManager::vFlush(bool use_dst_alpha)
vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), index_count, 1, vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), index_count, 1,
m_current_draw_base_index, m_current_draw_base_vertex, 0); m_current_draw_base_index, m_current_draw_base_vertex, 0);
// If the GPU does not support dual-source blending, we can approximate the effect by drawing
// the object a second time, with the write mask set to alpha only using a shader that outputs
// the destination/constant alpha value (which would normally be SRC_COLOR.a).
//
// This is also used when logic ops and destination alpha is enabled, since we can't enable
// blending and logic ops concurrently (and the logical operation applies to all channels).
bool logic_op_enabled = bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable;
if (use_dst_alpha && (!g_vulkan_context->SupportsDualSourceBlend() || logic_op_enabled))
{
StateTracker::GetInstance()->CheckForShaderChanges(m_current_primitive_type,
DSTALPHA_ALPHA_PASS);
if (!StateTracker::GetInstance()->Bind())
{
WARN_LOG(VIDEO, "Skipped draw of %u indices (alpha pass)", index_count);
return;
}
vkCmdDrawIndexed(g_command_buffer_mgr->GetCurrentCommandBuffer(), index_count, 1,
m_current_draw_base_index, m_current_draw_base_vertex, 0);
}
StateTracker::GetInstance()->OnDraw(); StateTracker::GetInstance()->OnDraw();
} }

View File

@ -31,7 +31,7 @@ protected:
void ResetBuffer(u32 stride) override; void ResetBuffer(u32 stride) override;
private: private:
void vFlush(bool use_dst_alpha) override; void vFlush() override;
std::vector<u8> m_cpu_vertex_buffer; std::vector<u8> m_cpu_vertex_buffer;
std::vector<u16> m_cpu_index_buffer; std::vector<u16> m_cpu_index_buffer;

View File

@ -156,13 +156,15 @@ static const char* tevAOutputTable[] = {"prev.a", "c0.a", "c1.a", "c2.a"};
// leak // leak
// into this UID; This is really unhelpful if these UIDs ever move from one machine to // into this UID; This is really unhelpful if these UIDs ever move from one machine to
// another. // another.
PixelShaderUid GetPixelShaderUid(DSTALPHA_MODE dstAlphaMode) PixelShaderUid GetPixelShaderUid()
{ {
PixelShaderUid out; PixelShaderUid out;
pixel_shader_uid_data* uid_data = out.GetUidData<pixel_shader_uid_data>(); pixel_shader_uid_data* uid_data = out.GetUidData<pixel_shader_uid_data>();
memset(uid_data, 0, sizeof(*uid_data)); memset(uid_data, 0, sizeof(*uid_data));
uid_data->dstAlphaMode = dstAlphaMode; uid_data->useDstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
uid_data->genMode_numindstages = bpmem.genMode.numindstages; uid_data->genMode_numindstages = bpmem.genMode.numindstages;
uid_data->genMode_numtevstages = bpmem.genMode.numtevstages; uid_data->genMode_numtevstages = bpmem.genMode.numtevstages;
uid_data->genMode_numtexgens = bpmem.genMode.numtexgens; uid_data->genMode_numtexgens = bpmem.genMode.numtexgens;
@ -327,13 +329,9 @@ PixelShaderUid GetPixelShaderUid(DSTALPHA_MODE dstAlphaMode)
uid_data->ztex_op = bpmem.ztex2.op; uid_data->ztex_op = bpmem.ztex2.op;
uid_data->early_ztest = bpmem.UseEarlyDepthTest(); uid_data->early_ztest = bpmem.UseEarlyDepthTest();
uid_data->fog_fsel = bpmem.fog.c_proj_fsel.fsel; uid_data->fog_fsel = bpmem.fog.c_proj_fsel.fsel;
uid_data->fog_fsel = bpmem.fog.c_proj_fsel.fsel;
if (dstAlphaMode != DSTALPHA_ALPHA_PASS) uid_data->fog_proj = bpmem.fog.c_proj_fsel.proj;
{ uid_data->fog_RangeBaseEnabled = bpmem.fogRange.Base.Enabled;
uid_data->fog_fsel = bpmem.fog.c_proj_fsel.fsel;
uid_data->fog_proj = bpmem.fog.c_proj_fsel.proj;
uid_data->fog_RangeBaseEnabled = bpmem.fogRange.Base.Enabled;
}
return out; return out;
} }
@ -510,7 +508,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
const bool use_dual_source = const bool use_dual_source =
g_ActiveConfig.backend_info.bSupportsDualSourceBlend && g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) || (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) ||
uid_data->dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND); uid_data->useDstAlpha);
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
{ {
@ -795,8 +793,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
out.Write("\tprev.rgb = (prev.rgb - (prev.rgb >> 6)) + abs(dither.y * 3 - dither.x * 2);\n"); out.Write("\tprev.rgb = (prev.rgb - (prev.rgb >> 6)) + abs(dither.y * 3 - dither.x * 2);\n");
} }
if (uid_data->dstAlphaMode != DSTALPHA_ALPHA_PASS) WriteFog(out, uid_data);
WriteFog(out, uid_data);
// Write the color and alpha values to the framebuffer // Write the color and alpha values to the framebuffer
WriteColor(out, uid_data, use_dual_source); WriteColor(out, uid_data, use_dual_source);
@ -1308,7 +1305,7 @@ static void WriteColor(ShaderCode& out, const pixel_shader_uid_data* uid_data, b
// Colors will be blended against the 8-bit alpha from ocol1 and // Colors will be blended against the 8-bit alpha from ocol1 and
// the 6-bit alpha from ocol0 will be written to the framebuffer // the 6-bit alpha from ocol0 will be written to the framebuffer
if (uid_data->dstAlphaMode == DSTALPHA_NONE) if (!uid_data->useDstAlpha)
{ {
out.Write("\tocol0.a = float(prev.a >> 2) / 63.0;\n"); out.Write("\tocol0.a = float(prev.a >> 2) / 63.0;\n");
if (use_dual_source) if (use_dual_source)
@ -1322,7 +1319,7 @@ static void WriteColor(ShaderCode& out, const pixel_shader_uid_data* uid_data, b
// Use dual-source color blending to perform dst alpha in a single pass // Use dual-source color blending to perform dst alpha in a single pass
if (use_dual_source) if (use_dual_source)
{ {
if (uid_data->dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND) if (uid_data->useDstAlpha)
out.Write("\tocol1.a = float(prev.a) / 255.0;\n"); out.Write("\tocol1.a = float(prev.a) / 255.0;\n");
else else
out.Write("\tocol1.a = float(" I_ALPHA ".a) / 255.0;\n"); out.Write("\tocol1.a = float(" I_ALPHA ".a) / 255.0;\n");

View File

@ -10,14 +10,6 @@
enum class APIType; enum class APIType;
// Different ways to achieve rendering with destination alpha
enum DSTALPHA_MODE
{
DSTALPHA_NONE, // Render normally, without destination alpha
DSTALPHA_ALPHA_PASS, // Render normally first, then render again for alpha
DSTALPHA_DUAL_SOURCE_BLEND // Use dual-source blending
};
#pragma pack(1) #pragma pack(1)
struct pixel_shader_uid_data struct pixel_shader_uid_data
{ {
@ -26,7 +18,8 @@ struct pixel_shader_uid_data
u32 num_values; // TODO: Shouldn't be a u32 u32 num_values; // TODO: Shouldn't be a u32
u32 NumValues() const { return num_values; } u32 NumValues() const { return num_values; }
u32 components : 2; u32 components : 2;
u32 dstAlphaMode : 2; u32 pad0 : 1;
u32 useDstAlpha : 1;
u32 Pretest : 2; u32 Pretest : 2;
u32 nIndirectStagesUsed : 4; u32 nIndirectStagesUsed : 4;
u32 stereo : 1; u32 stereo : 1;
@ -170,4 +163,4 @@ struct pixel_shader_uid_data
typedef ShaderUid<pixel_shader_uid_data> PixelShaderUid; typedef ShaderUid<pixel_shader_uid_data> PixelShaderUid;
ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* uid_data); ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* uid_data);
PixelShaderUid GetPixelShaderUid(DSTALPHA_MODE dstAlphaMode); PixelShaderUid GetPixelShaderUid();

View File

@ -74,7 +74,7 @@ public:
virtual void SetViewport() {} virtual void SetViewport() {}
virtual void SetFullscreen(bool enable_fullscreen) {} virtual void SetFullscreen(bool enable_fullscreen) {}
virtual bool IsFullscreen() const { return false; } virtual bool IsFullscreen() const { return false; }
virtual void ApplyState(bool bUseDstAlpha) {} virtual void ApplyState() {}
virtual void RestoreState() {} virtual void RestoreState() {}
virtual void ResetAPIState() {} virtual void ResetAPIState() {}
virtual void RestoreAPIState() {} virtual void RestoreAPIState() {}

View File

@ -253,12 +253,9 @@ void VertexManagerBase::Flush()
GeometryShaderManager::SetConstants(); GeometryShaderManager::SetConstants();
PixelShaderManager::SetConstants(); PixelShaderManager::SetConstants();
bool useDstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
if (PerfQueryBase::ShouldEmulate()) if (PerfQueryBase::ShouldEmulate())
g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
g_vertex_manager->vFlush(useDstAlpha); g_vertex_manager->vFlush();
if (PerfQueryBase::ShouldEmulate()) if (PerfQueryBase::ShouldEmulate())
g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
} }

View File

@ -82,7 +82,7 @@ protected:
private: private:
bool m_is_flushed = true; bool m_is_flushed = true;
virtual void vFlush(bool useDstAlpha) = 0; virtual void vFlush() = 0;
virtual void CreateDeviceObjects() {} virtual void CreateDeviceObjects() {}
virtual void DestroyDeviceObjects() {} virtual void DestroyDeviceObjects() {}