blob: 6e390b0bfeaec75c94a439408f9749d6cf914c5d [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
Nicolas Capensba53fbf2016-01-14 13:43:42 -050028 QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, const PixelShader *pixelShader) : state(state), shader(pixelShader)
John Bauman89401822014-05-06 15:04:28 -040029 {
30 }
31
32 QuadRasterizer::~QuadRasterizer()
33 {
34 }
35
36 void QuadRasterizer::generate()
37 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050038 #if PERF_PROFILE
39 for(int i = 0; i < PERF_TIMERS; i++)
40 {
41 cycles[i] = 0;
42 }
43
44 Long pixelTime = Ticks();
45 #endif
46
Nicolas Capens4f172c72016-01-13 08:34:30 -050047 constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,constants));
48 occlusion = 0;
49
50 Do
John Bauman89401822014-05-06 15:04:28 -040051 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050052 Int yMin = *Pointer<Int>(primitive + OFFSET(Primitive,yMin));
53 Int yMax = *Pointer<Int>(primitive + OFFSET(Primitive,yMax));
John Bauman89401822014-05-06 15:04:28 -040054
Nicolas Capens4f172c72016-01-13 08:34:30 -050055 Int cluster2 = cluster + cluster;
56 yMin += clusterCount * 2 - 2 - cluster2;
57 yMin &= -clusterCount * 2;
58 yMin += cluster2;
John Bauman89401822014-05-06 15:04:28 -040059
Nicolas Capens4f172c72016-01-13 08:34:30 -050060 If(yMin < yMax)
John Bauman89401822014-05-06 15:04:28 -040061 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050062 rasterize(yMin, yMax);
John Bauman89401822014-05-06 15:04:28 -040063 }
64
Nicolas Capens4f172c72016-01-13 08:34:30 -050065 primitive += sizeof(Primitive) * state.multiSample;
66 count--;
67 }
68 Until(count == 0)
John Bauman89401822014-05-06 15:04:28 -040069
Nicolas Capens4f172c72016-01-13 08:34:30 -050070 if(state.occlusionEnabled)
71 {
72 UInt clusterOcclusion = *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster);
73 clusterOcclusion += occlusion;
74 *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster) = clusterOcclusion;
John Bauman89401822014-05-06 15:04:28 -040075 }
76
Nicolas Capens4f172c72016-01-13 08:34:30 -050077 #if PERF_PROFILE
78 cycles[PERF_PIXEL] = Ticks() - pixelTime;
79
80 for(int i = 0; i < PERF_TIMERS; i++)
81 {
82 *Pointer<Long>(data + OFFSET(DrawData,cycles[i]) + 8 * cluster) += cycles[i];
83 }
84 #endif
85
86 Return();
John Bauman89401822014-05-06 15:04:28 -040087 }
88
Nicolas Capens4f172c72016-01-13 08:34:30 -050089 void QuadRasterizer::rasterize(Int &yMin, Int &yMax)
John Bauman89401822014-05-06 15:04:28 -040090 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -050091 Pointer<Byte> cBuffer[RENDERTARGETS];
John Bauman89401822014-05-06 15:04:28 -040092 Pointer<Byte> zBuffer;
93 Pointer<Byte> sBuffer;
94
Alexis Hetu1edcd8b2015-11-05 11:12:41 -050095 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -040096 {
97 if(state.colorWriteActive(index))
98 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050099 cBuffer[index] = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,colorBuffer[index])) + yMin * *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
John Bauman89401822014-05-06 15:04:28 -0400100 }
101 }
102
103 if(state.depthTestActive)
104 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500105 zBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,depthBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData,depthPitchB));
John Bauman89401822014-05-06 15:04:28 -0400106 }
107
108 if(state.stencilActive)
109 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500110 sBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,stencilBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData,stencilPitchB));
John Bauman89401822014-05-06 15:04:28 -0400111 }
112
113 Int y = yMin;
Nicolas Capens81f18302016-01-14 09:32:35 -0500114
John Bauman89401822014-05-06 15:04:28 -0400115 Do
116 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500117 Int x0a = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
118 Int x0b = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500119 Int x0 = Min(x0a, x0b);
Nicolas Capens81f18302016-01-14 09:32:35 -0500120
John Bauman89401822014-05-06 15:04:28 -0400121 for(unsigned int q = 1; q < state.multiSample; q++)
122 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500123 x0a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
124 x0b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500125 x0 = Min(x0, Min(x0a, x0b));
John Bauman89401822014-05-06 15:04:28 -0400126 }
Nicolas Capens81f18302016-01-14 09:32:35 -0500127
John Bauman89401822014-05-06 15:04:28 -0400128 x0 &= 0xFFFFFFFE;
129
Nicolas Capens4f172c72016-01-13 08:34:30 -0500130 Int x1a = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
131 Int x1b = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500132 Int x1 = Max(x1a, x1b);
John Bauman89401822014-05-06 15:04:28 -0400133
134 for(unsigned int q = 1; q < state.multiSample; q++)
135 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500136 x1a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
137 x1b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500138 x1 = Max(x1, Max(x1a, x1b));
John Bauman89401822014-05-06 15:04:28 -0400139 }
140
Nicolas Capens4f172c72016-01-13 08:34:30 -0500141 Float4 yyyy = Float4(Float(y)) + *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16);
John Bauman89401822014-05-06 15:04:28 -0400142
John Bauman19bac1e2014-05-06 15:23:49 -0400143 if(interpolateZ())
John Bauman89401822014-05-06 15:04:28 -0400144 {
145 for(unsigned int q = 0; q < state.multiSample; q++)
146 {
147 Float4 y = yyyy;
148
149 if(state.multiSample > 1)
150 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500151 y -= *Pointer<Float4>(constants + OFFSET(Constants,Y) + q * sizeof(float4));
John Bauman89401822014-05-06 15:04:28 -0400152 }
153
Nicolas Capens4f172c72016-01-13 08:34:30 -0500154 Dz[q] = *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) + y * *Pointer<Float4>(primitive + OFFSET(Primitive,z.B), 16);
John Bauman89401822014-05-06 15:04:28 -0400155 }
156 }
157
158 if(veryEarlyDepthTest && state.multiSample == 1)
159 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400160 if(!state.stencilActive && state.depthTestActive && (state.depthCompareMode == DEPTH_LESSEQUAL || state.depthCompareMode == DEPTH_LESS)) // FIXME: Both modes ok?
John Bauman89401822014-05-06 15:04:28 -0400161 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500162 Float4 xxxx = Float4(Float(x0)) + *Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16);
John Bauman89401822014-05-06 15:04:28 -0400163
164 Pointer<Byte> buffer;
165 Int pitch;
166
167 if(!state.quadLayoutDepthBuffer)
168 {
169 buffer = zBuffer + 4 * x0;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500170 pitch = *Pointer<Int>(data + OFFSET(DrawData,depthPitchB));
John Bauman89401822014-05-06 15:04:28 -0400171 }
172 else
Nicolas Capens81f18302016-01-14 09:32:35 -0500173 {
John Bauman89401822014-05-06 15:04:28 -0400174 buffer = zBuffer + 8 * x0;
175 }
176
177 For(Int x = x0, x < x1, x += 2)
178 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500179 Float4 z = interpolate(xxxx, Dz[0], z, primitive + OFFSET(Primitive,z), false, false);
John Bauman89401822014-05-06 15:04:28 -0400180
181 Float4 zValue;
Nicolas Capens81f18302016-01-14 09:32:35 -0500182
John Bauman89401822014-05-06 15:04:28 -0400183 if(!state.quadLayoutDepthBuffer)
184 {
185 // FIXME: Properly optimizes?
186 zValue.xy = *Pointer<Float4>(buffer);
187 zValue.zw = *Pointer<Float4>(buffer + pitch - 8);
188 }
189 else
190 {
191 zValue = *Pointer<Float4>(buffer, 16);
192 }
193
194 Int4 zTest;
195
196 if(complementaryDepthBuffer)
197 {
198 zTest = CmpLE(zValue, z);
199 }
200 else
201 {
202 zTest = CmpNLT(zValue, z);
203 }
204
205 Int zMask = SignMask(zTest);
206
207 If(zMask == 0)
208 {
209 x0 += 2;
210 }
211 Else
212 {
213 x = x1;
214 }
215
216 xxxx += Float4(2);
217
218 if(!state.quadLayoutDepthBuffer)
219 {
220 buffer += 8;
221 }
222 else
223 {
224 buffer += 16;
225 }
226 }
227 }
228 }
229
230 If(x0 < x1)
231 {
John Bauman19bac1e2014-05-06 15:23:49 -0400232 if(interpolateW())
John Bauman89401822014-05-06 15:04:28 -0400233 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500234 Dw = *Pointer<Float4>(primitive + OFFSET(Primitive,w.C), 16) + yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,w.B), 16);
John Bauman89401822014-05-06 15:04:28 -0400235 }
236
Nicolas Capens66be2452015-01-27 14:58:57 -0500237 for(int interpolant = 0; interpolant < 10; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400238 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500239 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400240 {
241 if(state.interpolant[interpolant].component & (1 << component))
242 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500243 Dv[interpolant][component] = *Pointer<Float4>(primitive + OFFSET(Primitive,V[interpolant][component].C), 16);
John Bauman89401822014-05-06 15:04:28 -0400244
245 if(!(state.interpolant[interpolant].flat & (1 << component)))
246 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500247 Dv[interpolant][component] += yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,V[interpolant][component].B), 16);
John Bauman89401822014-05-06 15:04:28 -0400248 }
249 }
250 }
251 }
252
Nicolas Capens66be2452015-01-27 14:58:57 -0500253 if(state.fog.component)
254 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500255 Df = *Pointer<Float4>(primitive + OFFSET(Primitive,f.C), 16);
Nicolas Capens66be2452015-01-27 14:58:57 -0500256
257 if(!state.fog.flat)
258 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500259 Df += yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,f.B), 16);
Nicolas Capens66be2452015-01-27 14:58:57 -0500260 }
261 }
262
John Bauman89401822014-05-06 15:04:28 -0400263 Short4 xLeft[4];
264 Short4 xRight[4];
265
266 for(unsigned int q = 0; q < state.multiSample; q++)
267 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500268 xLeft[q] = *Pointer<Short4>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline) + y * sizeof(Primitive::Span));
John Bauman89401822014-05-06 15:04:28 -0400269 xRight[q] = xLeft[q];
270
271 xLeft[q] = Swizzle(xLeft[q], 0xA0) - Short4(1, 2, 1, 2);
272 xRight[q] = Swizzle(xRight[q], 0xF5) - Short4(0, 1, 0, 1);
273 }
274
275 For(Int x = x0, x < x1, x += 2)
276 {
277 Short4 xxxx = Short4(x);
278 Int cMask[4];
279
280 for(unsigned int q = 0; q < state.multiSample; q++)
281 {
282 Short4 mask = CmpGT(xxxx, xLeft[q]) & CmpGT(xRight[q], xxxx);
283 cMask[q] = SignMask(Pack(mask, mask)) & 0x0000000F;
284 }
285
Nicolas Capens4f172c72016-01-13 08:34:30 -0500286 quad(cBuffer, zBuffer, sBuffer, cMask, x, y);
John Bauman89401822014-05-06 15:04:28 -0400287 }
288 }
289
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500290 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -0400291 {
292 if(state.colorWriteActive(index))
293 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500294 cBuffer[index] += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index])) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400295 }
296 }
297
298 if(state.depthTestActive)
299 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500300 zBuffer += *Pointer<Int>(data + OFFSET(DrawData,depthPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400301 }
302
303 if(state.stencilActive)
304 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500305 sBuffer += *Pointer<Int>(data + OFFSET(DrawData,stencilPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400306 }
307
308 y += 2 * clusterCount;
309 }
310 Until(y >= yMax)
311 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400312
313 Float4 QuadRasterizer::interpolate(Float4 &x, Float4 &D, Float4 &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective)
314 {
315 Float4 interpolant = D;
316
317 if(!flat)
318 {
319 interpolant += x * *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation, A), 16);
320
321 if(perspective)
322 {
323 interpolant *= rhw;
324 }
325 }
326
327 return interpolant;
328 }
329
330 bool QuadRasterizer::interpolateZ() const
331 {
332 return state.depthTestActive || state.pixelFogActive() || (shader && shader->vPosDeclared && fullPixelPositionRegister);
333 }
334
335 bool QuadRasterizer::interpolateW() const
336 {
337 return state.perspective || (shader && shader->vPosDeclared && fullPixelPositionRegister);
338 }
John Bauman89401822014-05-06 15:04:28 -0400339}