1 // Copyright (c) 2013- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 #pragma once
19 
20 #include <vector>
21 
22 #include "Common/CommonTypes.h"
23 #include "Common/Data/Collections/Hashmaps.h"
24 
25 #include "GPU/GPUState.h"
26 #include "GPU/Common/GPUDebugInterface.h"
27 #include "GPU/Common/IndexGenerator.h"
28 #include "GPU/Common/VertexDecoderCommon.h"
29 
30 class VertexDecoder;
31 
32 enum {
33 	VERTEX_BUFFER_MAX = 65536,
34 	DECODED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 64,
35 	DECODED_INDEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 16,
36 };
37 
38 inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode) {
39 	// As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it
40 	// into the top of the verttype where there are unused bits.
41 	return (vertType & 0xFFFFFF) | (uvGenMode << 24);
42 }
43 
44 struct SimpleVertex;
45 namespace Spline { struct Weight2D; }
46 
47 class TessellationDataTransfer {
48 public:
49 	virtual ~TessellationDataTransfer() {}
50 	void CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType);
51 	virtual void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) = 0;
52 };
53 
54 class DrawEngineCommon {
55 public:
56 	DrawEngineCommon();
57 	virtual ~DrawEngineCommon();
58 
59 	void Init();
60 
61 	bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
62 
63 	static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType);
64 
65 	// Flush is normally non-virtual but here's a virtual way to call it, used by the shared spline code, which is expensive anyway.
66 	// Not really sure if these wrappers are worth it...
67 	virtual void DispatchFlush() = 0;
68 
69 	// This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim
70 	// is different. Should probably refactor that.
71 	// Note that vertTypeID should be computed using GetVertTypeID().
72 	virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
73 		SubmitPrim(verts, inds, prim, vertexCount, vertTypeID, cullMode, bytesRead);
74 	}
75 
76 	bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead);
77 
78 	void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead);
79 	template<class Surface>
80 	void SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope);
81 	void ClearSplineBezierWeights();
82 
83 	bool CanUseHardwareTransform(int prim);
84 	bool CanUseHardwareTessellation(GEPatchPrimType prim);
85 
86 	std::vector<std::string> DebugGetVertexLoaderIDs();
87 	std::string DebugGetVertexLoaderString(std::string id, DebugShaderStringType stringType);
88 
89 	virtual void Resized();
90 
91 	bool IsCodePtrVertexDecoder(const u8 *ptr) const {
92 		return decJitCache_->IsInSpace(ptr);
93 	}
94 	int GetNumDrawCalls() const {
95 		return numDrawCalls;
96 	}
97 
98 	VertexDecoder *GetVertexDecoder(u32 vtype);
99 
100 protected:
101 	virtual bool UpdateUseHWTessellation(bool enabled) { return enabled; }
102 	virtual void ClearTrackedVertexArrays() {}
103 
104 	int ComputeNumVertsToDecode() const;
105 	void DecodeVerts(u8 *dest);
106 
107 	// Preprocessing for spline/bezier
108 	u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize = nullptr);
109 
110 	// Utility for vertex caching
111 	u32 ComputeMiniHash();
112 	uint64_t ComputeHash();
113 
114 	// Vertex decoding
115 	void DecodeVertsStep(u8 *dest, int &i, int &decodedVerts);
116 
117 	bool ApplyFramebufferRead(bool *fboTexNeedsBind);
118 
119 	inline int IndexSize(u32 vtype) const {
120 		const u32 indexType = (vtype & GE_VTYPE_IDX_MASK);
121 		if (indexType == GE_VTYPE_IDX_16BIT) {
122 			return 2;
123 		} else if (indexType == GE_VTYPE_IDX_32BIT) {
124 			return 4;
125 		}
126 		return 1;
127 	}
128 
129 	bool useHWTransform_ = false;
130 	bool useHWTessellation_ = false;
131 
132 	// Vertex collector buffers
133 	u8 *decoded = nullptr;
134 	u16 *decIndex = nullptr;
135 
136 	// Cached vertex decoders
137 	u32 lastVType_ = -1;
138 	DenseHashMap<u32, VertexDecoder *, nullptr> decoderMap_;
139 	VertexDecoder *dec_ = nullptr;
140 	VertexDecoderJitCache *decJitCache_ = nullptr;
141 	VertexDecoderOptions decOptions_{};
142 
143 	TransformedVertex *transformed = nullptr;
144 	TransformedVertex *transformedExpanded = nullptr;
145 
146 	// Defer all vertex decoding to a "Flush" (except when software skinning)
147 	struct DeferredDrawCall {
148 		void *verts;
149 		void *inds;
150 		u32 vertexCount;
151 		u8 indexType;
152 		s8 prim;
153 		u16 indexLowerBound;
154 		u16 indexUpperBound;
155 		UVScale uvScale;
156 		int cullMode;
157 	};
158 
159 	enum { MAX_DEFERRED_DRAW_CALLS = 128 };
160 	DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS];
161 	int numDrawCalls = 0;
162 	int vertexCountInDrawCalls_ = 0;
163 
164 	int decimationCounter_ = 0;
165 	int decodeCounter_ = 0;
166 	u32 dcid_ = 0;
167 
168 	// Vertex collector state
169 	IndexGenerator indexGen;
170 	int decodedVerts_ = 0;
171 	GEPrimitiveType prevPrim_ = GE_PRIM_INVALID;
172 
173 	// Shader blending state
174 	bool fboTexNeedsBind_ = false;
175 	bool fboTexBound_ = false;
176 
177 	// Hardware tessellation
178 	TessellationDataTransfer *tessDataTransfer;
179 };
180