2014-09-26 09:06:55 -07:00
// Copyright (c) 2013- 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/.
# pragma once
# include <vector>
# include "Common/CommonTypes.h"
2020-10-05 20:58:33 +02:00
# include "Common/Data/Collections/Hashmaps.h"
2014-09-26 09:06:55 -07:00
2023-07-30 14:42:22 +02:00
# include "GPU/Math3D.h"
2017-01-23 16:57:16 +01:00
# include "GPU/GPUState.h"
2022-09-02 21:07:29 +02:00
# include "GPU/Common/GPUStateUtils.h"
2014-09-26 09:06:55 -07:00
# include "GPU/Common/GPUDebugInterface.h"
2017-06-02 12:03:46 +02:00
# include "GPU/Common/IndexGenerator.h"
2015-04-08 21:35:00 +02:00
# include "GPU/Common/VertexDecoderCommon.h"
2014-09-26 09:06:55 -07:00
class VertexDecoder ;
2015-01-29 14:12:24 +01:00
enum {
VERTEX_BUFFER_MAX = 65536 ,
2023-05-03 00:23:31 +02:00
DECODED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 2 * 36 , // 36 == sizeof(SimpleVertex)
DECODED_INDEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 6 * 6 * 2 , // * 6 for spline tessellation, then * 6 again for converting into points/lines, and * 2 for 2 bytes per index
2015-01-29 14:12:24 +01:00
} ;
2022-08-02 15:42:05 +02:00
enum {
TEX_SLOT_PSP_TEXTURE = 0 ,
TEX_SLOT_SHADERBLEND_SRC = 1 ,
TEX_SLOT_ALPHATEST = 2 ,
TEX_SLOT_CLUT = 3 ,
TEX_SLOT_SPLINE_POINTS = 4 ,
TEX_SLOT_SPLINE_WEIGHTS_U = 5 ,
TEX_SLOT_SPLINE_WEIGHTS_V = 6 ,
} ;
2022-02-19 20:40:27 +01:00
enum FBOTexState {
FBO_TEX_NONE ,
FBO_TEX_COPY_BIND_TEX ,
FBO_TEX_READ_FRAMEBUFFER ,
} ;
2022-11-06 08:09:01 -08:00
inline uint32_t GetVertTypeID ( uint32_t vertType , int uvGenMode , bool skinInDecode ) {
2018-03-05 12:24:02 +01:00
// As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it
// into the top of the verttype where there are unused bits.
2022-11-06 08:09:01 -08:00
return ( vertType & 0xFFFFFF ) | ( uvGenMode < < 24 ) | ( skinInDecode < < 26 ) ;
2018-03-05 12:24:02 +01:00
}
2018-06-28 01:41:16 +09:00
struct SimpleVertex ;
2018-09-29 13:39:02 +09:00
namespace Spline { struct Weight2D ; }
2018-06-28 01:41:16 +09:00
2018-07-13 18:35:44 +09:00
class TessellationDataTransfer {
public :
2018-12-01 13:59:47 -08:00
virtual ~ TessellationDataTransfer ( ) { }
2024-04-05 17:04:31 +03:00
static void CopyControlPoints ( float * pos , float * tex , float * col , int posStride , int texStride , int colStride , const SimpleVertex * const * points , int size , u32 vertType ) ;
2018-09-29 13:39:02 +09:00
virtual void SendDataToShader ( const SimpleVertex * const * points , int size_u , int size_v , u32 vertType , const Spline : : Weight2D & weights ) = 0 ;
2018-07-13 18:35:44 +09:00
} ;
2023-12-09 00:55:02 +01:00
// Culling plane, group of 8.
struct alignas ( 16 ) Plane8 {
float x [ 8 ] , y [ 8 ] , z [ 8 ] , w [ 8 ] ;
void Set ( int i , float _x , float _y , float _z , float _w ) { x [ i ] = _x ; y [ i ] = _y ; z [ i ] = _z ; w [ i ] = _w ; }
float Test ( int i , const float f [ 3 ] ) const { return x [ i ] * f [ 0 ] + y [ i ] * f [ 1 ] + z [ i ] * f [ 2 ] + w [ i ] ; }
2023-07-30 14:42:22 +02:00
} ;
2014-09-26 09:06:55 -07:00
class DrawEngineCommon {
public :
2015-04-08 21:35:00 +02:00
DrawEngineCommon ( ) ;
2014-09-26 09:06:55 -07:00
virtual ~ DrawEngineCommon ( ) ;
2021-05-08 09:10:23 -07:00
void Init ( ) ;
2023-02-26 11:05:52 +01:00
virtual void DeviceLost ( ) = 0 ;
virtual void DeviceRestore ( Draw : : DrawContext * draw ) = 0 ;
2021-05-08 09:10:23 -07:00
2014-09-26 09:06:55 -07:00
bool GetCurrentSimpleVertices ( int count , std : : vector < GPUDebugVertex > & vertices , std : : vector < u16 > & indices ) ;
static u32 NormalizeVertices ( u8 * outPtr , u8 * bufPtr , const u8 * inPtr , VertexDecoder * dec , int lowerBound , int upperBound , u32 vertType ) ;
2015-04-08 21:44:54 +02:00
// Flush is normally non-virtual but here's a virtual way to call it, used by the shared spline code, which is expensive anyway.
// Not really sure if these wrappers are worth it...
2015-04-08 21:37:54 +02:00
virtual void DispatchFlush ( ) = 0 ;
2018-02-26 11:26:52 +01:00
// This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim
// is different. Should probably refactor that.
2018-03-05 12:24:02 +01:00
// Note that vertTypeID should be computed using GetVertTypeID().
2023-10-10 13:16:34 +02:00
virtual void DispatchSubmitPrim ( const void * verts , const void * inds , GEPrimitiveType prim , int vertexCount , u32 vertTypeID , bool clockwise , int * bytesRead ) {
SubmitPrim ( verts , inds , prim , vertexCount , vertTypeID , clockwise , bytesRead ) ;
2018-02-26 11:33:17 +01:00
}
2015-04-08 21:44:54 +02:00
2022-09-17 20:15:40 -07:00
virtual void DispatchSubmitImm ( GEPrimitiveType prim , TransformedVertex * buffer , int vertexCount , int cullMode , bool continuation ) ;
2022-01-22 22:41:41 -08:00
2022-10-22 10:01:56 -07:00
bool TestBoundingBox ( const void * control_points , const void * inds , int vertexCount , u32 vertType ) ;
2018-02-26 11:02:52 +01:00
2023-12-04 18:54:46 +01:00
// This is a less accurate version of TestBoundingBox, but faster. Can have more false positives.
// Doesn't support indexing.
bool TestBoundingBoxFast ( const void * control_points , int vertexCount , u32 vertType ) ;
2024-12-01 14:49:10 +01:00
bool TestBoundingBoxThrough ( const void * vdata , int vertexCount , u32 vertType ) ;
2023-12-04 18:54:46 +01:00
2023-10-02 16:53:54 +02:00
void FlushSkin ( ) {
bool applySkin = ( lastVType_ & GE_VTYPE_WEIGHT_MASK ) & & decOptions_ . applySkinInDecode ;
if ( applySkin ) {
DecodeVerts ( decoded_ ) ;
}
}
2023-10-10 13:16:34 +02:00
int ExtendNonIndexedPrim ( const uint32_t * cmd , const uint32_t * stall , u32 vertTypeID , bool clockwise , int * bytesRead , bool isTriangle ) ;
bool SubmitPrim ( const void * verts , const void * inds , GEPrimitiveType prim , int vertexCount , u32 vertTypeID , bool clockwise , int * bytesRead ) ;
2023-11-26 11:14:13 +01:00
void SkipPrim ( GEPrimitiveType prim , int vertexCount , u32 vertTypeID , int * bytesRead ) ;
2018-11-13 17:12:41 +09:00
template < class Surface >
void SubmitCurve ( const void * control_points , const void * indices , Surface & surface , u32 vertType , int * bytesRead , const char * scope ) ;
2024-04-05 17:04:31 +03:00
static void ClearSplineBezierWeights ( ) ;
2015-04-08 21:37:54 +02:00
2024-04-05 17:04:31 +03:00
bool CanUseHardwareTransform ( int prim ) const ;
bool CanUseHardwareTessellation ( GEPatchPrimType prim ) const ;
2020-04-04 11:14:32 -07:00
2015-10-21 23:06:32 +02:00
std : : vector < std : : string > DebugGetVertexLoaderIDs ( ) ;
std : : string DebugGetVertexLoaderString ( std : : string id , DebugShaderStringType stringType ) ;
2017-01-23 16:57:16 +01:00
2022-11-06 08:40:54 -08:00
virtual void NotifyConfigChanged ( ) ;
2017-03-17 10:27:49 +01:00
2022-11-13 08:13:22 -08:00
bool EverUsedExactEqualDepth ( ) const {
return everUsedExactEqualDepth_ ;
}
2022-12-13 21:32:11 -08:00
void SetEverUsedExactEqualDepth ( bool v ) {
everUsedExactEqualDepth_ = v ;
}
2022-11-13 08:13:22 -08:00
2023-12-19 12:25:54 +01:00
bool DescribeCodePtr ( const u8 * ptr , std : : string & name ) const ;
2018-02-26 13:51:14 +01:00
int GetNumDrawCalls ( ) const {
2023-10-02 00:50:20 +02:00
return numDrawVerts_ ;
2018-02-26 13:51:14 +01:00
}
2017-10-20 11:06:06 +02:00
2018-03-13 23:22:21 +01:00
VertexDecoder * GetVertexDecoder ( u32 vtype ) ;
2023-02-25 12:07:28 +01:00
virtual void ClearTrackedVertexArrays ( ) { }
2024-10-17 21:01:58 +02:00
void AssertEmpty ( ) {
_dbg_assert_ ( numDrawVerts_ = = 0 & & numDrawInds_ = = 0 ) ;
}
2014-09-26 09:06:55 -07:00
protected :
2023-06-12 20:20:06 +02:00
virtual bool UpdateUseHWTessellation ( bool enabled ) const { return enabled ; }
2023-07-30 14:42:22 +02:00
void UpdatePlanes ( ) ;
2017-03-17 10:27:49 +01:00
2017-11-19 12:38:52 +01:00
void DecodeVerts ( u8 * dest ) ;
2023-10-06 12:43:10 +02:00
int DecodeInds ( ) ;
2017-11-19 12:38:52 +01:00
2015-04-08 21:44:54 +02:00
// Preprocessing for spline/bezier
2017-11-17 13:36:48 +01:00
u32 NormalizeVertices ( u8 * outPtr , u8 * bufPtr , const u8 * inPtr , int lowerBound , int upperBound , u32 vertType , int * vertexSize = nullptr ) ;
2015-04-08 21:44:54 +02:00
2023-10-02 00:50:20 +02:00
int ComputeNumVertsToDecode ( ) const ;
2017-06-02 12:09:57 +02:00
2022-02-19 20:40:27 +01:00
void ApplyFramebufferRead ( FBOTexState * fboTexState ) ;
2016-09-18 19:40:44 -07:00
2024-04-05 17:04:31 +03:00
static inline int IndexSize ( u32 vtype ) {
2016-04-10 01:52:51 -07:00
const u32 indexType = ( vtype & GE_VTYPE_IDX_MASK ) ;
if ( indexType = = GE_VTYPE_IDX_16BIT ) {
return 2 ;
} else if ( indexType = = GE_VTYPE_IDX_32BIT ) {
return 4 ;
}
return 1 ;
}
2022-11-07 20:07:57 -08:00
inline void UpdateEverUsedEqualDepth ( GEComparison comp ) {
switch ( comp ) {
case GE_COMP_EQUAL :
2022-11-13 08:13:22 -08:00
everUsedExactEqualDepth_ = true ;
everUsedEqualDepth_ = true ;
break ;
2022-11-07 20:07:57 -08:00
case GE_COMP_NOTEQUAL :
case GE_COMP_LEQUAL :
case GE_COMP_GEQUAL :
everUsedEqualDepth_ = true ;
break ;
default :
break ;
}
}
2023-10-06 12:24:59 +02:00
inline void ResetAfterDrawInline ( ) {
gpuStats . numFlushes + + ;
gpuStats . numDrawCalls + = numDrawInds_ ;
gpuStats . numVertexDecodes + = numDrawVerts_ ;
gpuStats . numVertsSubmitted + = vertexCountInDrawCalls_ ;
2024-02-01 19:19:53 +01:00
gpuStats . numVertsDecoded + = numDecodedVerts_ ;
2023-10-06 12:24:59 +02:00
indexGen . Reset ( ) ;
2023-12-10 11:58:47 +01:00
numDecodedVerts_ = 0 ;
2023-10-06 12:24:59 +02:00
numDrawVerts_ = 0 ;
numDrawInds_ = 0 ;
vertexCountInDrawCalls_ = 0 ;
decodeIndsCounter_ = 0 ;
decodeVertsCounter_ = 0 ;
2023-10-06 12:43:10 +02:00
seenPrims_ = 0 ;
anyCCWOrIndexed_ = false ;
2023-10-06 12:24:59 +02:00
gstate_c . vertexFullAlpha = true ;
// Now seems as good a time as any to reset the min/max coords, which we may examine later.
gstate_c . vertBounds . minU = 512 ;
gstate_c . vertBounds . minV = 512 ;
gstate_c . vertBounds . maxU = 0 ;
gstate_c . vertBounds . maxV = 0 ;
}
2023-10-06 12:43:10 +02:00
inline bool CollectedPureDraw ( ) const {
switch ( seenPrims_ ) {
case 1 < < GE_PRIM_TRIANGLE_STRIP :
return ! anyCCWOrIndexed_ & & numDrawInds_ = = 1 ;
case 1 < < GE_PRIM_LINES :
case 1 < < GE_PRIM_POINTS :
case 1 < < GE_PRIM_TRIANGLES :
return ! anyCCWOrIndexed_ ;
default :
return false ;
}
}
inline void DecodeIndsAndGetData ( GEPrimitiveType * prim , int * numVerts , int * maxIndex , bool * useElements , bool forceIndexed ) {
if ( ! forceIndexed & & CollectedPureDraw ( ) ) {
* prim = drawInds_ [ 0 ] . prim ;
* numVerts = numDecodedVerts_ ;
* maxIndex = numDecodedVerts_ ;
* useElements = false ;
} else {
int vertexCount = DecodeInds ( ) ;
* numVerts = vertexCount ;
* maxIndex = numDecodedVerts_ ;
* prim = IndexGenerator : : GeneralPrim ( ( GEPrimitiveType ) drawInds_ [ 0 ] . prim ) ;
* useElements = true ;
}
}
2024-01-15 10:09:04 +01:00
inline int RemainingIndices ( const uint16_t * inds ) const {
return DECODED_INDEX_BUFFER_SIZE / sizeof ( uint16_t ) - ( inds - decIndex_ ) ;
}
2023-06-12 14:24:20 +02:00
2020-04-04 11:21:22 -07:00
bool useHWTransform_ = false ;
2020-04-04 11:52:32 -07:00
bool useHWTessellation_ = false ;
2022-09-22 00:08:38 -07:00
// Used to prevent unnecessary flushing in softgpu.
bool flushOnParams_ = true ;
2020-04-04 11:21:22 -07:00
2022-11-07 20:07:57 -08:00
// Set once a equal depth test is encountered.
bool everUsedEqualDepth_ = false ;
2022-11-13 08:13:22 -08:00
bool everUsedExactEqualDepth_ = false ;
2022-11-07 20:07:57 -08:00
2014-09-26 09:06:55 -07:00
// Vertex collector buffers
2023-05-23 16:46:43 +02:00
u8 * decoded_ = nullptr ;
2023-05-23 18:00:50 +02:00
u16 * decIndex_ = nullptr ;
2015-04-08 21:35:00 +02:00
// Cached vertex decoders
2023-09-11 12:02:56 +02:00
DenseHashMap < u32 , VertexDecoder * > decoderMap_ ;
2017-06-02 13:06:14 +02:00
VertexDecoderJitCache * decJitCache_ = nullptr ;
VertexDecoderOptions decOptions_ { } ;
2015-04-08 21:35:00 +02:00
2023-05-23 18:00:50 +02:00
TransformedVertex * transformed_ = nullptr ;
TransformedVertex * transformedExpanded_ = nullptr ;
2017-06-02 12:25:47 +02:00
2018-04-10 11:50:24 +02:00
// Defer all vertex decoding to a "Flush" (except when software skinning)
2023-10-02 00:50:20 +02:00
struct DeferredVerts {
2022-07-20 12:40:22 +02:00
const void * verts ;
2023-10-06 12:43:10 +02:00
UVScale uvScale ;
2018-06-26 19:49:49 +02:00
u32 vertexCount ;
2017-06-02 12:03:46 +02:00
u16 indexLowerBound ;
u16 indexUpperBound ;
} ;
2023-10-02 00:50:20 +02:00
struct DeferredInds {
const void * inds ;
u32 vertexCount ;
2023-10-02 11:25:27 +02:00
u8 vertDecodeIndex ; // index into the drawVerts_ array to look up the vertexOffset.
2023-10-02 00:50:20 +02:00
u8 indexType ;
2023-10-06 12:43:10 +02:00
GEPrimitiveType prim ;
2023-10-10 13:00:57 +02:00
bool clockwise ;
2023-10-02 16:03:49 +02:00
u16 offset ;
2023-10-02 00:50:20 +02:00
} ;
2023-10-02 11:25:27 +02:00
enum { MAX_DEFERRED_DRAW_VERTS = 128 } ; // If you change this to more than 256, change type of DeferredInds::vertDecodeIndex.
enum { MAX_DEFERRED_DRAW_INDS = 512 } ; // Monster Hunter spams indexed calls that we end up merging.
DeferredVerts drawVerts_ [ MAX_DEFERRED_DRAW_VERTS ] ;
uint32_t drawVertexOffsets_ [ MAX_DEFERRED_DRAW_VERTS ] ;
DeferredInds drawInds_ [ MAX_DEFERRED_DRAW_INDS ] ;
2023-10-02 00:50:20 +02:00
2023-10-06 12:43:10 +02:00
VertexDecoder * dec_ = nullptr ;
u32 lastVType_ = - 1 ; // corresponds to dec_. Could really just pick it out of dec_...
2023-10-02 00:50:20 +02:00
int numDrawVerts_ = 0 ;
int numDrawInds_ = 0 ;
2017-06-02 12:03:46 +02:00
int vertexCountInDrawCalls_ = 0 ;
2023-10-02 00:50:20 +02:00
int decodeVertsCounter_ = 0 ;
int decodeIndsCounter_ = 0 ;
2023-10-06 12:43:10 +02:00
int seenPrims_ = 0 ;
bool anyCCWOrIndexed_ = 0 ;
bool anyIndexed_ = 0 ;
2017-06-02 12:03:46 +02:00
// Vertex collector state
IndexGenerator indexGen ;
2023-12-10 11:58:47 +01:00
int numDecodedVerts_ = 0 ;
2017-06-02 12:03:46 +02:00
GEPrimitiveType prevPrim_ = GE_PRIM_INVALID ;
2017-02-17 12:21:18 +01:00
// Shader blending state
2017-06-02 12:03:46 +02:00
bool fboTexBound_ = false ;
2017-02-17 12:21:18 +01:00
2022-08-28 08:34:48 -07:00
// Sometimes, unusual situations mean we need to reset dirty flags after state calc finishes.
uint64_t dirtyRequiresRecheck_ = 0 ;
2022-09-02 21:07:29 +02:00
ComputedPipelineState pipelineState_ ;
2017-01-08 22:14:35 +09:00
// Hardware tessellation
TessellationDataTransfer * tessDataTransfer ;
2023-07-30 14:42:22 +02:00
// Culling
2023-12-09 00:55:02 +01:00
Plane8 planes_ ;
2023-07-30 14:42:22 +02:00
Vec2f minOffset_ ;
Vec2f maxOffset_ ;
2023-12-04 18:54:46 +01:00
bool offsetOutsideEdge_ ;
2015-03-01 15:28:11 +01:00
} ;