blob: 543c0ce47c6d94eed845106ec58b847ec68076ff [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;
24
25 extern int clusterCount;
26
27 QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, const PixelShader *pixelShader) : PixelRoutine(state, pixelShader)
28 {
29 }
30
31 QuadRasterizer::~QuadRasterizer()
32 {
33 }
34
35 void QuadRasterizer::generate()
36 {
John Bauman66b8ab22014-05-06 15:57:45 -040037 Function<Void, Pointer<Byte>, Int, Int, Pointer<Byte> > function;
John Bauman89401822014-05-06 15:04:28 -040038 {
39 #if PERF_PROFILE
40 Long pixelTime = Ticks();
41 #endif
42
43 Pointer<Byte> primitive(function.arg(0));
44 Int count(function.arg(1));
45 Int cluster(function.arg(2));
46 Pointer<Byte> data(function.arg(3));
47
John Bauman19bac1e2014-05-06 15:23:49 -040048 Registers r(shader);
John Bauman66b8ab22014-05-06 15:57:45 -040049 r.constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
John Bauman89401822014-05-06 15:04:28 -040050 r.cluster = cluster;
51 r.data = data;
52
53 Do
54 {
55 r.primitive = primitive;
56
57 Int yMin = *Pointer<Int>(primitive + OFFSET(Primitive,yMin));
58 Int yMax = *Pointer<Int>(primitive + OFFSET(Primitive,yMax));
59
60 Int cluster2 = r.cluster + r.cluster;
61 yMin += clusterCount * 2 - 2 - cluster2;
62 yMin &= -clusterCount * 2;
63 yMin += cluster2;
64
65 If(yMin < yMax)
66 {
67 rasterize(r, yMin, yMax);
68 }
69
70 primitive += sizeof(Primitive) * state.multiSample;
71 count--;
72 }
73 Until(count == 0)
74
75 if(state.occlusionEnabled)
76 {
77 UInt clusterOcclusion = *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster);
78 clusterOcclusion += r.occlusion;
79 *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster) = clusterOcclusion;
80 }
81
82 #if PERF_PROFILE
83 r.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) += r.cycles[i];
88 }
89 #endif
90
91 Return();
92 }
93
John Bauman19bac1e2014-05-06 15:23:49 -040094 routine = function(L"PixelRoutine_%0.8X", state.shaderID);
John Bauman89401822014-05-06 15:04:28 -040095 }
96
97 void QuadRasterizer::rasterize(Registers &r, Int &yMin, Int &yMax)
98 {
99 Pointer<Byte> cBuffer[4];
100 Pointer<Byte> zBuffer;
101 Pointer<Byte> sBuffer;
102
103 for(int index = 0; index < 4; index++)
104 {
105 if(state.colorWriteActive(index))
106 {
John Bauman66b8ab22014-05-06 15:57:45 -0400107 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 -0400108 }
109 }
110
111 if(state.depthTestActive)
112 {
John Bauman66b8ab22014-05-06 15:57:45 -0400113 zBuffer = *Pointer<Pointer<Byte> >(r.data + OFFSET(DrawData,depthBuffer)) + yMin * *Pointer<Int>(r.data + OFFSET(DrawData,depthPitchB));
John Bauman89401822014-05-06 15:04:28 -0400114 }
115
116 if(state.stencilActive)
117 {
John Bauman66b8ab22014-05-06 15:57:45 -0400118 sBuffer = *Pointer<Pointer<Byte> >(r.data + OFFSET(DrawData,stencilBuffer)) + yMin * *Pointer<Int>(r.data + OFFSET(DrawData,stencilPitchB));
John Bauman89401822014-05-06 15:04:28 -0400119 }
120
121 Int y = yMin;
122
123 Do
124 {
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500125 Int x0a = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
126 Int x0b = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
127 Int x0 = Min(x0a, x0b);
John Bauman89401822014-05-06 15:04:28 -0400128
129 for(unsigned int q = 1; q < state.multiSample; q++)
130 {
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500131 x0a = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
132 x0b = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
133 x0 = Min(x0, Min(x0a, x0b));
John Bauman89401822014-05-06 15:04:28 -0400134 }
135
136 x0 &= 0xFFFFFFFE;
137
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500138 Int x1a = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
139 Int x1b = Int(*Pointer<Short>(r.primitive + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
140 Int x1 = Max(x1a, x1b);
John Bauman89401822014-05-06 15:04:28 -0400141
142 for(unsigned int q = 1; q < state.multiSample; q++)
143 {
Nicolas Capensc50d35d2015-01-27 01:52:41 -0500144 x1a = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
145 x1b = Int(*Pointer<Short>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
146 x1 = Max(x1, Max(x1a, x1b));
John Bauman89401822014-05-06 15:04:28 -0400147 }
148
149 Float4 yyyy = Float4(Float(y)) + *Pointer<Float4>(r.primitive + OFFSET(Primitive,yQuad), 16);
150
John Bauman19bac1e2014-05-06 15:23:49 -0400151 if(interpolateZ())
John Bauman89401822014-05-06 15:04:28 -0400152 {
153 for(unsigned int q = 0; q < state.multiSample; q++)
154 {
155 Float4 y = yyyy;
156
157 if(state.multiSample > 1)
158 {
159 y -= *Pointer<Float4>(r.constants + OFFSET(Constants,Y) + q * sizeof(float4));
160 }
161
162 r.Dz[q] = *Pointer<Float4>(r.primitive + OFFSET(Primitive,z.C), 16) + y * *Pointer<Float4>(r.primitive + OFFSET(Primitive,z.B), 16);
163 }
164 }
165
166 if(veryEarlyDepthTest && state.multiSample == 1)
167 {
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400168 if(!state.stencilActive && state.depthTestActive && (state.depthCompareMode == DEPTH_LESSEQUAL || state.depthCompareMode == DEPTH_LESS)) // FIXME: Both modes ok?
John Bauman89401822014-05-06 15:04:28 -0400169 {
170 Float4 xxxx = Float4(Float(x0)) + *Pointer<Float4>(r.primitive + OFFSET(Primitive,xQuad), 16);
171
172 Pointer<Byte> buffer;
173 Int pitch;
174
175 if(!state.quadLayoutDepthBuffer)
176 {
177 buffer = zBuffer + 4 * x0;
178 pitch = *Pointer<Int>(r.data + OFFSET(DrawData,depthPitchB));
179 }
180 else
181 {
182 buffer = zBuffer + 8 * x0;
183 }
184
185 For(Int x = x0, x < x1, x += 2)
186 {
187 Float4 z = interpolate(xxxx, r.Dz[0], z, r.primitive + OFFSET(Primitive,z), false, false);
188
189 Float4 zValue;
190
191 if(!state.quadLayoutDepthBuffer)
192 {
193 // FIXME: Properly optimizes?
194 zValue.xy = *Pointer<Float4>(buffer);
195 zValue.zw = *Pointer<Float4>(buffer + pitch - 8);
196 }
197 else
198 {
199 zValue = *Pointer<Float4>(buffer, 16);
200 }
201
202 Int4 zTest;
203
204 if(complementaryDepthBuffer)
205 {
206 zTest = CmpLE(zValue, z);
207 }
208 else
209 {
210 zTest = CmpNLT(zValue, z);
211 }
212
213 Int zMask = SignMask(zTest);
214
215 If(zMask == 0)
216 {
217 x0 += 2;
218 }
219 Else
220 {
221 x = x1;
222 }
223
224 xxxx += Float4(2);
225
226 if(!state.quadLayoutDepthBuffer)
227 {
228 buffer += 8;
229 }
230 else
231 {
232 buffer += 16;
233 }
234 }
235 }
236 }
237
238 If(x0 < x1)
239 {
John Bauman19bac1e2014-05-06 15:23:49 -0400240 if(interpolateW())
John Bauman89401822014-05-06 15:04:28 -0400241 {
242 r.Dw = *Pointer<Float4>(r.primitive + OFFSET(Primitive,w.C), 16) + yyyy * *Pointer<Float4>(r.primitive + OFFSET(Primitive,w.B), 16);
243 }
244
Nicolas Capens66be2452015-01-27 14:58:57 -0500245 for(int interpolant = 0; interpolant < 10; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400246 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500247 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400248 {
249 if(state.interpolant[interpolant].component & (1 << component))
250 {
251 r.Dv[interpolant][component] = *Pointer<Float4>(r.primitive + OFFSET(Primitive,V[interpolant][component].C), 16);
252
253 if(!(state.interpolant[interpolant].flat & (1 << component)))
254 {
255 r.Dv[interpolant][component] += yyyy * *Pointer<Float4>(r.primitive + OFFSET(Primitive,V[interpolant][component].B), 16);
256 }
257 }
258 }
259 }
260
Nicolas Capens66be2452015-01-27 14:58:57 -0500261 if(state.fog.component)
262 {
263 r.Df = *Pointer<Float4>(r.primitive + OFFSET(Primitive,f.C), 16);
264
265 if(!state.fog.flat)
266 {
267 r.Df += yyyy * *Pointer<Float4>(r.primitive + OFFSET(Primitive,f.B), 16);
268 }
269 }
270
John Bauman89401822014-05-06 15:04:28 -0400271 Short4 xLeft[4];
272 Short4 xRight[4];
273
274 for(unsigned int q = 0; q < state.multiSample; q++)
275 {
276 xLeft[q] = *Pointer<Short4>(r.primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline) + y * sizeof(Primitive::Span));
277 xRight[q] = xLeft[q];
278
279 xLeft[q] = Swizzle(xLeft[q], 0xA0) - Short4(1, 2, 1, 2);
280 xRight[q] = Swizzle(xRight[q], 0xF5) - Short4(0, 1, 0, 1);
281 }
282
283 For(Int x = x0, x < x1, x += 2)
284 {
285 Short4 xxxx = Short4(x);
286 Int cMask[4];
287
288 for(unsigned int q = 0; q < state.multiSample; q++)
289 {
290 Short4 mask = CmpGT(xxxx, xLeft[q]) & CmpGT(xRight[q], xxxx);
291 cMask[q] = SignMask(Pack(mask, mask)) & 0x0000000F;
292 }
293
294 quad(r, cBuffer, zBuffer, sBuffer, cMask, x, y);
295 }
296 }
297
298 for(int index = 0; index < 4; index++)
299 {
300 if(state.colorWriteActive(index))
301 {
John Bauman19bac1e2014-05-06 15:23:49 -0400302 cBuffer[index] += *Pointer<Int>(r.data + OFFSET(DrawData,colorPitchB[index])) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400303 }
304 }
305
306 if(state.depthTestActive)
307 {
John Bauman19bac1e2014-05-06 15:23:49 -0400308 zBuffer += *Pointer<Int>(r.data + OFFSET(DrawData,depthPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400309 }
310
311 if(state.stencilActive)
312 {
John Bauman19bac1e2014-05-06 15:23:49 -0400313 sBuffer += *Pointer<Int>(r.data + OFFSET(DrawData,stencilPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
John Bauman89401822014-05-06 15:04:28 -0400314 }
315
316 y += 2 * clusterCount;
317 }
318 Until(y >= yMax)
319 }
320}