2014-09-26 16:06:55 +00: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 18:58:33 +00:00
# include "Common/Data/Collections/Hashmaps.h"
2014-09-26 16:06:55 +00:00
2023-07-30 12:42:22 +00:00
# include "GPU/Math3D.h"
2017-01-23 15:57:16 +00:00
# include "GPU/GPUState.h"
2022-09-02 19:07:29 +00:00
# include "GPU/Common/GPUStateUtils.h"
2014-09-26 16:06:55 +00:00
# include "GPU/Common/GPUDebugInterface.h"
2017-06-02 10:03:46 +00:00
# include "GPU/Common/IndexGenerator.h"
2015-04-08 19:35:00 +00:00
# include "GPU/Common/VertexDecoderCommon.h"
2014-09-26 16:06:55 +00:00
class VertexDecoder ;
2015-01-29 13:12:24 +00:00
enum {
VERTEX_BUFFER_MAX = 65536 ,
2023-05-02 22:23:31 +00: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 13:12:24 +00:00
} ;
2022-08-02 13:42:05 +00: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 19:40:27 +00:00
enum FBOTexState {
FBO_TEX_NONE ,
FBO_TEX_COPY_BIND_TEX ,
FBO_TEX_READ_FRAMEBUFFER ,
} ;
2022-11-06 16:09:01 +00:00
inline uint32_t GetVertTypeID ( uint32_t vertType , int uvGenMode , bool skinInDecode ) {
2018-03-05 11:24:02 +00: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 16:09:01 +00:00
return ( vertType & 0xFFFFFF ) | ( uvGenMode < < 24 ) | ( skinInDecode < < 26 ) ;
2018-03-05 11:24:02 +00:00
}
2018-06-27 16:41:16 +00:00
struct SimpleVertex ;
2018-09-29 04:39:02 +00:00
namespace Spline { struct Weight2D ; }
2018-06-27 16:41:16 +00:00
2018-07-13 09:35:44 +00:00
class TessellationDataTransfer {
public :
2018-12-01 21:59:47 +00:00
virtual ~ TessellationDataTransfer ( ) { }
2018-07-13 09:35:44 +00:00
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 04:39:02 +00:00
virtual void SendDataToShader ( const SimpleVertex * const * points , int size_u , int size_v , u32 vertType , const Spline : : Weight2D & weights ) = 0 ;
2018-07-13 09:35:44 +00:00
} ;
2023-07-30 12:42:22 +00:00
// Culling plane.
struct Plane {
float x , y , z , w ;
void Set ( float _x , float _y , float _z , float _w ) { x = _x ; y = _y ; z = _z ; w = _w ; }
float Test ( const float f [ 3 ] ) const { return x * f [ 0 ] + y * f [ 1 ] + z * f [ 2 ] + w ; }
} ;
2014-09-26 16:06:55 +00:00
class DrawEngineCommon {
public :
2015-04-08 19:35:00 +00:00
DrawEngineCommon ( ) ;
2014-09-26 16:06:55 +00:00
virtual ~ DrawEngineCommon ( ) ;
2021-05-08 16:10:23 +00:00
void Init ( ) ;
2023-02-26 10:05:52 +00:00
virtual void DeviceLost ( ) = 0 ;
virtual void DeviceRestore ( Draw : : DrawContext * draw ) = 0 ;
2021-05-08 16:10:23 +00:00
2014-09-26 16:06:55 +00: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 19:44:54 +00: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 19:37:54 +00:00
virtual void DispatchFlush ( ) = 0 ;
2018-02-26 10:26:52 +00: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 11:24:02 +00:00
// Note that vertTypeID should be computed using GetVertTypeID().
2022-07-20 10:40:22 +00:00
virtual void DispatchSubmitPrim ( const void * verts , const void * inds , GEPrimitiveType prim , int vertexCount , u32 vertTypeID , int cullMode , int * bytesRead ) {
2018-12-16 21:00:36 +00:00
SubmitPrim ( verts , inds , prim , vertexCount , vertTypeID , cullMode , bytesRead ) ;
2018-02-26 10:33:17 +00:00
}
2015-04-08 19:44:54 +00:00
2022-09-18 03:15:40 +00:00
virtual void DispatchSubmitImm ( GEPrimitiveType prim , TransformedVertex * buffer , int vertexCount , int cullMode , bool continuation ) ;
2022-01-23 06:41:41 +00:00
2022-10-22 17:01:56 +00:00
bool TestBoundingBox ( const void * control_points , const void * inds , int vertexCount , u32 vertType ) ;
2018-02-26 10:02:52 +00:00
2022-07-20 10:40:22 +00:00
void SubmitPrim ( const void * verts , const void * inds , GEPrimitiveType prim , int vertexCount , u32 vertTypeID , int cullMode , int * bytesRead ) ;
2018-11-13 08:12:41 +00:00
template < class Surface >
void SubmitCurve ( const void * control_points , const void * indices , Surface & surface , u32 vertType , int * bytesRead , const char * scope ) ;
2018-01-31 12:42:39 +00:00
void ClearSplineBezierWeights ( ) ;
2015-04-08 19:37:54 +00:00
2020-04-04 18:14:32 +00:00
bool CanUseHardwareTransform ( int prim ) ;
bool CanUseHardwareTessellation ( GEPatchPrimType prim ) ;
2015-10-21 21:06:32 +00:00
std : : vector < std : : string > DebugGetVertexLoaderIDs ( ) ;
std : : string DebugGetVertexLoaderString ( std : : string id , DebugShaderStringType stringType ) ;
2017-01-23 15:57:16 +00:00
2022-11-06 16:40:54 +00:00
virtual void NotifyConfigChanged ( ) ;
2017-03-17 09:27:49 +00:00
2022-11-13 16:13:22 +00:00
bool EverUsedExactEqualDepth ( ) const {
return everUsedExactEqualDepth_ ;
}
2022-12-14 05:32:11 +00:00
void SetEverUsedExactEqualDepth ( bool v ) {
everUsedExactEqualDepth_ = v ;
}
2022-11-13 16:13:22 +00:00
2017-10-20 09:06:06 +00:00
bool IsCodePtrVertexDecoder ( const u8 * ptr ) const {
2023-02-28 15:03:12 +00:00
if ( decJitCache_ )
return decJitCache_ - > IsInSpace ( ptr ) ;
return false ;
2017-10-20 09:06:06 +00:00
}
2018-02-26 12:51:14 +00:00
int GetNumDrawCalls ( ) const {
2023-05-23 16:00:50 +00:00
return numDrawCalls_ ;
2018-02-26 12:51:14 +00:00
}
2017-10-20 09:06:06 +00:00
2018-03-13 22:22:21 +00:00
VertexDecoder * GetVertexDecoder ( u32 vtype ) ;
2023-02-25 11:07:28 +00:00
virtual void ClearTrackedVertexArrays ( ) { }
2014-09-26 16:06:55 +00:00
protected :
2023-06-12 18:20:06 +00:00
virtual bool UpdateUseHWTessellation ( bool enabled ) const { return enabled ; }
2023-07-30 12:42:22 +00:00
void UpdatePlanes ( ) ;
2017-03-17 09:27:49 +00:00
2017-11-19 11:38:52 +00:00
int ComputeNumVertsToDecode ( ) const ;
void DecodeVerts ( u8 * dest ) ;
2015-04-08 19:44:54 +00:00
// Preprocessing for spline/bezier
2017-11-17 12:36:48 +00:00
u32 NormalizeVertices ( u8 * outPtr , u8 * bufPtr , const u8 * inPtr , int lowerBound , int upperBound , u32 vertType , int * vertexSize = nullptr ) ;
2015-04-08 19:44:54 +00:00
2017-06-02 10:16:43 +00:00
// Utility for vertex caching
u32 ComputeMiniHash ( ) ;
2020-08-28 03:37:49 +00:00
uint64_t ComputeHash ( ) ;
2017-06-02 10:16:43 +00:00
2017-06-02 10:09:57 +00:00
// Vertex decoding
2023-06-12 14:46:12 +00:00
void DecodeVertsStep ( u8 * dest , int & i , int & decodedVerts , const UVScale * uvScale ) ;
2017-06-02 10:09:57 +00:00
2022-02-19 19:40:27 +00:00
void ApplyFramebufferRead ( FBOTexState * fboTexState ) ;
2016-09-19 02:40:44 +00:00
2016-04-10 08:52:51 +00:00
inline int IndexSize ( u32 vtype ) const {
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-08 04:07:57 +00:00
inline void UpdateEverUsedEqualDepth ( GEComparison comp ) {
switch ( comp ) {
case GE_COMP_EQUAL :
2022-11-13 16:13:22 +00:00
everUsedExactEqualDepth_ = true ;
everUsedEqualDepth_ = true ;
break ;
2022-11-08 04:07:57 +00:00
case GE_COMP_NOTEQUAL :
case GE_COMP_LEQUAL :
case GE_COMP_GEQUAL :
everUsedEqualDepth_ = true ;
break ;
default :
break ;
}
}
2023-06-12 12:24:20 +00:00
uint32_t ComputeDrawcallsHash ( ) const ;
2020-04-04 18:21:22 +00:00
bool useHWTransform_ = false ;
2020-04-04 18:52:32 +00:00
bool useHWTessellation_ = false ;
2022-09-22 07:08:38 +00:00
// Used to prevent unnecessary flushing in softgpu.
bool flushOnParams_ = true ;
2020-04-04 18:21:22 +00:00
2022-11-08 04:07:57 +00:00
// Set once a equal depth test is encountered.
bool everUsedEqualDepth_ = false ;
2022-11-13 16:13:22 +00:00
bool everUsedExactEqualDepth_ = false ;
2022-11-08 04:07:57 +00:00
2014-09-26 16:06:55 +00:00
// Vertex collector buffers
2023-05-23 14:46:43 +00:00
u8 * decoded_ = nullptr ;
2023-05-23 16:00:50 +00:00
u16 * decIndex_ = nullptr ;
2015-04-08 19:35:00 +00:00
// Cached vertex decoders
2022-12-14 21:48:17 +00:00
u32 lastVType_ = - 1 ; // corresponds to dec_. Could really just pick it out of dec_...
2017-08-20 17:10:52 +00:00
DenseHashMap < u32 , VertexDecoder * , nullptr > decoderMap_ ;
2017-06-02 09:47:14 +00:00
VertexDecoder * dec_ = nullptr ;
2017-06-02 11:06:14 +00:00
VertexDecoderJitCache * decJitCache_ = nullptr ;
VertexDecoderOptions decOptions_ { } ;
2015-04-08 19:35:00 +00:00
2023-05-23 16:00:50 +00:00
TransformedVertex * transformed_ = nullptr ;
TransformedVertex * transformedExpanded_ = nullptr ;
2017-06-02 10:25:47 +00:00
2018-04-10 09:50:24 +00:00
// Defer all vertex decoding to a "Flush" (except when software skinning)
2017-06-02 10:03:46 +00:00
struct DeferredDrawCall {
2022-07-20 10:40:22 +00:00
const void * verts ;
const void * inds ;
2018-06-26 17:49:49 +00:00
u32 vertexCount ;
2017-06-02 10:03:46 +00:00
u8 indexType ;
s8 prim ;
2022-09-01 09:07:30 +00:00
u8 cullMode ;
2017-06-02 10:03:46 +00:00
u16 indexLowerBound ;
u16 indexUpperBound ;
2018-03-05 11:24:02 +00:00
UVScale uvScale ;
2017-06-02 10:03:46 +00:00
} ;
enum { MAX_DEFERRED_DRAW_CALLS = 128 } ;
2023-05-23 16:00:50 +00:00
DeferredDrawCall drawCalls_ [ MAX_DEFERRED_DRAW_CALLS ] ;
int numDrawCalls_ = 0 ;
2017-06-02 10:03:46 +00:00
int vertexCountInDrawCalls_ = 0 ;
int decimationCounter_ = 0 ;
int decodeCounter_ = 0 ;
// Vertex collector state
IndexGenerator indexGen ;
int decodedVerts_ = 0 ;
GEPrimitiveType prevPrim_ = GE_PRIM_INVALID ;
2017-02-17 11:21:18 +00:00
// Shader blending state
2017-06-02 10:03:46 +00:00
bool fboTexBound_ = false ;
2017-02-17 11:21:18 +00:00
2022-08-28 15:34:48 +00:00
// Sometimes, unusual situations mean we need to reset dirty flags after state calc finishes.
uint64_t dirtyRequiresRecheck_ = 0 ;
2022-09-02 19:07:29 +00:00
ComputedPipelineState pipelineState_ ;
2017-01-08 13:14:35 +00:00
// Hardware tessellation
TessellationDataTransfer * tessDataTransfer ;
2023-07-30 12:42:22 +00:00
// Culling
Plane planes_ [ 6 ] ;
Vec2f minOffset_ ;
Vec2f maxOffset_ ;
2015-03-01 14:28:11 +00:00
} ;