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
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 ( ) { }
2018-07-13 18:35:44 +09: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 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
} ;
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().
2022-07-20 12:40:22 +02:00
virtual void DispatchSubmitPrim ( const void * verts , const void * inds , GEPrimitiveType prim , int vertexCount , u32 vertTypeID , int cullMode , int * bytesRead ) {
2018-12-16 13:00:36 -08:00
SubmitPrim ( verts , inds , prim , vertexCount , vertTypeID , cullMode , 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
2022-07-20 12:40:22 +02:00
void SubmitPrim ( const void * verts , const void * inds , GEPrimitiveType prim , int vertexCount , u32 vertTypeID , int cullMode , 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 ) ;
2018-01-31 21:42:39 +09:00
void ClearSplineBezierWeights ( ) ;
2015-04-08 21:37:54 +02:00
2020-04-04 11:14:32 -07:00
bool CanUseHardwareTransform ( int prim ) ;
bool CanUseHardwareTessellation ( GEPatchPrimType prim ) ;
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
2017-10-20 11:06:06 +02:00
bool IsCodePtrVertexDecoder ( const u8 * ptr ) const {
2023-02-28 07:03:12 -08:00
if ( decJitCache_ )
return decJitCache_ - > IsInSpace ( ptr ) ;
return false ;
2017-10-20 11:06:06 +02:00
}
2018-02-26 13:51:14 +01:00
int GetNumDrawCalls ( ) const {
return numDrawCalls ;
}
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 ( ) { }
2014-09-26 09:06:55 -07:00
protected :
2020-04-04 11:52:32 -07:00
virtual bool UpdateUseHWTessellation ( bool enabled ) { return enabled ; }
2017-03-17 10:27:49 +01:00
2017-11-19 12:38:52 +01:00
int ComputeNumVertsToDecode ( ) const ;
void DecodeVerts ( u8 * dest ) ;
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
2017-06-02 12:16:43 +02:00
// Utility for vertex caching
u32 ComputeMiniHash ( ) ;
2020-08-27 20:37:49 -07:00
uint64_t ComputeHash ( ) ;
2017-06-02 12:16:43 +02:00
2017-06-02 12:09:57 +02:00
// Vertex decoding
void DecodeVertsStep ( u8 * dest , int & i , int & decodedVerts ) ;
2022-02-19 20:40:27 +01:00
void ApplyFramebufferRead ( FBOTexState * fboTexState ) ;
2016-09-18 19:40:44 -07:00
2016-04-10 01:52:51 -07: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-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 ;
}
}
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 ;
2017-06-02 12:03:46 +02:00
u16 * decIndex = nullptr ;
2015-04-08 21:35:00 +02:00
// Cached vertex decoders
2022-12-14 22:48:17 +01:00
u32 lastVType_ = - 1 ; // corresponds to dec_. Could really just pick it out of dec_...
2017-08-20 19:10:52 +02:00
DenseHashMap < u32 , VertexDecoder * , nullptr > decoderMap_ ;
2017-06-02 11:47:14 +02:00
VertexDecoder * dec_ = nullptr ;
2017-06-02 13:06:14 +02:00
VertexDecoderJitCache * decJitCache_ = nullptr ;
VertexDecoderOptions decOptions_ { } ;
2015-04-08 21:35:00 +02:00
2017-06-02 12:25:47 +02:00
TransformedVertex * transformed = nullptr ;
TransformedVertex * transformedExpanded = nullptr ;
2018-04-10 11:50:24 +02:00
// Defer all vertex decoding to a "Flush" (except when software skinning)
2017-06-02 12:03:46 +02:00
struct DeferredDrawCall {
2022-07-20 12:40:22 +02:00
const void * verts ;
const void * inds ;
2018-06-26 19:49:49 +02:00
u32 vertexCount ;
2017-06-02 12:03:46 +02:00
u8 indexType ;
s8 prim ;
2022-09-01 11:07:30 +02:00
u8 cullMode ;
2017-06-02 12:03:46 +02:00
u16 indexLowerBound ;
u16 indexUpperBound ;
2018-03-05 12:24:02 +01:00
UVScale uvScale ;
2017-06-02 12:03:46 +02:00
} ;
enum { MAX_DEFERRED_DRAW_CALLS = 128 } ;
DeferredDrawCall drawCalls [ MAX_DEFERRED_DRAW_CALLS ] ;
int numDrawCalls = 0 ;
int vertexCountInDrawCalls_ = 0 ;
int decimationCounter_ = 0 ;
int decodeCounter_ = 0 ;
u32 dcid_ = 0 ;
// Vertex collector state
IndexGenerator indexGen ;
int decodedVerts_ = 0 ;
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 ;
2015-03-01 15:28:11 +01:00
} ;