-
Notifications
You must be signed in to change notification settings - Fork 5
/
GSRasterizer.h
267 lines (217 loc) · 7.44 KB
/
GSRasterizer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* 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; either version 2, or (at your option)
* any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GS.h"
#include "GSVertexSW.h"
#include "GSFunctionMap.h"
#include "GSAlignedClass.h"
#include "GSPerfMon.h"
#ifdef ENABLE_BOOST
#include "GSThread_CXX11.h"
#else
#include "GSThread.h"
#endif
__aligned(class, 32) GSRasterizerData : public GSAlignedClass<32>
{
static int s_counter;
public:
GSVector4i scissor;
GSVector4i bbox;
GS_PRIM_CLASS primclass;
uint8* buff;
GSVertexSW* vertex;
int vertex_count;
uint32* index;
int index_count;
uint64 frame;
uint64 start;
int pixels;
int counter;
GSRasterizerData()
: scissor(GSVector4i::zero())
, bbox(GSVector4i::zero())
, primclass(GS_INVALID_CLASS)
, buff(NULL)
, vertex(NULL)
, vertex_count(0)
, index(NULL)
, index_count(0)
, frame(0)
, start(0)
, pixels(0)
{
counter = s_counter++;
}
virtual ~GSRasterizerData()
{
if(buff != NULL) _aligned_free(buff);
}
};
class IDrawScanline : public GSAlignedClass<32>
{
public:
typedef void (*SetupPrimPtr)(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan);
typedef void (__fastcall *DrawScanlinePtr)(int pixels, int left, int top, const GSVertexSW& scan);
typedef void (IDrawScanline::*DrawRectPtr)(const GSVector4i& r, const GSVertexSW& v); // TODO: jit
protected:
SetupPrimPtr m_sp;
DrawScanlinePtr m_ds;
DrawScanlinePtr m_de;
DrawRectPtr m_dr;
public:
IDrawScanline() : m_sp(NULL), m_ds(NULL), m_de(NULL), m_dr(NULL) {}
virtual ~IDrawScanline() {}
virtual void BeginDraw(const GSRasterizerData* data) = 0;
virtual void EndDraw(uint64 frame, uint64 ticks, int actual, int total) = 0;
#ifdef ENABLE_JIT_RASTERIZER
__forceinline void SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan) {m_sp(vertex, index, dscan);}
__forceinline void DrawScanline(int pixels, int left, int top, const GSVertexSW& scan) {m_ds(pixels, left, top, scan);}
__forceinline void DrawEdge(int pixels, int left, int top, const GSVertexSW& scan) {m_de(pixels, left, top, scan);}
__forceinline void DrawRect(const GSVector4i& r, const GSVertexSW& v) {(this->*m_dr)(r, v);}
#else
virtual void SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan) = 0;
virtual void DrawScanline(int pixels, int left, int top, const GSVertexSW& scan) = 0;
virtual void DrawEdge(int pixels, int left, int top, const GSVertexSW& scan) = 0;
virtual void DrawRect(const GSVector4i& r, const GSVertexSW& v) = 0;
#endif
virtual void PrintStats() = 0;
__forceinline bool HasEdge() const {return m_de != NULL;}
__forceinline bool IsSolidRect() const {return m_dr != NULL;}
};
class IRasterizer : public GSAlignedClass<32>
{
public:
virtual ~IRasterizer() {}
virtual void Queue(const shared_ptr<GSRasterizerData>& data) = 0;
virtual void Sync() = 0;
virtual bool IsSynced() const = 0;
virtual int GetPixels(bool reset = true) = 0;
virtual void PrintStats() = 0;
};
__aligned(class, 32) GSRasterizer : public IRasterizer
{
protected:
GSPerfMon* m_perfmon;
IDrawScanline* m_ds;
int m_id;
int m_threads;
uint8* m_scanline;
GSVector4i m_scissor;
GSVector4 m_fscissor_x;
GSVector4 m_fscissor_y;
struct {GSVertexSW* buff; int count;} m_edge;
struct {int sum, actual, total;} m_pixels;
typedef void (GSRasterizer::*DrawPrimPtr)(const GSVertexSW* v, int count);
template<bool scissor_test>
void DrawPoint(const GSVertexSW* vertex, int vertex_count, const uint32* index, int index_count);
void DrawLine(const GSVertexSW* vertex, const uint32* index);
void DrawTriangle(const GSVertexSW* vertex, const uint32* index);
void DrawSprite(const GSVertexSW* vertex, const uint32* index);
#if _M_SSE >= 0x501
__forceinline void DrawTriangleSection(int top, int bottom, GSVertexSW2& edge, const GSVertexSW2& dedge, const GSVertexSW2& dscan, const GSVector4& p0);
#else
__forceinline void DrawTriangleSection(int top, int bottom, GSVertexSW& edge, const GSVertexSW& dedge, const GSVertexSW& dscan, const GSVector4& p0);
#endif
void DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GSVertexSW& dv, int orientation, int side);
__forceinline void AddScanline(GSVertexSW* e, int pixels, int left, int top, const GSVertexSW& scan);
__forceinline void Flush(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan, bool edge = false);
__forceinline void DrawScanline(int pixels, int left, int top, const GSVertexSW& scan);
__forceinline void DrawEdge(int pixels, int left, int top, const GSVertexSW& scan);
public:
GSRasterizer(IDrawScanline* ds, int id, int threads, GSPerfMon* perfmon);
virtual ~GSRasterizer();
__forceinline bool IsOneOfMyScanlines(int top) const;
__forceinline bool IsOneOfMyScanlines(int top, int bottom) const;
__forceinline int FindMyNextScanline(int top) const;
void Draw(GSRasterizerData* data);
// IRasterizer
void Queue(const shared_ptr<GSRasterizerData>& data);
void Sync() {}
bool IsSynced() const {return true;}
int GetPixels(bool reset);
void PrintStats() {m_ds->PrintStats();}
};
class GSRasterizerList : public IRasterizer
{
protected:
class GSWorker : public GSJobQueue<shared_ptr<GSRasterizerData>, 256 >
{
GSRasterizer* m_r;
public:
GSWorker(GSRasterizer* r);
virtual ~GSWorker();
int GetPixels(bool reset);
// GSJobQueue
void Process(shared_ptr<GSRasterizerData>& item);
};
#ifdef ENABLE_BOOST
class GSWorkerSpin : public GSJobQueueSpin<shared_ptr<GSRasterizerData>, 256>
{
GSRasterizer* m_r;
public:
GSWorkerSpin(GSRasterizer* r);
virtual ~GSWorkerSpin();
int GetPixels(bool reset);
// GSJobQueue
void Process(shared_ptr<GSRasterizerData>& item);
};
#endif
GSPerfMon* m_perfmon;
#ifdef ENABLE_BOOST
vector<IGSJobQueue<shared_ptr<GSRasterizerData> > *> m_workers;
#else
vector<GSWorker*> m_workers;
#endif
uint8* m_scanline;
GSRasterizerList(int threads, GSPerfMon* perfmon);
public:
virtual ~GSRasterizerList();
template<class DS> static IRasterizer* Create(int threads, GSPerfMon* perfmon, bool spin_thread = false)
{
threads = std::max<int>(threads, 0);
if(threads == 0)
{
return new GSRasterizer(new DS(), 0, 1, perfmon);
}
else
{
GSRasterizerList* rl = new GSRasterizerList(threads, perfmon);
for(int i = 0; i < threads; i++)
{
#ifdef ENABLE_BOOST
if (spin_thread)
rl->m_workers.push_back(new GSWorkerSpin(new GSRasterizer(new DS(), i, threads, perfmon)));
else
rl->m_workers.push_back(new GSWorker(new GSRasterizer(new DS(), i, threads, perfmon)));
#else
rl->m_workers.push_back(new GSWorker(new GSRasterizer(new DS(), i, threads, perfmon)));
#endif
}
return rl;
}
}
// IRasterizer
void Queue(const shared_ptr<GSRasterizerData>& data);
void Sync();
bool IsSynced() const;
int GetPixels(bool reset);
void PrintStats() {}
};