2015-10-10 14:41:19 +00:00
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2020-09-16 11:11:39 +00:00
# include <algorithm>
2020-10-04 21:24:14 +00:00
# include "Common/GPU/Vulkan/VulkanLoader.h"
# include "Common/GPU/Vulkan/VulkanRenderManager.h"
2015-10-10 14:41:19 +00:00
2020-10-03 22:25:21 +00:00
# include "Common/Data/Convert/SmallDataConvert.h"
2015-10-10 14:41:19 +00:00
# include "GPU/Math3D.h"
# include "GPU/GPUState.h"
# include "GPU/ge_constants.h"
# include "GPU/Common/GPUStateUtils.h"
# include "Core/System.h"
# include "Core/Config.h"
# include "Core/Reporting.h"
# include "GPU/Vulkan/GPU_Vulkan.h"
# include "GPU/Vulkan/PipelineManagerVulkan.h"
2020-08-03 21:22:11 +00:00
# include "GPU/Vulkan/FramebufferManagerVulkan.h"
2016-01-09 22:27:53 +00:00
# include "GPU/Vulkan/ShaderManagerVulkan.h"
2017-02-17 11:21:27 +00:00
# include "GPU/Vulkan/DrawEngineVulkan.h"
2015-10-10 14:41:19 +00:00
2016-01-09 12:31:36 +00:00
// These tables all fit into u8s.
2015-10-10 14:41:19 +00:00
static const VkBlendFactor vkBlendFactorLookup [ ( size_t ) BlendFactor : : COUNT ] = {
VK_BLEND_FACTOR_ZERO ,
VK_BLEND_FACTOR_ONE ,
VK_BLEND_FACTOR_SRC_COLOR ,
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR ,
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 ,
VK_BLEND_FACTOR_CONSTANT_COLOR ,
VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ,
VK_BLEND_FACTOR_CONSTANT_ALPHA ,
VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA ,
2016-12-26 22:51:17 +00:00
VK_BLEND_FACTOR_SRC1_COLOR ,
VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR ,
2016-03-19 00:57:13 +00:00
VK_BLEND_FACTOR_SRC1_ALPHA ,
VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA ,
2015-10-10 14:41:19 +00:00
VK_BLEND_FACTOR_MAX_ENUM ,
} ;
static const VkBlendOp vkBlendEqLookup [ ( size_t ) BlendEq : : COUNT ] = {
VK_BLEND_OP_ADD ,
VK_BLEND_OP_SUBTRACT ,
VK_BLEND_OP_REVERSE_SUBTRACT ,
VK_BLEND_OP_MIN ,
VK_BLEND_OP_MAX ,
} ;
static const VkCullModeFlagBits cullingMode [ ] = {
VK_CULL_MODE_BACK_BIT ,
VK_CULL_MODE_FRONT_BIT ,
} ;
static const VkCompareOp compareOps [ ] = {
VK_COMPARE_OP_NEVER ,
VK_COMPARE_OP_ALWAYS ,
VK_COMPARE_OP_EQUAL ,
VK_COMPARE_OP_NOT_EQUAL ,
VK_COMPARE_OP_LESS ,
VK_COMPARE_OP_LESS_OR_EQUAL ,
VK_COMPARE_OP_GREATER ,
VK_COMPARE_OP_GREATER_OR_EQUAL ,
} ;
static const VkStencilOp stencilOps [ ] = {
VK_STENCIL_OP_KEEP ,
VK_STENCIL_OP_ZERO ,
VK_STENCIL_OP_REPLACE ,
VK_STENCIL_OP_INVERT ,
VK_STENCIL_OP_INCREMENT_AND_CLAMP ,
VK_STENCIL_OP_DECREMENT_AND_CLAMP ,
VK_STENCIL_OP_KEEP , // reserved
VK_STENCIL_OP_KEEP , // reserved
} ;
2016-03-27 19:39:01 +00:00
static const VkPrimitiveTopology primToVulkan [ 8 ] = {
2016-01-09 16:12:37 +00:00
VK_PRIMITIVE_TOPOLOGY_POINT_LIST ,
VK_PRIMITIVE_TOPOLOGY_LINE_LIST ,
VK_PRIMITIVE_TOPOLOGY_LINE_STRIP ,
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ,
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP ,
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN ,
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , // Vulkan doesn't do quads. We could do strips with restart-index though. We could also do RECT primitives in the geometry shader.
} ;
2016-03-27 19:39:01 +00:00
// These are actually the same exact values/order/etc. as the GE ones, but for clarity...
static const VkLogicOp logicOps [ ] = {
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 ,
} ;
2016-01-09 16:12:37 +00:00
2017-10-31 11:02:10 +00:00
void DrawEngineVulkan : : ResetShaderBlending ( ) {
boundSecondary_ = VK_NULL_HANDLE ;
2015-10-10 14:41:19 +00:00
}
// TODO: Do this more progressively. No need to compute the entire state if the entire state hasn't changed.
// In Vulkan, we simply collect all the state together into a "pipeline key" - we don't actually set any state here
// (the caller is responsible for setting the little dynamic state that is supported, dynState).
2017-02-17 11:21:27 +00:00
void DrawEngineVulkan : : ConvertStateToVulkanKey ( FramebufferManagerVulkan & fbManager , ShaderManagerVulkan * shaderManager , int prim , VulkanPipelineRasterStateKey & key , VulkanDynamicState & dynState ) {
2017-08-15 14:01:50 +00:00
key . topology = primToVulkan [ prim ] ;
2017-08-15 10:02:47 +00:00
2020-04-04 17:51:47 +00:00
bool useBufferedRendering = framebufferManager_ - > UseBufferedRendering ( ) ;
2015-10-10 14:41:19 +00:00
2017-01-30 10:56:14 +00:00
if ( gstate_c . IsDirty ( DIRTY_BLEND_STATE ) ) {
2017-10-31 11:02:10 +00:00
gstate_c . SetAllowShaderBlend ( ! g_Config . bDisableSlowFramebufEffects ) ;
2017-01-30 10:56:14 +00:00
if ( gstate . isModeClear ( ) ) {
key . logicOpEnable = false ;
2017-04-03 15:26:54 +00:00
key . logicOp = VK_LOGIC_OP_CLEAR ;
2017-01-30 10:56:14 +00:00
key . blendEnable = false ;
2017-04-03 15:26:54 +00:00
key . blendOpColor = VK_BLEND_OP_ADD ;
key . blendOpAlpha = VK_BLEND_OP_ADD ;
key . srcColor = VK_BLEND_FACTOR_ONE ;
key . srcAlpha = VK_BLEND_FACTOR_ONE ;
key . destColor = VK_BLEND_FACTOR_ZERO ;
key . destAlpha = VK_BLEND_FACTOR_ZERO ;
2017-01-30 10:56:14 +00:00
dynState . useBlendColor = false ;
// Color Mask
bool colorMask = gstate . isClearModeColorMask ( ) ;
bool alphaMask = gstate . isClearModeAlphaMask ( ) ;
key . colorWriteMask = ( colorMask ? ( VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT ) : 0 ) | ( alphaMask ? VK_COLOR_COMPONENT_A_BIT : 0 ) ;
2015-10-10 14:41:19 +00:00
} else {
2017-11-05 21:26:18 +00:00
if ( gstate_c . Supports ( GPU_SUPPORTS_LOGIC_OP ) & & gstate . isLogicOpEnabled ( ) & & gstate . getLogicOp ( ) ! = GE_LOGIC_COPY ) {
key . logicOpEnable = true ;
key . logicOp = logicOps [ gstate . getLogicOp ( ) ] ;
} else {
key . logicOpEnable = false ;
key . logicOp = VK_LOGIC_OP_CLEAR ;
}
2017-05-22 14:16:09 +00:00
2017-01-30 10:56:14 +00:00
// Set blend - unless we need to do it in the shader.
GenericBlendState blendState ;
ConvertBlendState ( blendState , gstate_c . allowShaderBlend ) ;
if ( blendState . applyShaderBlending ) {
if ( ApplyShaderBlending ( ) ) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp ( blendState . replaceAlphaWithStencil , blendState ) ;
} else {
// Until next time, force it off.
ResetShaderBlending ( ) ;
2017-04-03 15:04:58 +00:00
gstate_c . SetAllowShaderBlend ( false ) ;
2020-03-29 12:51:54 +00:00
// Make sure we recompute the fragment shader ID to one that doesn't try to use shader blending.
gstate_c . Dirty ( DIRTY_FRAGMENTSHADER_STATE ) ;
2017-01-30 10:56:14 +00:00
}
} else if ( blendState . resetShaderBlending ) {
ResetShaderBlending ( ) ;
}
2015-10-10 14:41:19 +00:00
2017-01-30 10:56:14 +00:00
if ( blendState . enabled ) {
key . blendEnable = true ;
key . blendOpColor = vkBlendEqLookup [ ( size_t ) blendState . eqColor ] ;
key . blendOpAlpha = vkBlendEqLookup [ ( size_t ) blendState . eqAlpha ] ;
key . srcColor = vkBlendFactorLookup [ ( size_t ) blendState . srcColor ] ;
key . srcAlpha = vkBlendFactorLookup [ ( size_t ) blendState . srcAlpha ] ;
key . destColor = vkBlendFactorLookup [ ( size_t ) blendState . dstColor ] ;
key . destAlpha = vkBlendFactorLookup [ ( size_t ) blendState . dstAlpha ] ;
if ( blendState . dirtyShaderBlend ) {
gstate_c . Dirty ( DIRTY_SHADERBLEND ) ;
}
dynState . useBlendColor = blendState . useBlendColor ;
if ( blendState . useBlendColor ) {
dynState . blendColor = blendState . blendColor ;
}
} else {
key . blendEnable = false ;
2017-04-03 15:26:54 +00:00
key . blendOpColor = VK_BLEND_OP_ADD ;
key . blendOpAlpha = VK_BLEND_OP_ADD ;
key . srcColor = VK_BLEND_FACTOR_ONE ;
key . srcAlpha = VK_BLEND_FACTOR_ONE ;
key . destColor = VK_BLEND_FACTOR_ZERO ;
key . destAlpha = VK_BLEND_FACTOR_ZERO ;
2017-01-30 10:56:14 +00:00
dynState . useBlendColor = false ;
}
// PSP color/alpha mask is per bit but we can only support per byte.
// But let's do that, at least. And let's try a threshold.
bool rmask = ( gstate . pmskc & 0xFF ) < 128 ;
bool gmask = ( ( gstate . pmskc > > 8 ) & 0xFF ) < 128 ;
bool bmask = ( ( gstate . pmskc > > 16 ) & 0xFF ) < 128 ;
bool amask = ( gstate . pmska & 0xFF ) < 128 ;
# ifndef MOBILE_DEVICE
u8 abits = ( gstate . pmska > > 0 ) & 0xFF ;
u8 rbits = ( gstate . pmskc > > 0 ) & 0xFF ;
u8 gbits = ( gstate . pmskc > > 8 ) & 0xFF ;
u8 bbits = ( gstate . pmskc > > 16 ) & 0xFF ;
if ( ( rbits ! = 0 & & rbits ! = 0xFF ) | | ( gbits ! = 0 & & gbits ! = 0xFF ) | | ( bbits ! = 0 & & bbits ! = 0xFF ) ) {
WARN_LOG_REPORT_ONCE ( rgbmask , G3D , " Unsupported RGB mask: r=%02x g=%02x b=%02x " , rbits , gbits , bbits ) ;
}
if ( abits ! = 0 & & abits ! = 0xFF ) {
// The stencil part of the mask is supported.
WARN_LOG_REPORT_ONCE ( amask , G3D , " Unsupported alpha/stencil mask: %02x " , abits ) ;
}
# endif
// Let's not write to alpha if stencil isn't enabled.
2018-12-01 22:05:29 +00:00
if ( IsStencilTestOutputDisabled ( ) ) {
2017-01-30 10:56:14 +00:00
amask = false ;
} else {
// If the stencil type is set to KEEP, we shouldn't write to the stencil/alpha channel.
if ( ReplaceAlphaWithStencilType ( ) = = STENCIL_VALUE_KEEP ) {
amask = false ;
}
}
key . colorWriteMask = ( rmask ? VK_COLOR_COMPONENT_R_BIT : 0 ) | ( gmask ? VK_COLOR_COMPONENT_G_BIT : 0 ) | ( bmask ? VK_COLOR_COMPONENT_B_BIT : 0 ) | ( amask ? VK_COLOR_COMPONENT_A_BIT : 0 ) ;
2018-12-22 17:29:56 +00:00
2018-12-23 10:57:06 +00:00
// Workaround proposed in #10421, for bug where the color write mask is not applied correctly on Adreno.
2020-05-20 05:12:30 +00:00
if ( ( gstate . pmskc & 0x00FFFFFF ) = = 0x00FFFFFF & & g_Config . bVendorBugChecksEnabled & & draw_ - > GetBugs ( ) . Has ( Draw : : Bugs : : COLORWRITEMASK_BROKEN_WITH_DEPTHTEST ) ) {
2018-12-22 17:29:56 +00:00
key . colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT ;
2018-12-23 10:57:06 +00:00
if ( ! key . blendEnable ) {
key . blendEnable = true ;
key . blendOpAlpha = VK_BLEND_OP_ADD ;
key . srcAlpha = VK_BLEND_FACTOR_ZERO ;
key . destAlpha = VK_BLEND_FACTOR_ONE ;
}
2018-12-22 17:29:56 +00:00
key . blendOpColor = VK_BLEND_OP_ADD ;
key . srcColor = VK_BLEND_FACTOR_ZERO ;
key . destColor = VK_BLEND_FACTOR_ONE ;
}
2015-10-10 14:41:19 +00:00
}
}
2017-01-30 11:07:26 +00:00
if ( gstate_c . IsDirty ( DIRTY_RASTER_STATE ) ) {
2020-09-08 22:52:01 +00:00
bool wantCull = ! gstate . isModeClear ( ) & & prim ! = GE_PRIM_RECTANGLES & & gstate . isCullEnabled ( ) ;
key . cullMode = wantCull ? ( gstate . getCullMode ( ) ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT ) : VK_CULL_MODE_NONE ;
2018-09-18 04:43:29 +00:00
if ( gstate . isModeClear ( ) | | gstate . isModeThrough ( ) ) {
// TODO: Might happen in clear mode if not through...
2017-12-27 00:35:14 +00:00
key . depthClampEnable = false ;
2017-04-03 14:19:10 +00:00
} else {
// Set cull
2018-09-18 04:43:29 +00:00
if ( gstate . getDepthRangeMin ( ) = = 0 | | gstate . getDepthRangeMax ( ) = = 65535 ) {
// TODO: Still has a bug where we clamp to depth range if one is not the full range.
// But the alternate is not clamping in either direction...
key . depthClampEnable = gstate . isDepthClampEnabled ( ) & & gstate_c . Supports ( GPU_SUPPORTS_DEPTH_CLAMP ) ;
} else {
// We just want to clip in this case, the clamp would be clipped anyway.
key . depthClampEnable = false ;
}
2017-04-03 14:19:10 +00:00
}
}
2015-10-10 14:41:19 +00:00
2017-01-30 11:02:14 +00:00
if ( gstate_c . IsDirty ( DIRTY_DEPTHSTENCIL_STATE ) ) {
2017-04-03 14:19:10 +00:00
if ( gstate . isModeClear ( ) ) {
2017-01-30 11:02:14 +00:00
key . depthTestEnable = true ;
key . depthCompareOp = VK_COMPARE_OP_ALWAYS ;
key . depthWriteEnable = gstate . isClearModeDepthMask ( ) ;
if ( gstate . isClearModeDepthMask ( ) ) {
fbManager . SetDepthUpdated ( ) ;
}
2015-10-10 14:41:19 +00:00
2017-01-30 11:02:14 +00:00
// Stencil Test
bool alphaMask = gstate . isClearModeAlphaMask ( ) ;
if ( alphaMask ) {
key . stencilTestEnable = true ;
key . stencilCompareOp = VK_COMPARE_OP_ALWAYS ;
key . stencilPassOp = VK_STENCIL_OP_REPLACE ;
key . stencilFailOp = VK_STENCIL_OP_REPLACE ;
key . stencilDepthFailOp = VK_STENCIL_OP_REPLACE ;
dynState . useStencil = true ;
// In clear mode, the stencil value is set to the alpha value of the vertex.
// A normal clear will be 2 points, the second point has the color.
// We override this value in the pipeline from software transform for clear rectangles.
dynState . stencilRef = 0xFF ;
2019-03-17 02:42:18 +00:00
// But we still apply the stencil write mask.
dynState . stencilWriteMask = ( ~ gstate . getStencilWriteMask ( ) ) & 0xFF ;
2016-03-27 19:39:01 +00:00
} else {
2017-01-30 11:02:14 +00:00
key . stencilTestEnable = false ;
2017-04-03 15:26:54 +00:00
key . stencilCompareOp = VK_COMPARE_OP_ALWAYS ;
key . stencilPassOp = VK_STENCIL_OP_REPLACE ;
key . stencilFailOp = VK_STENCIL_OP_REPLACE ;
key . stencilDepthFailOp = VK_STENCIL_OP_REPLACE ;
2017-01-30 11:02:14 +00:00
dynState . useStencil = false ;
}
} else {
// Depth Test
if ( gstate . isDepthTestEnabled ( ) ) {
key . depthTestEnable = true ;
key . depthCompareOp = compareOps [ gstate . getDepthTestFunction ( ) ] ;
key . depthWriteEnable = gstate . isDepthWriteEnabled ( ) ;
if ( gstate . isDepthWriteEnabled ( ) ) {
fbManager . SetDepthUpdated ( ) ;
}
} else {
key . depthTestEnable = false ;
key . depthWriteEnable = false ;
key . depthCompareOp = VK_COMPARE_OP_ALWAYS ;
2015-10-10 14:41:19 +00:00
}
2017-01-30 11:02:14 +00:00
GenericStencilFuncState stencilState ;
ConvertStencilFuncState ( stencilState ) ;
// Stencil Test
if ( stencilState . enabled ) {
key . stencilTestEnable = true ;
key . stencilCompareOp = compareOps [ stencilState . testFunc ] ;
key . stencilPassOp = stencilOps [ stencilState . zPass ] ;
key . stencilFailOp = stencilOps [ stencilState . sFail ] ;
key . stencilDepthFailOp = stencilOps [ stencilState . zFail ] ;
dynState . useStencil = true ;
dynState . stencilRef = stencilState . testRef ;
dynState . stencilCompareMask = stencilState . testMask ;
dynState . stencilWriteMask = stencilState . writeMask ;
} else {
key . stencilTestEnable = false ;
2017-04-03 15:26:54 +00:00
key . stencilCompareOp = VK_COMPARE_OP_ALWAYS ;
key . stencilPassOp = VK_STENCIL_OP_REPLACE ;
key . stencilFailOp = VK_STENCIL_OP_REPLACE ;
key . stencilDepthFailOp = VK_STENCIL_OP_REPLACE ;
2017-01-30 11:02:14 +00:00
dynState . useStencil = false ;
}
2015-10-10 14:41:19 +00:00
}
}
2017-01-30 11:22:35 +00:00
if ( gstate_c . IsDirty ( DIRTY_VIEWPORTSCISSOR_STATE ) ) {
2017-01-30 11:02:14 +00:00
ViewportAndScissor vpAndScissor ;
ConvertViewportAndScissor ( useBufferedRendering ,
fbManager . GetRenderWidth ( ) , fbManager . GetRenderHeight ( ) ,
fbManager . GetTargetBufferWidth ( ) , fbManager . GetTargetBufferHeight ( ) ,
vpAndScissor ) ;
2017-08-15 08:38:20 +00:00
float depthMin = vpAndScissor . depthRangeMin ;
float depthMax = vpAndScissor . depthRangeMax ;
if ( depthMin < 0.0f ) depthMin = 0.0f ;
if ( depthMax > 1.0f ) depthMax = 1.0f ;
if ( vpAndScissor . dirtyDepth ) {
gstate_c . Dirty ( DIRTY_DEPTHRANGE ) ;
}
2017-01-30 11:02:14 +00:00
VkViewport & vp = dynState . viewport ;
vp . x = vpAndScissor . viewportX ;
vp . y = vpAndScissor . viewportY ;
vp . width = vpAndScissor . viewportW ;
vp . height = vpAndScissor . viewportH ;
vp . minDepth = vpAndScissor . depthRangeMin ;
vp . maxDepth = vpAndScissor . depthRangeMax ;
2017-08-15 08:38:20 +00:00
2017-01-30 11:02:14 +00:00
if ( vpAndScissor . dirtyProj ) {
gstate_c . Dirty ( DIRTY_PROJMATRIX ) ;
}
2015-10-10 14:41:19 +00:00
2017-01-30 11:02:14 +00:00
VkRect2D & scissor = dynState . scissor ;
2017-05-19 15:21:08 +00:00
if ( vpAndScissor . scissorEnable ) {
scissor . offset . x = vpAndScissor . scissorX ;
scissor . offset . y = vpAndScissor . scissorY ;
2017-08-15 08:38:20 +00:00
scissor . extent . width = std : : max ( 0 , vpAndScissor . scissorW ) ;
scissor . extent . height = std : : max ( 0 , vpAndScissor . scissorH ) ;
2017-05-19 15:21:08 +00:00
} else {
scissor . offset . x = 0 ;
scissor . offset . y = 0 ;
scissor . extent . width = framebufferManager_ - > GetRenderWidth ( ) ;
scissor . extent . height = framebufferManager_ - > GetRenderHeight ( ) ;
}
2015-10-10 14:41:19 +00:00
}
}
2017-05-23 22:45:15 +00:00
2017-11-15 19:43:29 +00:00
void DrawEngineVulkan : : BindShaderBlendTex ( ) {
2017-05-23 22:45:15 +00:00
// At this point, we know if the vertices are full alpha or not.
// TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)?
if ( ! gstate . isModeClear ( ) ) {
// TODO: Test texture?
if ( fboTexNeedBind_ ) {
// Note that this is positions, not UVs, that we need the copy from.
framebufferManager_ - > BindFramebufferAsColorTexture ( 1 , framebufferManager_ - > GetCurrentRenderVFB ( ) , BINDFBCOLOR_MAY_COPY ) ;
// If we are rendering at a higher resolution, linear is probably best for the dest color.
2017-10-31 11:02:10 +00:00
boundSecondary_ = ( VkImageView ) draw_ - > GetNativeObject ( Draw : : NativeObject : : BOUND_TEXTURE1_IMAGEVIEW ) ;
2017-05-23 22:45:15 +00:00
fboTexBound_ = true ;
fboTexNeedBind_ = false ;
}
}
2017-08-14 12:35:26 +00:00
2017-11-15 19:43:29 +00:00
}
void DrawEngineVulkan : : ApplyDrawStateLate ( VulkanRenderManager * renderManager , bool applyStencilRef , uint8_t stencilRef , bool useBlendConstant ) {
2017-08-14 12:35:26 +00:00
if ( gstate_c . IsDirty ( DIRTY_VIEWPORTSCISSOR_STATE ) ) {
2017-08-22 11:25:45 +00:00
renderManager - > SetScissor ( dynState_ . scissor ) ;
renderManager - > SetViewport ( dynState_ . viewport ) ;
2017-08-14 12:35:26 +00:00
}
2017-08-22 11:25:45 +00:00
if ( ( gstate_c . IsDirty ( DIRTY_DEPTHSTENCIL_STATE ) & & dynState_ . useStencil ) | | applyStencilRef ) {
renderManager - > SetStencilParams ( dynState_ . stencilWriteMask , dynState_ . stencilCompareMask , applyStencilRef ? stencilRef : dynState_ . stencilRef ) ;
2017-08-14 12:35:26 +00:00
}
2017-10-20 16:09:05 +00:00
if ( gstate_c . IsDirty ( DIRTY_BLEND_STATE ) & & useBlendConstant ) {
2019-10-13 19:15:01 +00:00
renderManager - > SetBlendFactor ( dynState_ . blendColor ) ;
2017-08-14 12:35:26 +00:00
}
2017-10-20 16:09:05 +00:00
}