mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
Merge pull request #5284 from stenzek/vulkan-videocommon-blending-state
Vulkan: Use BlendingState from VideoCommon
This commit is contained in:
commit
d1dc9d5a0c
@ -1085,11 +1085,6 @@ void Renderer::SetLogicOpMode()
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetDitherMode()
|
||||
{
|
||||
// TODO: Set dither mode to bpmem.blendmode.dither
|
||||
}
|
||||
|
||||
void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
|
||||
{
|
||||
const FourTexUnits& tex = bpmem.tex[texindex];
|
||||
|
@ -25,7 +25,6 @@ public:
|
||||
void SetGenerationMode() override;
|
||||
void SetDepthMode() override;
|
||||
void SetLogicOpMode() override;
|
||||
void SetDitherMode() override;
|
||||
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
|
||||
void SetInterlacingMode() override;
|
||||
void SetViewport() override;
|
||||
|
@ -1108,11 +1108,6 @@ void Renderer::SetLogicOpMode()
|
||||
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
|
||||
}
|
||||
|
||||
void Renderer::SetDitherMode()
|
||||
{
|
||||
// EXISTINGD3D11TODO: Set dither mode to bpmem.blendmode.dither
|
||||
}
|
||||
|
||||
void Renderer::SetSamplerState(int stage, int tex_index, bool custom_tex)
|
||||
{
|
||||
const FourTexUnits& tex = bpmem.tex[tex_index];
|
||||
|
@ -26,7 +26,6 @@ public:
|
||||
void SetGenerationMode() override;
|
||||
void SetDepthMode() override;
|
||||
void SetLogicOpMode() override;
|
||||
void SetDitherMode() override;
|
||||
void SetSamplerState(int stage, int tex_index, bool custom_tex) override;
|
||||
void SetInterlacingMode() override;
|
||||
void SetViewport() override;
|
||||
|
@ -1214,7 +1214,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
||||
state.Generate(bpmem);
|
||||
|
||||
bool useDualSource =
|
||||
g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
|
||||
state.usedualsrc && g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
|
||||
(!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) || state.dstalpha);
|
||||
|
||||
const GLenum src_factors[8] = {
|
||||
@ -1274,11 +1274,6 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
||||
glDisable(GL_COLOR_LOGIC_OP);
|
||||
}
|
||||
|
||||
if (state.dither)
|
||||
glEnable(GL_DITHER);
|
||||
else
|
||||
glDisable(GL_DITHER);
|
||||
|
||||
glColorMask(state.colorupdate, state.colorupdate, state.colorupdate, state.alphaupdate);
|
||||
}
|
||||
|
||||
|
@ -145,34 +145,6 @@ union DepthStencilState
|
||||
u32 bits;
|
||||
};
|
||||
|
||||
// Blend state info
|
||||
union BlendState
|
||||
{
|
||||
struct
|
||||
{
|
||||
union
|
||||
{
|
||||
BitField<0, 1, VkBool32> blend_enable;
|
||||
BitField<1, 3, VkBlendOp> blend_op;
|
||||
BitField<4, 5, VkBlendFactor> src_blend;
|
||||
BitField<9, 5, VkBlendFactor> dst_blend;
|
||||
BitField<14, 3, VkBlendOp> alpha_blend_op;
|
||||
BitField<17, 5, VkBlendFactor> src_alpha_blend;
|
||||
BitField<22, 5, VkBlendFactor> dst_alpha_blend;
|
||||
BitField<27, 4, VkColorComponentFlags> write_mask;
|
||||
u32 low_bits;
|
||||
};
|
||||
union
|
||||
{
|
||||
BitField<0, 1, VkBool32> logic_op_enable;
|
||||
BitField<1, 4, VkLogicOp> logic_op;
|
||||
u32 high_bits;
|
||||
};
|
||||
};
|
||||
|
||||
u64 bits;
|
||||
};
|
||||
|
||||
// Sampler info
|
||||
union SamplerState
|
||||
{
|
||||
|
@ -1163,14 +1163,10 @@ void FramebufferManager::DrawPokeVertices(const EFBPokeVertex* vertices, size_t
|
||||
pipeline_info.rasterization_state.bits = Util::GetNoCullRasterizationState().bits;
|
||||
pipeline_info.rasterization_state.samples = m_efb_samples;
|
||||
pipeline_info.depth_stencil_state.bits = Util::GetNoDepthTestingDepthStencilState().bits;
|
||||
pipeline_info.blend_state.bits = Util::GetNoBlendingBlendState().bits;
|
||||
pipeline_info.blend_state.write_mask = 0;
|
||||
pipeline_info.blend_state.hex = Util::GetNoBlendingBlendState().hex;
|
||||
pipeline_info.blend_state.colorupdate = write_color;
|
||||
pipeline_info.blend_state.alphaupdate = write_color;
|
||||
pipeline_info.primitive_topology = m_poke_primitive_topology;
|
||||
if (write_color)
|
||||
{
|
||||
pipeline_info.blend_state.write_mask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
}
|
||||
if (write_depth)
|
||||
{
|
||||
pipeline_info.depth_stencil_state.test_enable = VK_TRUE;
|
||||
|
@ -135,33 +135,95 @@ GetVulkanDepthStencilState(const DepthStencilState& state)
|
||||
};
|
||||
}
|
||||
|
||||
static VkPipelineColorBlendAttachmentState GetVulkanAttachmentBlendState(const BlendState& state)
|
||||
static VkPipelineColorBlendAttachmentState GetVulkanAttachmentBlendState(const BlendingState& state)
|
||||
{
|
||||
VkPipelineColorBlendAttachmentState vk_state = {
|
||||
state.blend_enable, // VkBool32 blendEnable
|
||||
state.src_blend, // VkBlendFactor srcColorBlendFactor
|
||||
state.dst_blend, // VkBlendFactor dstColorBlendFactor
|
||||
state.blend_op, // VkBlendOp colorBlendOp
|
||||
state.src_alpha_blend, // VkBlendFactor srcAlphaBlendFactor
|
||||
state.dst_alpha_blend, // VkBlendFactor dstAlphaBlendFactor
|
||||
state.alpha_blend_op, // VkBlendOp alphaBlendOp
|
||||
state.write_mask // VkColorComponentFlags colorWriteMask
|
||||
};
|
||||
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;
|
||||
|
||||
if (state.usedualsrc && g_vulkan_context->SupportsDualSourceBlend())
|
||||
{
|
||||
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_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[state.srcfactor];
|
||||
vk_state.srcAlphaBlendFactor = src_factors[state.srcfactoralpha];
|
||||
vk_state.dstColorBlendFactor = dst_factors[state.dstfactor];
|
||||
vk_state.dstAlphaBlendFactor = dst_factors[state.dstfactoralpha];
|
||||
}
|
||||
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[state.srcfactor];
|
||||
vk_state.srcAlphaBlendFactor = src_factors[state.srcfactoralpha];
|
||||
vk_state.dstColorBlendFactor = dst_factors[state.dstfactor];
|
||||
vk_state.dstAlphaBlendFactor = dst_factors[state.dstfactoralpha];
|
||||
}
|
||||
|
||||
if (state.colorupdate)
|
||||
{
|
||||
vk_state.colorWriteMask =
|
||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
vk_state.colorWriteMask = 0;
|
||||
}
|
||||
|
||||
if (state.alphaupdate)
|
||||
vk_state.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
|
||||
|
||||
return vk_state;
|
||||
}
|
||||
|
||||
static VkPipelineColorBlendStateCreateInfo
|
||||
GetVulkanColorBlendState(const BlendState& state,
|
||||
GetVulkanColorBlendState(const BlendingState& state,
|
||||
const VkPipelineColorBlendAttachmentState* attachments,
|
||||
uint32_t num_attachments)
|
||||
{
|
||||
static constexpr std::array<VkLogicOp, 16> vk_logic_ops = {
|
||||
{VK_LOGIC_OP_CLEAR, VK_LOGIC_OP_AND, VK_LOGIC_OP_AND_REVERSE, VK_LOGIC_OP_COPY,
|
||||
VK_LOGIC_OP_AND_INVERTED, VK_LOGIC_OP_NO_OP, VK_LOGIC_OP_XOR, VK_LOGIC_OP_OR,
|
||||
VK_LOGIC_OP_NOR, VK_LOGIC_OP_EQUIVALENT, VK_LOGIC_OP_INVERT, VK_LOGIC_OP_OR_REVERSE,
|
||||
VK_LOGIC_OP_COPY_INVERTED, VK_LOGIC_OP_OR_INVERTED, VK_LOGIC_OP_NAND, VK_LOGIC_OP_SET}};
|
||||
|
||||
VkBool32 vk_logic_op_enable = static_cast<VkBool32>(state.logicopenable);
|
||||
if (vk_logic_op_enable && !g_vulkan_context->SupportsLogicOps())
|
||||
{
|
||||
// At the time of writing, Adreno and Mali drivers didn't support logic ops.
|
||||
// The "emulation" through blending path has been removed, so just disable it completely.
|
||||
// These drivers don't support dual-source blend either, so issues are to be expected.
|
||||
vk_logic_op_enable = VK_FALSE;
|
||||
}
|
||||
|
||||
VkLogicOp vk_logic_op = vk_logic_op_enable ? vk_logic_ops[state.logicmode] : VK_LOGIC_OP_CLEAR;
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo vk_state = {
|
||||
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void* pNext
|
||||
0, // VkPipelineColorBlendStateCreateFlags flags
|
||||
state.logic_op_enable, // VkBool32 logicOpEnable
|
||||
state.logic_op, // VkLogicOp logicOp
|
||||
vk_logic_op_enable, // VkBool32 logicOpEnable
|
||||
vk_logic_op, // VkLogicOp logicOp
|
||||
num_attachments, // uint32_t attachmentCount
|
||||
attachments, // const VkPipelineColorBlendAttachmentState* pAttachments
|
||||
{1.0f, 1.0f, 1.0f, 1.0f} // float blendConstants[4]
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "VideoCommon/GeometryShaderGen.h"
|
||||
#include "VideoCommon/PixelShaderGen.h"
|
||||
#include "VideoCommon/RenderState.h"
|
||||
#include "VideoCommon/VertexShaderGen.h"
|
||||
|
||||
namespace Vulkan
|
||||
@ -36,7 +37,7 @@ struct PipelineInfo
|
||||
VkShaderModule gs;
|
||||
VkShaderModule ps;
|
||||
VkRenderPass render_pass;
|
||||
BlendState blend_state;
|
||||
BlendingState blend_state;
|
||||
RasterizationState rasterization_state;
|
||||
DepthStencilState depth_stencil_state;
|
||||
VkPrimitiveTopology primitive_topology;
|
||||
|
@ -395,11 +395,10 @@ void RasterFont::PrintMultiLineText(VkRenderPass render_pass, const std::string&
|
||||
draw.SetPSSampler(0, m_texture->GetView(), g_object_cache->GetLinearSampler());
|
||||
|
||||
// Setup alpha blending
|
||||
BlendState blend_state = Util::GetNoBlendingBlendState();
|
||||
blend_state.blend_enable = VK_TRUE;
|
||||
blend_state.src_blend = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_state.blend_op = VK_BLEND_OP_ADD;
|
||||
blend_state.dst_blend = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
BlendingState blend_state = Util::GetNoBlendingBlendState();
|
||||
blend_state.blendenable = true;
|
||||
blend_state.srcfactor = BlendMode::SRCALPHA;
|
||||
blend_state.dstfactor = BlendMode::INVSRCALPHA;
|
||||
draw.SetBlendState(blend_state);
|
||||
|
||||
draw.Draw();
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
#include "VideoCommon/PixelEngine.h"
|
||||
#include "VideoCommon/PixelShaderManager.h"
|
||||
#include "VideoCommon/RenderState.h"
|
||||
#include "VideoCommon/SamplerCommon.h"
|
||||
#include "VideoCommon/TextureCacheBase.h"
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
@ -432,13 +433,9 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
|
||||
StateTracker::GetInstance()->SetPendingRebind();
|
||||
|
||||
// Mask away the appropriate colors and use a shader
|
||||
BlendState blend_state = Util::GetNoBlendingBlendState();
|
||||
u32 write_mask = 0;
|
||||
if (color_enable)
|
||||
write_mask |= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT;
|
||||
if (alpha_enable)
|
||||
write_mask |= VK_COLOR_COMPONENT_A_BIT;
|
||||
blend_state.write_mask = write_mask;
|
||||
BlendingState blend_state = Util::GetNoBlendingBlendState();
|
||||
blend_state.colorupdate = color_enable;
|
||||
blend_state.alphaupdate = alpha_enable;
|
||||
|
||||
DepthStencilState depth_state = Util::GetNoDepthTestingDepthStencilState();
|
||||
depth_state.test_enable = z_enable ? VK_TRUE : VK_FALSE;
|
||||
@ -1324,232 +1321,12 @@ void Renderer::SetDepthMode()
|
||||
StateTracker::GetInstance()->SetDepthStencilState(new_ds_state);
|
||||
}
|
||||
|
||||
void Renderer::SetColorMask()
|
||||
{
|
||||
u32 color_mask = 0;
|
||||
|
||||
if (bpmem.alpha_test.TestResult() != AlphaTest::FAIL)
|
||||
{
|
||||
if (bpmem.blendmode.alphaupdate && bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24)
|
||||
color_mask |= VK_COLOR_COMPONENT_A_BIT;
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
color_mask |= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT;
|
||||
}
|
||||
|
||||
BlendState new_blend_state = {};
|
||||
new_blend_state.bits = StateTracker::GetInstance()->GetBlendState().bits;
|
||||
new_blend_state.write_mask = color_mask;
|
||||
|
||||
StateTracker::GetInstance()->SetBlendState(new_blend_state);
|
||||
}
|
||||
|
||||
void Renderer::SetBlendMode(bool force_update)
|
||||
{
|
||||
BlendState new_blend_state = {};
|
||||
new_blend_state.bits = StateTracker::GetInstance()->GetBlendState().bits;
|
||||
BlendingState state;
|
||||
state.Generate(bpmem);
|
||||
|
||||
// Fast path for blending disabled
|
||||
if (!bpmem.blendmode.blendenable)
|
||||
{
|
||||
new_blend_state.blend_enable = VK_FALSE;
|
||||
new_blend_state.blend_op = VK_BLEND_OP_ADD;
|
||||
new_blend_state.src_blend = VK_BLEND_FACTOR_ONE;
|
||||
new_blend_state.dst_blend = VK_BLEND_FACTOR_ZERO;
|
||||
new_blend_state.alpha_blend_op = VK_BLEND_OP_ADD;
|
||||
new_blend_state.src_alpha_blend = VK_BLEND_FACTOR_ONE;
|
||||
new_blend_state.dst_alpha_blend = VK_BLEND_FACTOR_ZERO;
|
||||
StateTracker::GetInstance()->SetBlendState(new_blend_state);
|
||||
return;
|
||||
}
|
||||
// Fast path for subtract blending
|
||||
else if (bpmem.blendmode.subtract)
|
||||
{
|
||||
new_blend_state.blend_enable = VK_TRUE;
|
||||
new_blend_state.blend_op = VK_BLEND_OP_REVERSE_SUBTRACT;
|
||||
new_blend_state.src_blend = VK_BLEND_FACTOR_ONE;
|
||||
new_blend_state.dst_blend = VK_BLEND_FACTOR_ONE;
|
||||
new_blend_state.alpha_blend_op = VK_BLEND_OP_REVERSE_SUBTRACT;
|
||||
new_blend_state.src_alpha_blend = VK_BLEND_FACTOR_ONE;
|
||||
new_blend_state.dst_alpha_blend = VK_BLEND_FACTOR_ONE;
|
||||
StateTracker::GetInstance()->SetBlendState(new_blend_state);
|
||||
return;
|
||||
}
|
||||
|
||||
// Our render target always uses an alpha channel, so we need to override the blend functions to
|
||||
// assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel.
|
||||
bool target_has_alpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
|
||||
bool use_dst_alpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && target_has_alpha;
|
||||
bool use_dual_src = g_vulkan_context->SupportsDualSourceBlend();
|
||||
|
||||
new_blend_state.blend_enable = VK_TRUE;
|
||||
new_blend_state.blend_op = VK_BLEND_OP_ADD;
|
||||
|
||||
switch (bpmem.blendmode.srcfactor)
|
||||
{
|
||||
case BlendMode::ZERO:
|
||||
new_blend_state.src_blend = VK_BLEND_FACTOR_ZERO;
|
||||
break;
|
||||
case BlendMode::ONE:
|
||||
new_blend_state.src_blend = VK_BLEND_FACTOR_ONE;
|
||||
break;
|
||||
case BlendMode::DSTCLR:
|
||||
new_blend_state.src_blend = VK_BLEND_FACTOR_DST_COLOR;
|
||||
break;
|
||||
case BlendMode::INVDSTCLR:
|
||||
new_blend_state.src_blend = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
|
||||
break;
|
||||
case BlendMode::SRCALPHA:
|
||||
new_blend_state.src_blend =
|
||||
use_dual_src ? VK_BLEND_FACTOR_SRC1_ALPHA : VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
break;
|
||||
case BlendMode::INVSRCALPHA:
|
||||
new_blend_state.src_blend =
|
||||
use_dual_src ? VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA : VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
break;
|
||||
case BlendMode::DSTALPHA:
|
||||
new_blend_state.src_blend = target_has_alpha ? VK_BLEND_FACTOR_DST_ALPHA : VK_BLEND_FACTOR_ONE;
|
||||
break;
|
||||
case BlendMode::INVDSTALPHA:
|
||||
new_blend_state.src_blend =
|
||||
target_has_alpha ? VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA : VK_BLEND_FACTOR_ZERO;
|
||||
break;
|
||||
default:
|
||||
new_blend_state.src_blend = VK_BLEND_FACTOR_ONE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (bpmem.blendmode.dstfactor)
|
||||
{
|
||||
case BlendMode::ZERO:
|
||||
new_blend_state.dst_blend = VK_BLEND_FACTOR_ZERO;
|
||||
break;
|
||||
case BlendMode::ONE:
|
||||
new_blend_state.dst_blend = VK_BLEND_FACTOR_ONE;
|
||||
break;
|
||||
case BlendMode::SRCCLR:
|
||||
new_blend_state.dst_blend = VK_BLEND_FACTOR_SRC_COLOR;
|
||||
break;
|
||||
case BlendMode::INVSRCCLR:
|
||||
new_blend_state.dst_blend = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
|
||||
break;
|
||||
case BlendMode::SRCALPHA:
|
||||
new_blend_state.dst_blend =
|
||||
use_dual_src ? VK_BLEND_FACTOR_SRC1_ALPHA : VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
break;
|
||||
case BlendMode::INVSRCALPHA:
|
||||
new_blend_state.dst_blend =
|
||||
use_dual_src ? VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA : VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
break;
|
||||
case BlendMode::DSTALPHA:
|
||||
new_blend_state.dst_blend = target_has_alpha ? VK_BLEND_FACTOR_DST_ALPHA : VK_BLEND_FACTOR_ONE;
|
||||
break;
|
||||
case BlendMode::INVDSTALPHA:
|
||||
new_blend_state.dst_blend =
|
||||
target_has_alpha ? VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA : VK_BLEND_FACTOR_ZERO;
|
||||
break;
|
||||
default:
|
||||
new_blend_state.dst_blend = VK_BLEND_FACTOR_ONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (use_dst_alpha)
|
||||
{
|
||||
// Destination alpha sets 1*SRC
|
||||
new_blend_state.alpha_blend_op = VK_BLEND_OP_ADD;
|
||||
new_blend_state.src_alpha_blend = VK_BLEND_FACTOR_ONE;
|
||||
new_blend_state.dst_alpha_blend = VK_BLEND_FACTOR_ZERO;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_blend_state.alpha_blend_op = VK_BLEND_OP_ADD;
|
||||
new_blend_state.src_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.src_blend);
|
||||
new_blend_state.dst_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.dst_blend);
|
||||
}
|
||||
|
||||
StateTracker::GetInstance()->SetBlendState(new_blend_state);
|
||||
}
|
||||
|
||||
void Renderer::SetLogicOpMode()
|
||||
{
|
||||
BlendState new_blend_state = {};
|
||||
new_blend_state.bits = StateTracker::GetInstance()->GetBlendState().bits;
|
||||
|
||||
// Does our device support logic ops?
|
||||
bool logic_op_enable = bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable;
|
||||
if (g_vulkan_context->SupportsLogicOps())
|
||||
{
|
||||
if (logic_op_enable)
|
||||
{
|
||||
static const std::array<VkLogicOp, 16> logic_ops = {
|
||||
{VK_LOGIC_OP_CLEAR, VK_LOGIC_OP_AND, VK_LOGIC_OP_AND_REVERSE, VK_LOGIC_OP_COPY,
|
||||
VK_LOGIC_OP_AND_INVERTED, VK_LOGIC_OP_NO_OP, VK_LOGIC_OP_XOR, VK_LOGIC_OP_OR,
|
||||
VK_LOGIC_OP_NOR, VK_LOGIC_OP_EQUIVALENT, VK_LOGIC_OP_INVERT, VK_LOGIC_OP_OR_REVERSE,
|
||||
VK_LOGIC_OP_COPY_INVERTED, VK_LOGIC_OP_OR_INVERTED, VK_LOGIC_OP_NAND, VK_LOGIC_OP_SET}};
|
||||
|
||||
new_blend_state.logic_op_enable = VK_TRUE;
|
||||
new_blend_state.logic_op = logic_ops[bpmem.blendmode.logicmode];
|
||||
}
|
||||
else
|
||||
{
|
||||
new_blend_state.logic_op_enable = VK_FALSE;
|
||||
new_blend_state.logic_op = VK_LOGIC_OP_CLEAR;
|
||||
}
|
||||
|
||||
StateTracker::GetInstance()->SetBlendState(new_blend_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No logic op support, approximate with blending instead.
|
||||
// This is by no means correct, but necessary for some devices.
|
||||
if (logic_op_enable)
|
||||
{
|
||||
struct LogicOpBlend
|
||||
{
|
||||
VkBlendFactor src_factor;
|
||||
VkBlendOp op;
|
||||
VkBlendFactor dst_factor;
|
||||
};
|
||||
static const std::array<LogicOpBlend, 16> logic_ops = {
|
||||
{{VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ZERO},
|
||||
{VK_BLEND_FACTOR_DST_COLOR, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ZERO},
|
||||
{VK_BLEND_FACTOR_ONE, VK_BLEND_OP_SUBTRACT, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR},
|
||||
{VK_BLEND_FACTOR_ONE, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ZERO},
|
||||
{VK_BLEND_FACTOR_DST_COLOR, VK_BLEND_OP_REVERSE_SUBTRACT, VK_BLEND_FACTOR_ONE},
|
||||
{VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE},
|
||||
{VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_OP_MAX,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR},
|
||||
{VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE},
|
||||
{VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_OP_MAX,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR},
|
||||
{VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_OP_MAX, VK_BLEND_FACTOR_SRC_COLOR},
|
||||
{VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_OP_ADD,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR},
|
||||
{VK_BLEND_FACTOR_ONE, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR},
|
||||
{VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_OP_ADD,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR},
|
||||
{VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE},
|
||||
{VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_OP_ADD,
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR},
|
||||
{VK_BLEND_FACTOR_ONE, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE}}};
|
||||
|
||||
new_blend_state.blend_enable = VK_TRUE;
|
||||
new_blend_state.blend_op = logic_ops[bpmem.blendmode.logicmode].op;
|
||||
new_blend_state.src_blend = logic_ops[bpmem.blendmode.logicmode].src_factor;
|
||||
new_blend_state.dst_blend = logic_ops[bpmem.blendmode.logicmode].dst_factor;
|
||||
new_blend_state.alpha_blend_op = new_blend_state.blend_op;
|
||||
new_blend_state.src_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.src_blend);
|
||||
new_blend_state.dst_alpha_blend = Util::GetAlphaBlendFactor(new_blend_state.dst_blend);
|
||||
|
||||
StateTracker::GetInstance()->SetBlendState(new_blend_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is unfortunate. Since we clobber the blend state when enabling logic ops,
|
||||
// we have to call SetBlendMode again to restore the current blend state.
|
||||
SetBlendMode(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
StateTracker::GetInstance()->SetBlendState(state);
|
||||
}
|
||||
|
||||
void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
|
||||
@ -1630,10 +1407,6 @@ void Renderer::ResetSamplerStates()
|
||||
g_object_cache->ClearSamplerCache();
|
||||
}
|
||||
|
||||
void Renderer::SetDitherMode()
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer::SetInterlacingMode()
|
||||
{
|
||||
}
|
||||
|
@ -56,13 +56,10 @@ public:
|
||||
void ResetAPIState() override;
|
||||
void RestoreAPIState() override;
|
||||
|
||||
void SetColorMask() override;
|
||||
void SetBlendMode(bool force_update) override;
|
||||
void SetScissorRect(const EFBRectangle& rc) override;
|
||||
void SetGenerationMode() override;
|
||||
void SetDepthMode() override;
|
||||
void SetLogicOpMode() override;
|
||||
void SetDitherMode() override;
|
||||
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
|
||||
void SetInterlacingMode() override;
|
||||
void SetViewport() override;
|
||||
|
@ -59,17 +59,14 @@ bool StateTracker::Initialize()
|
||||
m_pipeline_state.depth_stencil_state.test_enable = VK_TRUE;
|
||||
m_pipeline_state.depth_stencil_state.write_enable = VK_TRUE;
|
||||
m_pipeline_state.depth_stencil_state.compare_op = VK_COMPARE_OP_LESS;
|
||||
m_pipeline_state.blend_state.blend_enable = VK_FALSE;
|
||||
m_pipeline_state.blend_state.blend_op = VK_BLEND_OP_ADD;
|
||||
m_pipeline_state.blend_state.src_blend = VK_BLEND_FACTOR_ONE;
|
||||
m_pipeline_state.blend_state.dst_blend = VK_BLEND_FACTOR_ZERO;
|
||||
m_pipeline_state.blend_state.alpha_blend_op = VK_BLEND_OP_ADD;
|
||||
m_pipeline_state.blend_state.src_alpha_blend = VK_BLEND_FACTOR_ONE;
|
||||
m_pipeline_state.blend_state.dst_alpha_blend = VK_BLEND_FACTOR_ZERO;
|
||||
m_pipeline_state.blend_state.logic_op_enable = VK_FALSE;
|
||||
m_pipeline_state.blend_state.logic_op = VK_LOGIC_OP_CLEAR;
|
||||
m_pipeline_state.blend_state.write_mask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
m_pipeline_state.blend_state.hex = 0;
|
||||
m_pipeline_state.blend_state.blendenable = false;
|
||||
m_pipeline_state.blend_state.srcfactor = BlendMode::ONE;
|
||||
m_pipeline_state.blend_state.srcfactoralpha = BlendMode::ONE;
|
||||
m_pipeline_state.blend_state.dstfactor = BlendMode::ZERO;
|
||||
m_pipeline_state.blend_state.dstfactoralpha = BlendMode::ZERO;
|
||||
m_pipeline_state.blend_state.colorupdate = true;
|
||||
m_pipeline_state.blend_state.alphaupdate = true;
|
||||
|
||||
// Enable depth clamping if supported by driver.
|
||||
if (g_ActiveConfig.backend_info.bSupportsDepthClamp)
|
||||
@ -144,7 +141,7 @@ void StateTracker::LoadPipelineUIDCache()
|
||||
void StateTracker::AppendToPipelineUIDCache(const PipelineInfo& info)
|
||||
{
|
||||
SerializedPipelineUID sinfo;
|
||||
sinfo.blend_state_bits = info.blend_state.bits;
|
||||
sinfo.blend_state_bits = info.blend_state.hex;
|
||||
sinfo.rasterizer_state_bits = info.rasterization_state.bits;
|
||||
sinfo.depth_stencil_state_bits = info.depth_stencil_state.bits;
|
||||
sinfo.vertex_decl = m_pipeline_state.vertex_format->GetVertexDeclaration();
|
||||
@ -189,9 +186,9 @@ bool StateTracker::PrecachePipelineUID(const SerializedPipelineUID& uid)
|
||||
return false;
|
||||
}
|
||||
pinfo.render_pass = m_load_render_pass;
|
||||
pinfo.blend_state.bits = uid.blend_state_bits;
|
||||
pinfo.rasterization_state.bits = uid.rasterizer_state_bits;
|
||||
pinfo.depth_stencil_state.bits = uid.depth_stencil_state_bits;
|
||||
pinfo.blend_state.hex = uid.blend_state_bits;
|
||||
pinfo.primitive_topology = uid.primitive_topology;
|
||||
|
||||
VkPipeline pipeline = g_object_cache->GetPipeline(pinfo);
|
||||
@ -295,12 +292,12 @@ void StateTracker::SetDepthStencilState(const DepthStencilState& state)
|
||||
m_dirty_flags |= DIRTY_FLAG_PIPELINE;
|
||||
}
|
||||
|
||||
void StateTracker::SetBlendState(const BlendState& state)
|
||||
void StateTracker::SetBlendState(const BlendingState& state)
|
||||
{
|
||||
if (m_pipeline_state.blend_state.bits == state.bits)
|
||||
if (m_pipeline_state.blend_state.hex == state.hex)
|
||||
return;
|
||||
|
||||
m_pipeline_state.blend_state.bits = state.bits;
|
||||
m_pipeline_state.blend_state.hex = state.hex;
|
||||
m_dirty_flags |= DIRTY_FLAG_PIPELINE;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
{
|
||||
return m_pipeline_state.depth_stencil_state;
|
||||
}
|
||||
const BlendState& GetBlendState() const { return m_pipeline_state.blend_state; }
|
||||
const BlendingState& GetBlendState() const { return m_pipeline_state.blend_state; }
|
||||
void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset);
|
||||
void SetIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType type);
|
||||
|
||||
@ -57,7 +57,7 @@ public:
|
||||
|
||||
void SetRasterizationState(const RasterizationState& state);
|
||||
void SetDepthStencilState(const DepthStencilState& state);
|
||||
void SetBlendState(const BlendState& state);
|
||||
void SetBlendState(const BlendingState& state);
|
||||
|
||||
bool CheckForShaderChanges(u32 gx_primitive_type);
|
||||
|
||||
@ -123,9 +123,9 @@ private:
|
||||
// Serialized version of PipelineInfo, used when loading/saving the pipeline UID cache.
|
||||
struct SerializedPipelineUID
|
||||
{
|
||||
u64 blend_state_bits;
|
||||
u32 rasterizer_state_bits;
|
||||
u32 depth_stencil_state_bits;
|
||||
u32 blend_state_bits;
|
||||
PortableVertexDeclaration vertex_decl;
|
||||
VertexShaderUid vs_uid;
|
||||
GeometryShaderUid gs_uid;
|
||||
|
@ -143,20 +143,17 @@ DepthStencilState GetNoDepthTestingDepthStencilState()
|
||||
return state;
|
||||
}
|
||||
|
||||
BlendState GetNoBlendingBlendState()
|
||||
BlendingState GetNoBlendingBlendState()
|
||||
{
|
||||
BlendState state = {};
|
||||
state.blend_enable = VK_FALSE;
|
||||
state.blend_op = VK_BLEND_OP_ADD;
|
||||
state.src_blend = VK_BLEND_FACTOR_ONE;
|
||||
state.dst_blend = VK_BLEND_FACTOR_ZERO;
|
||||
state.alpha_blend_op = VK_BLEND_OP_ADD;
|
||||
state.src_alpha_blend = VK_BLEND_FACTOR_ONE;
|
||||
state.dst_alpha_blend = VK_BLEND_FACTOR_ZERO;
|
||||
state.logic_op_enable = VK_FALSE;
|
||||
state.logic_op = VK_LOGIC_OP_CLEAR;
|
||||
state.write_mask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
BlendingState state = {};
|
||||
state.blendenable = false;
|
||||
state.srcfactor = BlendMode::ONE;
|
||||
state.srcfactoralpha = BlendMode::ZERO;
|
||||
state.dstfactor = BlendMode::ONE;
|
||||
state.dstfactoralpha = BlendMode::ZERO;
|
||||
state.logicopenable = false;
|
||||
state.colorupdate = true;
|
||||
state.alphaupdate = true;
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -289,7 +286,7 @@ UtilityShaderDraw::UtilityShaderDraw(VkCommandBuffer command_buffer,
|
||||
m_pipeline_info.ps = pixel_shader;
|
||||
m_pipeline_info.rasterization_state.bits = Util::GetNoCullRasterizationState().bits;
|
||||
m_pipeline_info.depth_stencil_state.bits = Util::GetNoDepthTestingDepthStencilState().bits;
|
||||
m_pipeline_info.blend_state.bits = Util::GetNoBlendingBlendState().bits;
|
||||
m_pipeline_info.blend_state.hex = Util::GetNoBlendingBlendState().hex;
|
||||
m_pipeline_info.primitive_topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
}
|
||||
|
||||
@ -397,9 +394,9 @@ void UtilityShaderDraw::SetDepthStencilState(const DepthStencilState& state)
|
||||
m_pipeline_info.depth_stencil_state.bits = state.bits;
|
||||
}
|
||||
|
||||
void UtilityShaderDraw::SetBlendState(const BlendState& state)
|
||||
void UtilityShaderDraw::SetBlendState(const BlendingState& state)
|
||||
{
|
||||
m_pipeline_info.blend_state.bits = state.bits;
|
||||
m_pipeline_info.blend_state.hex = state.hex;
|
||||
}
|
||||
|
||||
void UtilityShaderDraw::BeginRenderPass(VkFramebuffer framebuffer, const VkRect2D& region,
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoBackends/Vulkan/Constants.h"
|
||||
#include "VideoBackends/Vulkan/ObjectCache.h"
|
||||
#include "VideoCommon/RenderState.h"
|
||||
|
||||
namespace Vulkan
|
||||
{
|
||||
@ -35,7 +36,7 @@ VkBlendFactor GetAlphaBlendFactor(VkBlendFactor factor);
|
||||
|
||||
RasterizationState GetNoCullRasterizationState();
|
||||
DepthStencilState GetNoDepthTestingDepthStencilState();
|
||||
BlendState GetNoBlendingBlendState();
|
||||
BlendingState GetNoBlendingBlendState();
|
||||
|
||||
// Combines viewport and scissor updates
|
||||
void SetViewportAndScissor(VkCommandBuffer command_buffer, int x, int y, int width, int height,
|
||||
@ -147,7 +148,7 @@ public:
|
||||
|
||||
void SetRasterizationState(const RasterizationState& state);
|
||||
void SetDepthStencilState(const DepthStencilState& state);
|
||||
void SetBlendState(const BlendState& state);
|
||||
void SetBlendState(const BlendingState& state);
|
||||
|
||||
void BeginRenderPass(VkFramebuffer framebuffer, const VkRect2D& region,
|
||||
const VkClearValue* clear_value = nullptr);
|
||||
|
@ -74,10 +74,7 @@ void SetBlendMode()
|
||||
{
|
||||
g_renderer->SetBlendMode(false);
|
||||
}
|
||||
void SetDitherMode()
|
||||
{
|
||||
g_renderer->SetDitherMode();
|
||||
}
|
||||
|
||||
void SetLogicOpMode()
|
||||
{
|
||||
g_renderer->SetLogicOpMode();
|
||||
|
@ -19,7 +19,6 @@ void SetGenerationMode();
|
||||
void SetScissor();
|
||||
void SetDepthMode();
|
||||
void SetBlendMode();
|
||||
void SetDitherMode();
|
||||
void SetLogicOpMode();
|
||||
void SetColorMask();
|
||||
void ClearScreen(const EFBRectangle& rc);
|
||||
|
@ -152,10 +152,6 @@ static void BPWritten(const BPCmd& bp)
|
||||
if (bp.changes & 0xF002) // logicopenable | logicmode
|
||||
SetLogicOpMode();
|
||||
|
||||
// Set Dithering Mode
|
||||
if (bp.changes & 4) // dither
|
||||
SetDitherMode();
|
||||
|
||||
// Set Color Mask
|
||||
if (bp.changes & 0x18) // colorupdate | alphaupdate
|
||||
SetColorMask();
|
||||
@ -1383,7 +1379,6 @@ void BPReload()
|
||||
SetScissor();
|
||||
SetDepthMode();
|
||||
SetLogicOpMode();
|
||||
SetDitherMode();
|
||||
SetBlendMode();
|
||||
SetColorMask();
|
||||
OnPixelFormatChange();
|
||||
|
@ -69,7 +69,6 @@ public:
|
||||
virtual void SetGenerationMode() {}
|
||||
virtual void SetDepthMode() {}
|
||||
virtual void SetLogicOpMode() {}
|
||||
virtual void SetDitherMode() {}
|
||||
virtual void SetSamplerState(int stage, int texindex, bool custom_tex) {}
|
||||
virtual void SetInterlacingMode() {}
|
||||
virtual void SetViewport() {}
|
||||
|
@ -61,10 +61,10 @@ void BlendingState::Generate(const BPMemory& bp)
|
||||
bool target_has_alpha = bp.zcontrol.pixel_format == PEControl::RGBA6_Z24;
|
||||
bool alpha_test_may_success = bp.alpha_test.TestResult() != AlphaTest::FAIL;
|
||||
|
||||
dither = bp.blendmode.dither;
|
||||
colorupdate = bp.blendmode.colorupdate && alpha_test_may_success;
|
||||
alphaupdate = bp.blendmode.alphaupdate && target_has_alpha && alpha_test_may_success;
|
||||
dstalpha = bp.dstalpha.enable && alphaupdate;
|
||||
usedualsrc = true;
|
||||
|
||||
// The subtract bit has the highest priority
|
||||
if (bp.blendmode.subtract)
|
||||
|
@ -16,11 +16,11 @@ union BlendingState
|
||||
BitField<0, 1, u32> blendenable;
|
||||
BitField<1, 1, u32> logicopenable;
|
||||
BitField<2, 1, u32> dstalpha;
|
||||
BitField<3, 1, u32> dither;
|
||||
BitField<4, 1, u32> colorupdate;
|
||||
BitField<5, 1, u32> alphaupdate;
|
||||
BitField<6, 1, u32> subtract;
|
||||
BitField<7, 1, u32> subtractAlpha;
|
||||
BitField<3, 1, u32> colorupdate;
|
||||
BitField<4, 1, u32> alphaupdate;
|
||||
BitField<5, 1, u32> subtract;
|
||||
BitField<6, 1, u32> subtractAlpha;
|
||||
BitField<7, 1, u32> usedualsrc;
|
||||
BitField<8, 3, BlendMode::BlendFactor> dstfactor;
|
||||
BitField<11, 3, BlendMode::BlendFactor> srcfactor;
|
||||
BitField<14, 3, BlendMode::BlendFactor> dstfactoralpha;
|
||||
|
Loading…
Reference in New Issue
Block a user