blob: 40c84e9c49b40cd0f3b465c21f8af6cc1032fcb4 [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Bauman19bac1e2014-05-06 15:23:49 -04003// Copyright(c) 2005-2012 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "QuadRasterizer.hpp"
13
14#include "Math.hpp"
15#include "Primitive.hpp"
16#include "Renderer.hpp"
17#include "Constants.hpp"
18#include "Debug.hpp"
19
20namespace sw
21{
22 extern bool veryEarlyDepthTest;
23 extern bool complementaryDepthBuffer;
Alexis Hetuf2a8c372015-07-13 11:08:41 -040024 extern bool fullPixelPositionRegister;
John Bauman89401822014-05-06 15:04:28 -040025
26 extern int clusterCount;
27
Alexis Hetuf2a8c372015-07-13 11:08:41 -040028 QuadRasterizer::Registers::Registers()
29 {
30 occlusion = 0;
31
32#if PERF_PROFILE
33 for(int i = 0; i < PERF_TIMERS; i++)
34 {
35 cycles[i] = 0;
36 }
37#endif
38 }
39
40 QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, const PixelShader *pixelShader) : Rasterizer(state), shader(pixelShader)
John Bauman89401822014-05-06 15:04:28 -040041 {
42 }
43
44 QuadRasterizer::~QuadRasterizer()
45 {
46 }
47
48 void QuadRasterizer::generate()
49 {
John Bauman66b8ab22014-05-06 15:57:45 -040050 Function<Void, Pointer<Byte>, Int, Int, Pointer<Byte> > function;
John Bauman89401822014-05-06 15:04:28 -040051 {
52 #if PERF_PROFILE
53 Long pixelTime = Ticks();
54 #endif
55
56 Pointer<Byte> primitive(function.arg(0));
57 Int count(function.arg(1));
58 Int cluster(function.arg(2));
59 Pointer<Byte> data(function.arg(3));
60
Alexis Hetuf2a8c372015-07-13 11:08:41 -040061 Registers& r = *createRegisters(shader);
John Bauman66b8ab22014-05-06 15:57:45 -040062 r.constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
John Bauman89401822014-05-06 15:04:28 -040063 r.cluster = cluster;
64 r.data = data;
65
66 Do
67 {
68 r.primitive = primitive;
69
70 Int yMin = *Pointer<Int>(primitive + OFFSET(Primitive,yMin));
71 Int yMax = *Pointer<Int>(primitive + OFFSET(Primitive,yMax));
72
73 Int cluster2 = r.cluster + r.cluster;
74 yMin += clusterCount * 2 - 2 - cluster2;
75 yMin &= -clusterCount * 2;
76 yMin += cluster2;
77
78 If(yMin < yMax)
79 {
80 rasterize(r, yMin, yMax);
81 }
82
83 primitive += sizeof(Primitive) * state.multiSample;
84 count--;
85 }
86 Until(count == 0)
87
88 if(state.occlusionEnabled)
89 {
90 UInt clusterOcclusion = *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster);
91 clusterOcclusion += r.occlusion;
92 *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster) = clusterOcclusion;
93 }
94
95 #if PERF_PROFILE
96 r.cycles[PERF_PIXEL] = Ticks() - pixelTime;
97
98 for(int i = 0; i < PERF_TIMERS; i++)
99 {
100 *Pointer<Long>(data + OFFSET(DrawData,cycles[i]) + 8 * cluster) += r.cycles[i];
101 }
102 #endif
103
104 Return();
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400105
106 delete &r;
John Bauman89401822014-05-06 15:04:28 -0400107 }
108
John Bauman19bac1e2014-05-06 15:23:49 -0400109 routine = function(L"PixelRoutine_%0.8X", state.shaderID);
John Bauman89401822014-05-06 15:04:28 -0400110 }
111
112 void QuadRasterizer::rasterize(Registers &r, Int &yMin, Int &yMax)
113 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500114 Pointer<Byte> cBuffer[RENDERTARGETS];
John Bauman89401822014-05-06 15:04:28 -0400115 Pointer<Byte> zBuffer;
116 Pointer<Byte> sBuffer;
117
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500118 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -0400119 {
120 if(state.colorWriteActive(index))
121 {
John Bauman66b8ab22014-05-06 15:57:45 -0400122 cBuffer[index] = *Pointer<Pointer<Byte> >(r.data + OFFSET(DrawData,colorBuffer[index])) + yMin * *Pointer<Int>(r.data + OFFSET(DrawData,colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -0400123 }
124 }
125
126 if(state.depthTestActive)
127 {
John Bauman66b8ab22014-05-06 15:57:45 -0400128 zBuffer = *Pointer<Pointer<Byte> >(r.data + OFFSET(DrawData,depthBuffer)) + yMin * *Pointer<Int>(r.data + OFFSET(DrawData,depthPitchB));
John Bauman89401822014-05-06 15:04:28 -0400129 }
130
131 if(state.stencilActive)
132 {
John Bauman66b8ab22014-05-06 15:57:45 -0400133 sBuffer = *Pointer<Pointer<Byte> >(r.data + OFFSET(DrawData,stencilBuffer)) + yMin * *Pointer<Int>(r.data + OFFSET(DrawData,stencilPitchB));
John Bauman89401822014-05-06 15:04:28 -0400134 }
135
136 Int y = yMin;
137
138 Do
139 {
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500140 Int x0a = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
141 Int x0b = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
142 Int x0 = Min(x0a, x0b);
John Bauman89401822014-05-06 15:04:28 -0400143
144 for(unsigned int q = 1; q < state.multiSample; q++)
145 {
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500146 x0a = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
147 x0b = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
148 x0 = Min(x0, Min(x0a, x0b));
John Bauman89401822014-05-06 15:04:28 -0400149 }
150
151 x0 &= 0xFFFFFFFE;
152
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500153 Int x1a = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
154 Int x1b = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
155 Int x1 = Max(x1a, x1b);
John Bauman89401822014-05-06 15:04:28 -0400156
157 for(unsigned int q = 1; q < state.multiSample; q++)
158 {
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500159 x1a = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
160 x1b = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
161 x1 = Max(x1, Max(x1a, x1b));
John Bauman89401822014-05-06 15:04:28 -0400162 }
163
164 Float4 yyyy = Float4(Float(y)) + *Pointer<Float4>(r.primitive + OFFSET(Primitive,yQuad), 16);
165
John Bauman19bac1e2014-05-06 15:23:49 -0400166 if(interpolateZ())
John Bauman89401822014-05-06 15:04:28 -0400167 {
168 for(unsigned int q = 0; q < state.multiSample; q++)
169 {
170 Float4 y = yyyy;
171
172 if(state.multiSample > 1)
173 {
174 y -= *Pointer<Float4>(r.constants + OFFSET(Constants,Y) + q * sizeof(float4));
175 }
176
177 r.Dz[q] = *Pointer<Float4>(r.primitive + OFFSET(Primitive,z.C), 16) + y * *Pointer<Float4>(r.primitive + OFFSET(Primitive,z.B), 16);
178 }
179 }
180
181 if(veryEarlyDepthTest && state.multiSample == 1)
182 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400183 if(!state.stencilActive && state.depthTestActive && (state.depthCompareMode == DEPTH_LESSEQUAL || state.depthCompareMode == DEPTH_LESS)) // FIXME: Both modes ok?
John Bauman89401822014-05-06 15:04:28 -0400184 {
185 Float4 xxxx = Float4(Float(x0)) + *Pointer<Float4>(r.primitive + OFFSET(Primitive,xQuad), 16);
186
187 Pointer<Byte> buffer;
188 Int pitch;
189
190 if(!state.quadLayoutDepthBuffer)
191 {
192 buffer = zBuffer + 4 * x0;
193 pitch = *Pointer<Int>(r.data + OFFSET(DrawData,depthPitchB));
194 }
195 else
196 {
197 buffer = zBuffer + 8 * x0;
198 }
199
200 For(Int x = x0, x < x1, x += 2)
201 {
202 Float4 z = interpolate(xxxx, r.Dz[0], z, r.primitive + OFFSET(Primitive,z), false, false);
203
204 Float4 zValue;
205
206 if(!state.quadLayoutDepthBuffer)
207 {
208 // FIXME: Properly optimizes?
209 zValue.xy = *Pointer<Float4>(buffer);
210 zValue.zw = *Pointer<Float4>(buffer + pitch - 8);
211 }
212 else
213 {
214 zValue = *Pointer<Float4>(buffer, 16);
215 }
216
217 Int4 zTest;
218
219 if(complementaryDepthBuffer)
220 {
221 zTest = CmpLE(zValue, z);
222 }
223 else
224 {
225 zTest = CmpNLT(zValue, z);
226 }
227
228 Int zMask = SignMask(zTest);
229
230 If(zMask == 0)
231 {
232 x0 += 2;
233 }
234 Else
235 {
236 x = x1;
237 }
238
239 xxxx += Float4(2);
240
241 if(!state.quadLayoutDepthBuffer)
242 {
243 buffer += 8;
244 }
245 else
246 {
247 buffer += 16;
248 }
249 }
250 }
251 }
252
253 If(x0 < x1)
254 {
John Bauman19bac1e2014-05-06 15:23:49 -0400255 if(interpolateW())
John Bauman89401822014-05-06 15:04:28 -0400256 {
257 r.Dw = *Pointer<Float4>(r.primitive + OFFSET(Primitive,w.C), 16) + yyyy * *Pointer<Float4>(r.primitive + OFFSET(Primitive,w.B), 16);
258 }
259
Nicolas Capens66be2452015-01-27 14:58:57 -0500260 for(int interpolant = 0; interpolant < 10; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400261 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500262 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400263 {
264 if(state.interpolant[interpolant].component & (1 << component))
265 {
266 r.Dv[interpolant][component] = *Pointer<Float4>(r.primitive + OFFSET(Primitive,V[interpolant][component].C), 16);
267
268 if(!(state.interpolant[interpolant].flat & (1 << component)))
269 {
270 r.Dv[interpolant][component] += yyyy * *Pointer<Float4>(r.primitive + OFFSET(Primitive,V[interpolant][component].B), 16);
271 }
272 }
273 }
274 }
275
Nicolas Capens66be2452015-01-27 14:58:57 -0500276 if(state.fog.component)
277 {
278 r.Df = *Pointer<Float4>(r.primitive + OFFSET(Primitive,f.C), 16);
279
280 if(!state.fog.flat)
281 {
282 r.Df += yyyy * *Pointer<Float4>(r.primitive + OFFSET(Primitive,f.B), 16);
283 }
284 }
285
John Bauman89401822014-05-06 15:04:28 -0400286 Short4 xLeft[4];
287 Short4 xRight[4];
288
289 for(unsigned int q = 0; q < state.multiSample; q++)
290 {
291 xLeft[q] = *Pointer<Short4>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline) + y * sizeof(Primitive::Span));
292 xRight[q] = xLeft[q];
293
294 xLeft[q] = Swizzle(xLeft[q], 0xA0) - Short4(1, 2, 1, 2);
295 xRight[q] = Swizzle(xRight[q], 0xF5) - Short4(0, 1, 0, 1);
296 }
297
298 For(Int x = x0, x < x1, x += 2)
299 {
300 Short4 xxxx = Short4(x);
301 Int cMask[4];
302
303 for(unsigned int q = 0; q < state.multiSample; q++)
304 {
305 Short4 mask = CmpGT(xxxx, xLeft[q]) & CmpGT(xRight[q], xxxx);
306 cMask[q] = SignMask(Pack(mask, mask)) & 0x0000000F;
307 }
308
309 quad(r, cBuffer, zBuffer, sBuffer, cMask, x, y);
310 }
311 }
312
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500313 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -0400314 {
315 if(state.colorWriteActive(index))
316 {
John Bauman19bac1e2014-05-06 15:23:49 -0400317 cBuffer[index] += *Pointer<Int>(r.data + OFFSET(DrawData,colorPitchB[index])) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400318 }
319 }
320
321 if(state.depthTestActive)
322 {
John Bauman19bac1e2014-05-06 15:23:49 -0400323 zBuffer += *Pointer<Int>(r.data + OFFSET(DrawData,depthPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400324 }
325
326 if(state.stencilActive)
327 {
John Bauman19bac1e2014-05-06 15:23:49 -0400328 sBuffer += *Pointer<Int>(r.data + OFFSET(DrawData,stencilPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400329 }
330
331 y += 2 * clusterCount;
332 }
333 Until(y >= yMax)
334 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400335
336 Float4 QuadRasterizer::interpolate(Float4 &x, Float4 &D, Float4 &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective)
337 {
338 Float4 interpolant = D;
339
340 if(!flat)
341 {
342 interpolant += x * *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation, A), 16);
343
344 if(perspective)
345 {
346 interpolant *= rhw;
347 }
348 }
349
350 return interpolant;
351 }
352
353 bool QuadRasterizer::interpolateZ() const
354 {
355 return state.depthTestActive || state.pixelFogActive() || (shader && shader->vPosDeclared && fullPixelPositionRegister);
356 }
357
358 bool QuadRasterizer::interpolateW() const
359 {
360 return state.perspective || (shader && shader->vPosDeclared && fullPixelPositionRegister);
361 }
John Bauman89401822014-05-06 15:04:28 -0400362}