2015-10-24 21:24:06 +00:00
# include <string>
# include <sstream>
2020-10-04 21:24:14 +00:00
# include "Common/GPU/thin3d.h"
2015-10-24 21:24:06 +00:00
# include "Common/StringUtils.h"
2022-04-16 21:47:05 +00:00
# include "Core/System.h"
2015-10-24 21:24:06 +00:00
# include "Core/Config.h"
# include "GPU/ge_constants.h"
2022-07-31 11:01:50 +00:00
# include "GPU/GPU.h"
2015-10-24 21:24:06 +00:00
# include "GPU/GPUState.h"
2015-10-24 21:49:05 +00:00
# include "GPU/Common/GPUStateUtils.h"
2015-10-24 21:24:06 +00:00
# include "GPU/Common/ShaderId.h"
# include "GPU/Common/VertexDecoderCommon.h"
2019-02-16 14:54:56 +00:00
std : : string VertexShaderDesc ( const VShaderID & id ) {
2015-10-24 21:24:06 +00:00
std : : stringstream desc ;
desc < < StringFromFormat ( " %08x:%08x " , id . d [ 1 ] , id . d [ 0 ] ) ;
if ( id . Bit ( VS_BIT_IS_THROUGH ) ) desc < < " THR " ;
if ( id . Bit ( VS_BIT_USE_HW_TRANSFORM ) ) desc < < " HWX " ;
if ( id . Bit ( VS_BIT_HAS_COLOR ) ) desc < < " C " ;
if ( id . Bit ( VS_BIT_HAS_TEXCOORD ) ) desc < < " T " ;
if ( id . Bit ( VS_BIT_HAS_NORMAL ) ) desc < < " N " ;
if ( id . Bit ( VS_BIT_LMODE ) ) desc < < " LM " ;
if ( id . Bit ( VS_BIT_NORM_REVERSE ) ) desc < < " RevN " ;
if ( id . Bit ( VS_BIT_DO_TEXTURE ) ) desc < < " Tex " ;
2020-11-01 10:48:55 +00:00
int uvgMode = id . Bits ( VS_BIT_UVGEN_MODE , 2 ) ;
if ( uvgMode = = GE_TEXMAP_TEXTURE_MATRIX ) {
2017-12-01 19:17:12 +00:00
int uvprojMode = id . Bits ( VS_BIT_UVPROJ_MODE , 2 ) ;
const char * uvprojModes [ 4 ] = { " TexProjPos " , " TexProjUV " , " TexProjNNrm " , " TexProjNrm " } ;
desc < < uvprojModes [ uvprojMode ] ;
}
2015-10-24 21:24:06 +00:00
const char * uvgModes [ 4 ] = { " UV " , " UVMtx " , " UVEnv " , " UVUnk " } ;
int ls0 = id . Bits ( VS_BIT_LS0 , 2 ) ;
int ls1 = id . Bits ( VS_BIT_LS1 , 2 ) ;
if ( uvgMode ) desc < < uvgModes [ uvgMode ] ;
2018-04-10 10:22:02 +00:00
if ( id . Bit ( VS_BIT_ENABLE_BONES ) ) desc < < " Bones: " < < ( id . Bits ( VS_BIT_BONES , 3 ) + 1 ) < < " " ;
2015-10-24 21:24:06 +00:00
// Lights
if ( id . Bit ( VS_BIT_LIGHTING_ENABLE ) ) {
desc < < " Light: " ;
2016-12-21 14:50:20 +00:00
}
2022-09-25 11:59:52 +00:00
if ( id . Bit ( VS_BIT_LIGHT_UBERSHADER ) ) {
desc < < " LightUberShader " ;
}
2016-12-21 14:50:20 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
bool enabled = id . Bit ( VS_BIT_LIGHT0_ENABLE + i ) & & id . Bit ( VS_BIT_LIGHTING_ENABLE ) ;
if ( enabled | | ( uvgMode = = GE_TEXMAP_ENVIRONMENT_MAP & & ( ls0 = = i | | ls1 = = i ) ) ) {
desc < < i < < " : " ;
desc < < " c: " < < id . Bits ( VS_BIT_LIGHT0_COMP + 4 * i , 2 ) < < " t: " < < id . Bits ( VS_BIT_LIGHT0_TYPE + 4 * i , 2 ) < < " " ;
2015-10-24 21:24:06 +00:00
}
}
if ( id . Bits ( VS_BIT_MATERIAL_UPDATE , 3 ) ) desc < < " MatUp: " < < id . Bits ( VS_BIT_MATERIAL_UPDATE , 3 ) < < " " ;
2018-04-10 09:22:58 +00:00
if ( id . Bits ( VS_BIT_WEIGHT_FMTSCALE , 2 ) ) desc < < " WScale " < < id . Bits ( VS_BIT_WEIGHT_FMTSCALE , 2 ) < < " " ;
2015-10-24 21:24:06 +00:00
if ( id . Bit ( VS_BIT_FLATSHADE ) ) desc < < " Flat " ;
2017-01-06 16:21:17 +00:00
if ( id . Bit ( VS_BIT_BEZIER ) ) desc < < " Bezier " ;
if ( id . Bit ( VS_BIT_SPLINE ) ) desc < < " Spline " ;
if ( id . Bit ( VS_BIT_HAS_COLOR_TESS ) ) desc < < " TessC " ;
if ( id . Bit ( VS_BIT_HAS_TEXCOORD_TESS ) ) desc < < " TessT " ;
2018-07-17 15:52:20 +00:00
if ( id . Bit ( VS_BIT_HAS_NORMAL_TESS ) ) desc < < " TessN " ;
2017-01-06 16:21:17 +00:00
if ( id . Bit ( VS_BIT_NORM_REVERSE_TESS ) ) desc < < " TessRevN " ;
2020-12-13 15:04:16 +00:00
if ( id . Bit ( VS_BIT_VERTEX_RANGE_CULLING ) ) desc < < " Cull " ;
2017-01-06 16:21:17 +00:00
2022-10-23 09:21:35 +00:00
if ( id . Bit ( VS_BIT_SIMPLE_STEREO ) ) desc < < " SimpleStereo " ;
2015-10-24 21:24:06 +00:00
return desc . str ( ) ;
}
2022-11-06 16:40:54 +00:00
void ComputeVertexShaderID ( VShaderID * id_out , u32 vertType , bool useHWTransform , bool useHWTessellation , bool weightsAsFloat , bool useSkinInDecode ) {
2018-12-02 22:02:46 +00:00
bool isModeThrough = ( vertType & GE_VTYPE_THROUGH ) ! = 0 ;
2015-10-24 21:24:06 +00:00
bool doTexture = gstate . isTextureMapEnabled ( ) & & ! gstate . isModeClear ( ) ;
bool doShadeMapping = doTexture & & ( gstate . getUVGenMode ( ) = = GE_TEXMAP_ENVIRONMENT_MAP ) ;
bool doFlatShading = gstate . getShadeMode ( ) = = GE_SHADE_FLAT & & ! gstate . isModeClear ( ) ;
bool hasColor = ( vertType & GE_VTYPE_COL_MASK ) ! = 0 ;
bool hasNormal = ( vertType & GE_VTYPE_NRM_MASK ) ! = 0 ;
bool hasTexcoord = ( vertType & GE_VTYPE_TC_MASK ) ! = 0 ;
2017-01-06 16:21:17 +00:00
2020-12-13 15:04:16 +00:00
bool doBezier = gstate_c . submitType = = SubmitType : : HW_BEZIER ;
bool doSpline = gstate_c . submitType = = SubmitType : : HW_SPLINE ;
2017-01-06 16:21:17 +00:00
2021-09-07 21:52:06 +00:00
if ( doBezier | | doSpline ) {
_assert_ ( hasNormal ) ;
}
2022-05-02 22:05:39 +00:00
bool lmode = gstate . isUsingSecondaryColor ( ) & & gstate . isLightingEnabled ( ) & & ! isModeThrough & & ! gstate . isModeClear ( ) ;
2022-10-17 06:30:27 +00:00
bool vertexRangeCulling = gstate_c . Use ( GPU_USE_VS_RANGE_CULLING ) & &
2020-12-13 15:04:16 +00:00
! isModeThrough & & gstate_c . submitType = = SubmitType : : DRAW ; // neither hw nor sw spline/bezier. See #11692
2015-10-24 21:24:06 +00:00
2019-02-16 14:54:56 +00:00
VShaderID id ;
2015-10-24 21:24:06 +00:00
id . SetBit ( VS_BIT_LMODE , lmode ) ;
2022-05-02 22:05:39 +00:00
id . SetBit ( VS_BIT_IS_THROUGH , isModeThrough ) ;
2015-10-24 21:24:06 +00:00
id . SetBit ( VS_BIT_HAS_COLOR , hasColor ) ;
2020-12-13 15:04:16 +00:00
id . SetBit ( VS_BIT_VERTEX_RANGE_CULLING , vertexRangeCulling ) ;
2015-10-24 21:24:06 +00:00
2022-10-23 09:21:35 +00:00
if ( ! isModeThrough & & gstate_c . Use ( GPU_USE_SINGLE_PASS_STEREO ) ) {
2022-10-22 15:34:23 +00:00
id . SetBit ( VS_BIT_SIMPLE_STEREO ) ;
}
2015-10-24 21:24:06 +00:00
if ( doTexture ) {
id . SetBit ( VS_BIT_DO_TEXTURE ) ;
2021-10-17 06:41:24 +00:00
// UV generation mode. doShadeMapping is implicitly stored here.
id . SetBits ( VS_BIT_UVGEN_MODE , 2 , gstate . getUVGenMode ( ) ) ;
2015-10-24 21:24:06 +00:00
}
if ( useHWTransform ) {
id . SetBit ( VS_BIT_USE_HW_TRANSFORM ) ;
id . SetBit ( VS_BIT_HAS_NORMAL , hasNormal ) ;
// The next bits are used differently depending on UVgen mode
2020-11-01 10:48:55 +00:00
if ( gstate . getUVGenMode ( ) = = GE_TEXMAP_TEXTURE_MATRIX ) {
2015-10-24 21:24:06 +00:00
id . SetBits ( VS_BIT_UVPROJ_MODE , 2 , gstate . getUVProjMode ( ) ) ;
} else if ( doShadeMapping ) {
id . SetBits ( VS_BIT_LS0 , 2 , gstate . getUVLS0 ( ) ) ;
id . SetBits ( VS_BIT_LS1 , 2 , gstate . getUVLS1 ( ) ) ;
}
2018-04-10 10:22:02 +00:00
// Bones.
2022-11-06 16:40:54 +00:00
bool enableBones = ! useSkinInDecode & & vertTypeIsSkinningEnabled ( vertType ) ;
2018-04-10 10:22:02 +00:00
id . SetBit ( VS_BIT_ENABLE_BONES , enableBones ) ;
if ( enableBones ) {
id . SetBits ( VS_BIT_BONES , 3 , TranslateNumBones ( vertTypeGetNumBoneWeights ( vertType ) ) - 1 ) ;
// 2 bits. We should probably send in the weight scalefactor as a uniform instead,
// or simply preconvert all weights to floats.
2021-01-10 16:51:15 +00:00
id . SetBits ( VS_BIT_WEIGHT_FMTSCALE , 2 , weightsAsFloat ? 0 : ( vertType & GE_VTYPE_WEIGHT_MASK ) > > GE_VTYPE_WEIGHT_SHIFT ) ;
2018-04-10 10:22:02 +00:00
}
2018-12-02 22:02:46 +00:00
if ( gstate . isLightingEnabled ( ) ) {
// doShadeMapping is stored as UVGenMode, and light type doesn't matter for shade mapping.
id . SetBit ( VS_BIT_LIGHTING_ENABLE ) ;
2022-10-17 06:27:49 +00:00
if ( gstate_c . Use ( GPU_USE_LIGHT_UBERSHADER ) ) {
2022-09-25 11:59:52 +00:00
id . SetBit ( VS_BIT_LIGHT_UBERSHADER ) ;
} else {
2022-09-26 09:20:17 +00:00
id . SetBits ( VS_BIT_MATERIAL_UPDATE , 3 , gstate . getMaterialUpdate ( ) ) ;
2022-09-25 11:59:52 +00:00
// Light bits
for ( int i = 0 ; i < 4 ; i + + ) {
bool chanEnabled = gstate . isLightChanEnabled ( i ) ! = 0 ;
id . SetBit ( VS_BIT_LIGHT0_ENABLE + i , chanEnabled ) ;
if ( chanEnabled ) {
id . SetBits ( VS_BIT_LIGHT0_COMP + 4 * i , 2 , gstate . getLightComputation ( i ) ) ;
id . SetBits ( VS_BIT_LIGHT0_TYPE + 4 * i , 2 , gstate . getLightType ( i ) ) ;
}
2015-10-24 21:24:06 +00:00
}
}
}
id . SetBit ( VS_BIT_NORM_REVERSE , gstate . areNormalsReversed ( ) ) ;
2015-10-25 04:26:12 +00:00
id . SetBit ( VS_BIT_HAS_TEXCOORD , hasTexcoord ) ;
2017-01-06 16:21:17 +00:00
2020-04-04 18:52:32 +00:00
if ( useHWTessellation ) {
2017-01-22 14:47:19 +00:00
id . SetBit ( VS_BIT_BEZIER , doBezier ) ;
id . SetBit ( VS_BIT_SPLINE , doSpline ) ;
2019-09-28 22:08:37 +00:00
if ( doBezier | | doSpline ) {
// These are the original vertType's values (normalized will always have colors, etc.)
id . SetBit ( VS_BIT_HAS_COLOR_TESS , ( gstate . vertType & GE_VTYPE_COL_MASK ) ! = 0 ) ;
id . SetBit ( VS_BIT_HAS_TEXCOORD_TESS , ( gstate . vertType & GE_VTYPE_TC_MASK ) ! = 0 ) ;
id . SetBit ( VS_BIT_HAS_NORMAL_TESS , ( gstate . vertType & GE_VTYPE_NRM_MASK ) ! = 0 | | gstate . isLightingEnabled ( ) ) ;
}
2017-01-22 14:47:19 +00:00
id . SetBit ( VS_BIT_NORM_REVERSE_TESS , gstate . isPatchNormalsReversed ( ) ) ;
}
2015-10-24 21:24:06 +00:00
}
id . SetBit ( VS_BIT_FLATSHADE , doFlatShading ) ;
2017-12-01 10:16:44 +00:00
// These two bits cannot be combined, otherwise havoc occurs. We get reports that indicate this happened somehow... "ERROR: 0:14: 'u_proj' : undeclared identifier"
2020-07-19 15:47:02 +00:00
_dbg_assert_msg_ ( ! id . Bit ( VS_BIT_USE_HW_TRANSFORM ) | | ! id . Bit ( VS_BIT_IS_THROUGH ) , " Can't have both THROUGH and USE_HW_TRANSFORM together! " ) ;
2017-12-01 10:16:44 +00:00
2015-10-24 21:24:06 +00:00
* id_out = id ;
}
2015-10-24 21:49:05 +00:00
static const char * alphaTestFuncs [ ] = { " NEVER " , " ALWAYS " , " == " , " != " , " < " , " <= " , " > " , " >= " } ;
2017-01-30 15:01:00 +00:00
static bool MatrixNeedsProjection ( const float m [ 12 ] ) {
return m [ 2 ] ! = 0.0f | | m [ 5 ] ! = 0.0f | | m [ 8 ] ! = 0.0f | | m [ 11 ] ! = 1.0f ;
}
2019-02-16 14:54:56 +00:00
std : : string FragmentShaderDesc ( const FShaderID & id ) {
2015-10-24 21:49:05 +00:00
std : : stringstream desc ;
desc < < StringFromFormat ( " %08x:%08x " , id . d [ 1 ] , id . d [ 0 ] ) ;
if ( id . Bit ( FS_BIT_CLEARMODE ) ) desc < < " Clear " ;
2022-07-25 16:51:08 +00:00
if ( id . Bit ( FS_BIT_DO_TEXTURE ) ) desc < < ( id . Bit ( FS_BIT_3D_TEXTURE ) ? " Tex3D " : " Tex " ) ;
2015-10-24 21:49:05 +00:00
if ( id . Bit ( FS_BIT_DO_TEXTURE_PROJ ) ) desc < < " TexProj " ;
if ( id . Bit ( FS_BIT_TEXALPHA ) ) desc < < " TexAlpha " ;
if ( id . Bit ( FS_BIT_TEXTURE_AT_OFFSET ) ) desc < < " TexOffs " ;
if ( id . Bit ( FS_BIT_LMODE ) ) desc < < " LM " ;
if ( id . Bit ( FS_BIT_ENABLE_FOG ) ) desc < < " Fog " ;
if ( id . Bit ( FS_BIT_COLOR_DOUBLE ) ) desc < < " 2x " ;
if ( id . Bit ( FS_BIT_FLATSHADE ) ) desc < < " Flat " ;
2015-10-24 22:34:23 +00:00
if ( id . Bit ( FS_BIT_BGRA_TEXTURE ) ) desc < < " BGRA " ;
2022-09-11 16:23:57 +00:00
switch ( ( ShaderDepalMode ) id . Bits ( FS_BIT_SHADER_DEPAL_MODE , 2 ) ) {
2022-09-11 12:14:18 +00:00
case ShaderDepalMode : : OFF : break ;
case ShaderDepalMode : : NORMAL : desc < < " Depal " ; break ;
case ShaderDepalMode : : SMOOTHED : desc < < " SmoothDepal " ; break ;
case ShaderDepalMode : : CLUT8_8888 : desc < < " CLUT8From8888Depal " ; break ;
}
2020-11-08 22:17:06 +00:00
if ( id . Bit ( FS_BIT_COLOR_WRITEMASK ) ) desc < < " WriteMask " ;
2015-10-24 21:49:05 +00:00
if ( id . Bit ( FS_BIT_SHADER_TEX_CLAMP ) ) {
desc < < " TClamp " ;
if ( id . Bit ( FS_BIT_CLAMP_S ) ) desc < < " S " ;
if ( id . Bit ( FS_BIT_CLAMP_T ) ) desc < < " T " ;
desc < < " " ;
}
2022-04-24 18:53:09 +00:00
int blendBits = id . Bits ( FS_BIT_REPLACE_BLEND , 3 ) ;
if ( blendBits ) {
switch ( blendBits ) {
case ReplaceBlendType : : REPLACE_BLEND_BLUE_TO_ALPHA :
2022-04-24 20:54:08 +00:00
desc < < " BlueToAlpha_ " < < " A: " < < id . Bits ( FS_BIT_BLENDFUNC_A , 4 ) ;
2022-04-24 18:53:09 +00:00
break ;
default :
desc < < " ReplaceBlend_ " < < id . Bits ( FS_BIT_REPLACE_BLEND , 3 )
< < " A: " < < id . Bits ( FS_BIT_BLENDFUNC_A , 4 )
< < " _B: " < < id . Bits ( FS_BIT_BLENDFUNC_B , 4 )
< < " _Eq: " < < id . Bits ( FS_BIT_BLENDEQ , 3 ) < < " " ;
break ;
}
2015-10-24 21:49:05 +00:00
}
switch ( id . Bits ( FS_BIT_STENCIL_TO_ALPHA , 2 ) ) {
case REPLACE_ALPHA_NO : break ;
case REPLACE_ALPHA_YES : desc < < " StenToAlpha " ; break ;
case REPLACE_ALPHA_DUALSOURCE : desc < < " StenToAlphaDual " ; break ;
}
if ( id . Bits ( FS_BIT_STENCIL_TO_ALPHA , 2 ) ! = REPLACE_ALPHA_NO ) {
switch ( id . Bits ( FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE , 4 ) ) {
case STENCIL_VALUE_UNIFORM : desc < < " StenUniform " ; break ;
case STENCIL_VALUE_ZERO : desc < < " Sten0 " ; break ;
case STENCIL_VALUE_ONE : desc < < " Sten1 " ; break ;
case STENCIL_VALUE_KEEP : desc < < " StenKeep " ; break ;
case STENCIL_VALUE_INVERT : desc < < " StenInv " ; break ;
case STENCIL_VALUE_INCR_4 : desc < < " StenIncr4 " ; break ;
case STENCIL_VALUE_INCR_8 : desc < < " StenIncr8 " ; break ;
case STENCIL_VALUE_DECR_4 : desc < < " StenDecr4 " ; break ;
2022-09-30 09:32:49 +00:00
case STENCIL_VALUE_DECR_8 : desc < < " StenDecr8 " ; break ;
2018-12-01 22:10:47 +00:00
default : desc < < " StenUnknown " ; break ;
2015-10-24 21:49:05 +00:00
}
2018-12-01 22:10:47 +00:00
} else if ( id . Bit ( FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE ) ) {
desc < < " StenOff " ;
2015-10-24 21:49:05 +00:00
}
if ( id . Bit ( FS_BIT_DO_TEXTURE ) ) {
switch ( id . Bits ( FS_BIT_TEXFUNC , 3 ) ) {
case GE_TEXFUNC_ADD : desc < < " TFuncAdd " ; break ;
case GE_TEXFUNC_BLEND : desc < < " TFuncBlend " ; break ;
case GE_TEXFUNC_DECAL : desc < < " TFuncDecal " ; break ;
case GE_TEXFUNC_MODULATE : desc < < " TFuncMod " ; break ;
case GE_TEXFUNC_REPLACE : desc < < " TFuncRepl " ; break ;
default : desc < < " TFuncUnk " ; break ;
}
}
if ( id . Bit ( FS_BIT_ALPHA_AGAINST_ZERO ) ) desc < < " AlphaTest0 " < < alphaTestFuncs [ id . Bits ( FS_BIT_ALPHA_TEST_FUNC , 3 ) ] < < " " ;
else if ( id . Bit ( FS_BIT_ALPHA_TEST ) ) desc < < " AlphaTest " < < alphaTestFuncs [ id . Bits ( FS_BIT_ALPHA_TEST_FUNC , 3 ) ] < < " " ;
if ( id . Bit ( FS_BIT_COLOR_AGAINST_ZERO ) ) desc < < " ColorTest0 " < < alphaTestFuncs [ id . Bits ( FS_BIT_COLOR_TEST_FUNC , 2 ) ] < < " " ; // first 4 match;
else if ( id . Bit ( FS_BIT_COLOR_TEST ) ) desc < < " ColorTest " < < alphaTestFuncs [ id . Bits ( FS_BIT_COLOR_TEST_FUNC , 2 ) ] < < " " ; // first 4 match
2022-09-26 09:55:47 +00:00
if ( id . Bit ( FS_BIT_TEST_DISCARD_TO_ZERO ) ) desc < < " TestDiscardToZero " ;
if ( id . Bit ( FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL ) ) desc < < " StencilDiscardWorkaround " ;
2022-11-10 11:14:06 +00:00
if ( ( id . Bits ( FS_BIT_REPLACE_LOGIC_OP , 4 ) ! = GE_LOGIC_COPY ) & & ! id . Bit ( FS_BIT_CLEARMODE ) ) desc < < " ReplaceLogic " ;
2022-10-23 09:21:35 +00:00
if ( id . Bit ( FS_BIT_SAMPLE_ARRAY_TEXTURE ) ) desc < < " TexArray " ;
if ( id . Bit ( FS_BIT_STEREO ) ) desc < < " Stereo " ;
2015-10-24 21:49:05 +00:00
return desc . str ( ) ;
}
2022-10-13 20:35:23 +00:00
bool FragmentIdNeedsFramebufferRead ( const FShaderID & id ) {
return id . Bit ( FS_BIT_COLOR_WRITEMASK ) | |
id . Bits ( FS_BIT_REPLACE_LOGIC_OP , 4 ) ! = GE_LOGIC_COPY | |
( ReplaceBlendType ) id . Bits ( FS_BIT_REPLACE_BLEND , 3 ) = = REPLACE_BLEND_READ_FRAMEBUFFER ;
}
2015-10-24 21:49:05 +00:00
// Here we must take all the bits of the gstate that determine what the fragment shader will
// look like, and concatenate them together into an ID.
2022-09-02 20:07:42 +00:00
void ComputeFragmentShaderID ( FShaderID * id_out , const ComputedPipelineState & pipelineState , const Draw : : Bugs & bugs ) {
2019-02-16 14:54:56 +00:00
FShaderID id ;
2015-10-24 21:49:05 +00:00
if ( gstate . isModeClear ( ) ) {
// We only need one clear shader, so let's ignore the rest of the bits.
id . SetBit ( FS_BIT_CLEARMODE ) ;
} else {
bool isModeThrough = gstate . isModeThrough ( ) ;
bool lmode = gstate . isUsingSecondaryColor ( ) & & gstate . isLightingEnabled ( ) & & ! isModeThrough ;
bool enableFog = gstate . isFogEnabled ( ) & & ! isModeThrough ;
2017-04-01 09:36:35 +00:00
bool enableAlphaTest = gstate . isAlphaTestEnabled ( ) & & ! IsAlphaTestTriviallyTrue ( ) ;
2015-10-24 21:49:05 +00:00
bool enableColorTest = gstate . isColorTestEnabled ( ) & & ! IsColorTestTriviallyTrue ( ) ;
2021-12-05 21:33:51 +00:00
bool enableColorDoubling = gstate . isColorDoublingEnabled ( ) & & gstate . isTextureMapEnabled ( ) ;
2017-01-30 15:01:00 +00:00
bool doTextureProjection = ( gstate . getUVGenMode ( ) = = GE_TEXMAP_TEXTURE_MATRIX & & MatrixNeedsProjection ( gstate . tgenMatrix ) ) ;
2015-10-24 21:49:05 +00:00
bool doTextureAlpha = gstate . isTextureAlphaUsed ( ) ;
bool doFlatShading = gstate . getShadeMode ( ) = = GE_SHADE_FLAT ;
2022-09-11 12:14:18 +00:00
ShaderDepalMode shaderDepalMode = gstate_c . shaderDepalMode ;
2022-09-02 21:06:41 +00:00
bool colorWriteMask = pipelineState . maskState . applyFramebufferRead ;
ReplaceBlendType replaceBlend = pipelineState . blendState . replaceBlend ;
2022-09-04 09:43:17 +00:00
GELogicOp replaceLogicOpType = pipelineState . logicState . applyFramebufferRead ? pipelineState . logicState . logicOp : GE_LOGIC_COPY ;
2015-10-24 21:49:05 +00:00
2022-10-13 20:35:23 +00:00
SimulateLogicOpType simulateLogicOpType = pipelineState . blendState . simulateLogicOpType ;
ReplaceAlphaType stencilToAlpha = pipelineState . blendState . replaceAlphaWithStencil ;
2015-10-24 21:49:05 +00:00
// All texfuncs except replace are the same for RGB as for RGBA with full alpha.
2017-03-19 10:32:29 +00:00
// Note that checking this means that we must dirty the fragment shader ID whenever textureFullAlpha changes.
2022-09-03 21:28:03 +00:00
if ( gstate_c . textureFullAlpha & & gstate . getTextureFunction ( ) ! = GE_TEXFUNC_REPLACE ) {
2015-10-24 21:49:05 +00:00
doTextureAlpha = false ;
2022-09-03 21:28:03 +00:00
}
2015-10-24 21:49:05 +00:00
if ( gstate . isTextureMapEnabled ( ) ) {
id . SetBit ( FS_BIT_DO_TEXTURE ) ;
id . SetBits ( FS_BIT_TEXFUNC , 3 , gstate . getTextureFunction ( ) ) ;
id . SetBit ( FS_BIT_TEXALPHA , doTextureAlpha & 1 ) ; // rgb or rgba
if ( gstate_c . needShaderTexClamp ) {
bool textureAtOffset = gstate_c . curTextureXOffset ! = 0 | | gstate_c . curTextureYOffset ! = 0 ;
// 4 bits total.
id . SetBit ( FS_BIT_SHADER_TEX_CLAMP ) ;
id . SetBit ( FS_BIT_CLAMP_S , gstate . isTexCoordClampedS ( ) ) ;
id . SetBit ( FS_BIT_CLAMP_T , gstate . isTexCoordClampedT ( ) ) ;
id . SetBit ( FS_BIT_TEXTURE_AT_OFFSET , textureAtOffset ) ;
}
2015-10-24 22:34:23 +00:00
id . SetBit ( FS_BIT_BGRA_TEXTURE , gstate_c . bgraTexture ) ;
2022-09-11 12:14:18 +00:00
id . SetBits ( FS_BIT_SHADER_DEPAL_MODE , 2 , ( int ) shaderDepalMode ) ;
2022-07-25 16:51:08 +00:00
id . SetBit ( FS_BIT_3D_TEXTURE , gstate_c . curTextureIs3D ) ;
2015-10-24 21:49:05 +00:00
}
id . SetBit ( FS_BIT_LMODE , lmode ) ;
2015-10-25 06:05:18 +00:00
if ( enableAlphaTest ) {
// 5 bits total.
id . SetBit ( FS_BIT_ALPHA_TEST ) ;
id . SetBits ( FS_BIT_ALPHA_TEST_FUNC , 3 , gstate . getAlphaTestFunction ( ) ) ;
id . SetBit ( FS_BIT_ALPHA_AGAINST_ZERO , IsAlphaTestAgainstZero ( ) ) ;
2018-07-28 03:04:36 +00:00
id . SetBit ( FS_BIT_TEST_DISCARD_TO_ZERO , ! NeedsTestDiscard ( ) ) ;
2015-10-25 06:05:18 +00:00
}
2015-10-24 21:49:05 +00:00
if ( enableColorTest ) {
// 4 bits total.
id . SetBit ( FS_BIT_COLOR_TEST ) ;
id . SetBits ( FS_BIT_COLOR_TEST_FUNC , 2 , gstate . getColorTestFunction ( ) ) ;
id . SetBit ( FS_BIT_COLOR_AGAINST_ZERO , IsColorTestAgainstZero ( ) ) ;
2018-07-28 03:04:36 +00:00
// This is alos set in enableAlphaTest - color test is uncommon, but we can skip discard the same way.
id . SetBit ( FS_BIT_TEST_DISCARD_TO_ZERO , ! NeedsTestDiscard ( ) ) ;
2015-10-24 21:49:05 +00:00
}
id . SetBit ( FS_BIT_ENABLE_FOG , enableFog ) ;
id . SetBit ( FS_BIT_DO_TEXTURE_PROJ , doTextureProjection ) ;
id . SetBit ( FS_BIT_COLOR_DOUBLE , enableColorDoubling ) ;
// 2 bits
id . SetBits ( FS_BIT_STENCIL_TO_ALPHA , 2 , stencilToAlpha ) ;
if ( stencilToAlpha ! = REPLACE_ALPHA_NO ) {
// 4 bits
id . SetBits ( FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE , 4 , ReplaceAlphaWithStencilType ( ) ) ;
}
// 2 bits.
2022-09-03 21:28:03 +00:00
id . SetBits ( FS_BIT_SIMULATE_LOGIC_OP_TYPE , 2 , simulateLogicOpType ) ;
2015-10-24 21:49:05 +00:00
2022-09-04 09:14:47 +00:00
// 4 bits. Set to GE_LOGIC_COPY if not used, which does nothing in the shader generator.
id . SetBits ( FS_BIT_REPLACE_LOGIC_OP , 4 , ( int ) replaceLogicOpType ) ;
2015-10-24 21:49:05 +00:00
// If replaceBlend == REPLACE_BLEND_STANDARD (or REPLACE_BLEND_NO) nothing is done, so we kill these bits.
2022-04-24 18:53:09 +00:00
if ( replaceBlend = = REPLACE_BLEND_BLUE_TO_ALPHA ) {
id . SetBits ( FS_BIT_REPLACE_BLEND , 3 , replaceBlend ) ;
2022-04-24 20:54:08 +00:00
id . SetBits ( FS_BIT_BLENDFUNC_A , 4 , gstate . getBlendFuncA ( ) ) ;
2022-04-24 18:53:09 +00:00
} else if ( replaceBlend > REPLACE_BLEND_STANDARD ) {
2015-10-24 21:49:05 +00:00
// 3 bits.
id . SetBits ( FS_BIT_REPLACE_BLEND , 3 , replaceBlend ) ;
// 11 bits total.
id . SetBits ( FS_BIT_BLENDEQ , 3 , gstate . getBlendEq ( ) ) ;
id . SetBits ( FS_BIT_BLENDFUNC_A , 4 , gstate . getBlendFuncA ( ) ) ;
id . SetBits ( FS_BIT_BLENDFUNC_B , 4 , gstate . getBlendFuncB ( ) ) ;
}
id . SetBit ( FS_BIT_FLATSHADE , doFlatShading ) ;
2020-11-08 22:17:06 +00:00
id . SetBit ( FS_BIT_COLOR_WRITEMASK , colorWriteMask ) ;
2018-12-23 20:19:34 +00:00
2022-10-26 21:48:45 +00:00
// All framebuffers are array textures in Vulkan now.
if ( gstate_c . arrayTexture & & g_Config . iGPUBackend = = ( int ) GPUBackend : : VULKAN ) {
2022-10-26 09:23:12 +00:00
id . SetBit ( FS_BIT_SAMPLE_ARRAY_TEXTURE ) ;
}
2022-10-17 22:26:10 +00:00
// Stereo support
if ( gstate_c . Use ( GPU_USE_SINGLE_PASS_STEREO ) ) {
2022-10-23 09:21:35 +00:00
id . SetBit ( FS_BIT_STEREO ) ;
2022-10-17 22:26:10 +00:00
}
2022-09-18 08:34:43 +00:00
if ( g_Config . bVendorBugChecksEnabled & & bugs . Has ( Draw : : Bugs : : NO_DEPTH_CANNOT_DISCARD_STENCIL ) ) {
bool stencilWithoutDepth = ! IsStencilTestOutputDisabled ( ) & & ( ! gstate . isDepthTestEnabled ( ) | | ! gstate . isDepthWriteEnabled ( ) ) ;
if ( stencilWithoutDepth ) {
id . SetBit ( FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL , stencilWithoutDepth ) ;
2018-12-23 20:19:34 +00:00
}
}
2015-10-24 21:49:05 +00:00
}
* id_out = id ;
}
2022-10-02 03:01:23 +00:00
std : : string GeometryShaderDesc ( const GShaderID & id ) {
std : : stringstream desc ;
desc < < StringFromFormat ( " %08x:%08x " , id . d [ 1 ] , id . d [ 0 ] ) ;
if ( id . Bit ( GS_BIT_ENABLED ) ) desc < < " ENABLED " ;
if ( id . Bit ( GS_BIT_DO_TEXTURE ) ) desc < < " TEX " ;
if ( id . Bit ( GS_BIT_LMODE ) ) desc < < " LMODE " ;
return desc . str ( ) ;
}
void ComputeGeometryShaderID ( GShaderID * id_out , const Draw : : Bugs & bugs , int prim ) {
GShaderID id ;
2022-10-06 02:41:59 +00:00
bool isModeThrough = gstate . isModeThrough ( ) ;
bool isCurve = gstate_c . submitType ! = SubmitType : : DRAW ;
bool isTriangle = prim = = GE_PRIM_TRIANGLES | | prim = = GE_PRIM_TRIANGLE_FAN | | prim = = GE_PRIM_TRIANGLE_STRIP ;
bool vertexRangeCulling = ! isCurve ;
2022-10-17 06:30:27 +00:00
bool clipClampedDepth = gstate_c . Use ( GPU_USE_DEPTH_CLAMP ) & & ! gstate_c . Use ( GPU_USE_CLIP_DISTANCE ) ;
2022-10-02 03:01:23 +00:00
// If we're not using GS culling, return a zero ID.
// Also, only use this for triangle primitives.
2022-10-17 06:30:27 +00:00
if ( ( ! vertexRangeCulling & & ! clipClampedDepth ) | | isModeThrough | | ! isTriangle | | ! gstate_c . Use ( GPU_USE_GS_CULLING ) ) {
2022-10-02 03:01:23 +00:00
* id_out = id ;
return ;
}
id . SetBit ( GS_BIT_ENABLED , true ) ;
2022-10-06 02:41:59 +00:00
// Vertex range culling doesn't seem tno happen for spline/bezier, see #11692.
id . SetBit ( GS_BIT_CURVE , isCurve ) ;
2022-10-02 03:01:23 +00:00
if ( gstate . isModeClear ( ) ) {
// No attribute bits.
} else {
bool lmode = gstate . isUsingSecondaryColor ( ) & & gstate . isLightingEnabled ( ) & & ! isModeThrough ;
id . SetBit ( GS_BIT_LMODE , lmode ) ;
if ( gstate . isTextureMapEnabled ( ) ) {
id . SetBit ( GS_BIT_DO_TEXTURE ) ;
}
}
* id_out = id ;
}