blob: 3fec7954b98651f50d3e230624c67d33c3f37554 [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::QuadRasterizer(const PixelProcessor::State &state, const PixelShader *pixelShader) : Rasterizer(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
47 primitive = Arg<0>();
48 Int count = Arg<1>();
49 Int cluster = Arg<2>();
50 data = Arg<3>();
51
52 constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,constants));
53 occlusion = 0;
54
55 Do
John Bauman89401822014-05-06 15:04:28 -040056 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050057 Int yMin = *Pointer<Int>(primitive + OFFSET(Primitive,yMin));
58 Int yMax = *Pointer<Int>(primitive + OFFSET(Primitive,yMax));
John Bauman89401822014-05-06 15:04:28 -040059
Nicolas Capens4f172c72016-01-13 08:34:30 -050060 Int cluster2 = cluster + cluster;
61 yMin += clusterCount * 2 - 2 - cluster2;
62 yMin &= -clusterCount * 2;
63 yMin += cluster2;
John Bauman89401822014-05-06 15:04:28 -040064
Nicolas Capens4f172c72016-01-13 08:34:30 -050065 If(yMin < yMax)
John Bauman89401822014-05-06 15:04:28 -040066 {
Nicolas Capens4f172c72016-01-13 08:34:30 -050067 rasterize(yMin, yMax);
John Bauman89401822014-05-06 15:04:28 -040068 }
69
Nicolas Capens4f172c72016-01-13 08:34:30 -050070 primitive += sizeof(Primitive) * state.multiSample;
71 count--;
72 }
73 Until(count == 0)
John Bauman89401822014-05-06 15:04:28 -040074
Nicolas Capens4f172c72016-01-13 08:34:30 -050075 if(state.occlusionEnabled)
76 {
77 UInt clusterOcclusion = *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster);
78 clusterOcclusion += occlusion;
79 *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster) = clusterOcclusion;
John Bauman89401822014-05-06 15:04:28 -040080 }
81
Nicolas Capens4f172c72016-01-13 08:34:30 -050082 #if PERF_PROFILE
83 cycles[PERF_PIXEL] = Ticks() - pixelTime;
84
85 for(int i = 0; i < PERF_TIMERS; i++)
86 {
87 *Pointer<Long>(data + OFFSET(DrawData,cycles[i]) + 8 * cluster) += cycles[i];
88 }
89 #endif
90
91 Return();
John Bauman89401822014-05-06 15:04:28 -040092 }
93
Nicolas Capens4f172c72016-01-13 08:34:30 -050094 void QuadRasterizer::rasterize(Int &yMin, Int &yMax)
John Bauman89401822014-05-06 15:04:28 -040095 {
Alexis Hetu1edcd8b2015-11-05 11:12:41 -050096 Pointer<Byte> cBuffer[RENDERTARGETS];
John Bauman89401822014-05-06 15:04:28 -040097 Pointer<Byte> zBuffer;
98 Pointer<Byte> sBuffer;
99
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500100 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -0400101 {
102 if(state.colorWriteActive(index))
103 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500104 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 -0400105 }
106 }
107
108 if(state.depthTestActive)
109 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500110 zBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,depthBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData,depthPitchB));
John Bauman89401822014-05-06 15:04:28 -0400111 }
112
113 if(state.stencilActive)
114 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500115 sBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,stencilBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData,stencilPitchB));
John Bauman89401822014-05-06 15:04:28 -0400116 }
117
118 Int y = yMin;
Nicolas Capens81f18302016-01-14 09:32:35 -0500119
John Bauman89401822014-05-06 15:04:28 -0400120 Do
121 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500122 Int x0a = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
123 Int x0b = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500124 Int x0 = Min(x0a, x0b);
Nicolas Capens81f18302016-01-14 09:32:35 -0500125
John Bauman89401822014-05-06 15:04:28 -0400126 for(unsigned int q = 1; q < state.multiSample; q++)
127 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500128 x0a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
129 x0b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500130 x0 = Min(x0, Min(x0a, x0b));
John Bauman89401822014-05-06 15:04:28 -0400131 }
Nicolas Capens81f18302016-01-14 09:32:35 -0500132
John Bauman89401822014-05-06 15:04:28 -0400133 x0 &= 0xFFFFFFFE;
134
Nicolas Capens4f172c72016-01-13 08:34:30 -0500135 Int x1a = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
136 Int x1b = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500137 Int x1 = Max(x1a, x1b);
John Bauman89401822014-05-06 15:04:28 -0400138
139 for(unsigned int q = 1; q < state.multiSample; q++)
140 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500141 x1a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
142 x1b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500143 x1 = Max(x1, Max(x1a, x1b));
John Bauman89401822014-05-06 15:04:28 -0400144 }
145
Nicolas Capens4f172c72016-01-13 08:34:30 -0500146 Float4 yyyy = Float4(Float(y)) + *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16);
John Bauman89401822014-05-06 15:04:28 -0400147
John Bauman19bac1e2014-05-06 15:23:49 -0400148 if(interpolateZ())
John Bauman89401822014-05-06 15:04:28 -0400149 {
150 for(unsigned int q = 0; q < state.multiSample; q++)
151 {
152 Float4 y = yyyy;
153
154 if(state.multiSample > 1)
155 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500156 y -= *Pointer<Float4>(constants + OFFSET(Constants,Y) + q * sizeof(float4));
John Bauman89401822014-05-06 15:04:28 -0400157 }
158
Nicolas Capens4f172c72016-01-13 08:34:30 -0500159 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 -0400160 }
161 }
162
163 if(veryEarlyDepthTest && state.multiSample == 1)
164 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400165 if(!state.stencilActive && state.depthTestActive && (state.depthCompareMode == DEPTH_LESSEQUAL || state.depthCompareMode == DEPTH_LESS)) // FIXME: Both modes ok?
John Bauman89401822014-05-06 15:04:28 -0400166 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500167 Float4 xxxx = Float4(Float(x0)) + *Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16);
John Bauman89401822014-05-06 15:04:28 -0400168
169 Pointer<Byte> buffer;
170 Int pitch;
171
172 if(!state.quadLayoutDepthBuffer)
173 {
174 buffer = zBuffer + 4 * x0;
Nicolas Capens4f172c72016-01-13 08:34:30 -0500175 pitch = *Pointer<Int>(data + OFFSET(DrawData,depthPitchB));
John Bauman89401822014-05-06 15:04:28 -0400176 }
177 else
Nicolas Capens81f18302016-01-14 09:32:35 -0500178 {
John Bauman89401822014-05-06 15:04:28 -0400179 buffer = zBuffer + 8 * x0;
180 }
181
182 For(Int x = x0, x < x1, x += 2)
183 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500184 Float4 z = interpolate(xxxx, Dz[0], z, primitive + OFFSET(Primitive,z), false, false);
John Bauman89401822014-05-06 15:04:28 -0400185
186 Float4 zValue;
Nicolas Capens81f18302016-01-14 09:32:35 -0500187
John Bauman89401822014-05-06 15:04:28 -0400188 if(!state.quadLayoutDepthBuffer)
189 {
190 // FIXME: Properly optimizes?
191 zValue.xy = *Pointer<Float4>(buffer);
192 zValue.zw = *Pointer<Float4>(buffer + pitch - 8);
193 }
194 else
195 {
196 zValue = *Pointer<Float4>(buffer, 16);
197 }
198
199 Int4 zTest;
200
201 if(complementaryDepthBuffer)
202 {
203 zTest = CmpLE(zValue, z);
204 }
205 else
206 {
207 zTest = CmpNLT(zValue, z);
208 }
209
210 Int zMask = SignMask(zTest);
211
212 If(zMask == 0)
213 {
214 x0 += 2;
215 }
216 Else
217 {
218 x = x1;
219 }
220
221 xxxx += Float4(2);
222
223 if(!state.quadLayoutDepthBuffer)
224 {
225 buffer += 8;
226 }
227 else
228 {
229 buffer += 16;
230 }
231 }
232 }
233 }
234
235 If(x0 < x1)
236 {
John Bauman19bac1e2014-05-06 15:23:49 -0400237 if(interpolateW())
John Bauman89401822014-05-06 15:04:28 -0400238 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500239 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 -0400240 }
241
Nicolas Capens66be2452015-01-27 14:58:57 -0500242 for(int interpolant = 0; interpolant < 10; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400243 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500244 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400245 {
246 if(state.interpolant[interpolant].component & (1 << component))
247 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500248 Dv[interpolant][component] = *Pointer<Float4>(primitive + OFFSET(Primitive,V[interpolant][component].C), 16);
John Bauman89401822014-05-06 15:04:28 -0400249
250 if(!(state.interpolant[interpolant].flat & (1 << component)))
251 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500252 Dv[interpolant][component] += yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,V[interpolant][component].B), 16);
John Bauman89401822014-05-06 15:04:28 -0400253 }
254 }
255 }
256 }
257
Nicolas Capens66be2452015-01-27 14:58:57 -0500258 if(state.fog.component)
259 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500260 Df = *Pointer<Float4>(primitive + OFFSET(Primitive,f.C), 16);
Nicolas Capens66be2452015-01-27 14:58:57 -0500261
262 if(!state.fog.flat)
263 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500264 Df += yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,f.B), 16);
Nicolas Capens66be2452015-01-27 14:58:57 -0500265 }
266 }
267
John Bauman89401822014-05-06 15:04:28 -0400268 Short4 xLeft[4];
269 Short4 xRight[4];
270
271 for(unsigned int q = 0; q < state.multiSample; q++)
272 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500273 xLeft[q] = *Pointer<Short4>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline) + y * sizeof(Primitive::Span));
John Bauman89401822014-05-06 15:04:28 -0400274 xRight[q] = xLeft[q];
275
276 xLeft[q] = Swizzle(xLeft[q], 0xA0) - Short4(1, 2, 1, 2);
277 xRight[q] = Swizzle(xRight[q], 0xF5) - Short4(0, 1, 0, 1);
278 }
279
280 For(Int x = x0, x < x1, x += 2)
281 {
282 Short4 xxxx = Short4(x);
283 Int cMask[4];
284
285 for(unsigned int q = 0; q < state.multiSample; q++)
286 {
287 Short4 mask = CmpGT(xxxx, xLeft[q]) & CmpGT(xRight[q], xxxx);
288 cMask[q] = SignMask(Pack(mask, mask)) & 0x0000000F;
289 }
290
Nicolas Capens4f172c72016-01-13 08:34:30 -0500291 quad(cBuffer, zBuffer, sBuffer, cMask, x, y);
John Bauman89401822014-05-06 15:04:28 -0400292 }
293 }
294
Alexis Hetu1edcd8b2015-11-05 11:12:41 -0500295 for(int index = 0; index < RENDERTARGETS; index++)
John Bauman89401822014-05-06 15:04:28 -0400296 {
297 if(state.colorWriteActive(index))
298 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500299 cBuffer[index] += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index])) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400300 }
301 }
302
303 if(state.depthTestActive)
304 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500305 zBuffer += *Pointer<Int>(data + OFFSET(DrawData,depthPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400306 }
307
308 if(state.stencilActive)
309 {
Nicolas Capens4f172c72016-01-13 08:34:30 -0500310 sBuffer += *Pointer<Int>(data + OFFSET(DrawData,stencilPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400311 }
312
313 y += 2 * clusterCount;
314 }
315 Until(y >= yMax)
316 }
Alexis Hetuf2a8c372015-07-13 11:08:41 -0400317
318 Float4 QuadRasterizer::interpolate(Float4 &x, Float4 &D, Float4 &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective)
319 {
320 Float4 interpolant = D;
321
322 if(!flat)
323 {
324 interpolant += x * *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation, A), 16);
325
326 if(perspective)
327 {
328 interpolant *= rhw;
329 }
330 }
331
332 return interpolant;
333 }
334
335 bool QuadRasterizer::interpolateZ() const
336 {
337 return state.depthTestActive || state.pixelFogActive() || (shader && shader->vPosDeclared && fullPixelPositionRegister);
338 }
339
340 bool QuadRasterizer::interpolateW() const
341 {
342 return state.perspective || (shader && shader->vPosDeclared && fullPixelPositionRegister);
343 }
John Bauman89401822014-05-06 15:04:28 -0400344}