blob: 7ecfa3d6baa4f5b6a53b6b124bdc154a502212c5 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "SetupRoutine.hpp"
16
17#include "Constants.hpp"
18#include "Renderer/Primitive.hpp"
19#include "Renderer/Polygon.hpp"
20#include "Renderer/Renderer.hpp"
John Bauman19bac1e2014-05-06 15:23:49 -040021#include "Reactor/Reactor.hpp"
John Bauman89401822014-05-06 15:04:28 -040022
23namespace sw
24{
25 extern bool complementaryDepthBuffer;
26 extern TranscendentalPrecision logPrecision;
Nicolas Capens3aa46cb2015-06-03 16:33:02 -040027 extern bool leadingVertexFirst;
John Bauman89401822014-05-06 15:04:28 -040028
29 SetupRoutine::SetupRoutine(const SetupProcessor::State &state) : state(state)
30 {
31 routine = 0;
32 }
33
34 SetupRoutine::~SetupRoutine()
35 {
36 }
37
38 void SetupRoutine::generate()
39 {
Nicolas Capens2ab859f2015-02-05 12:36:46 -050040 Function<Bool(Pointer<Byte>, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>)> function;
John Bauman89401822014-05-06 15:04:28 -040041 {
Nicolas Capens81f18302016-01-14 09:32:35 -050042 Pointer<Byte> primitive(function.Arg<0>());
43 Pointer<Byte> tri(function.Arg<1>());
44 Pointer<Byte> polygon(function.Arg<2>());
45 Pointer<Byte> data(function.Arg<3>());
John Bauman89401822014-05-06 15:04:28 -040046
John Bauman66b8ab22014-05-06 15:57:45 -040047 Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants));
John Bauman89401822014-05-06 15:04:28 -040048
49 const bool point = state.isDrawPoint;
50 const bool sprite = state.pointSprite;
51 const bool line = state.isDrawLine;
52 const bool triangle = state.isDrawSolidTriangle || sprite;
53 const bool solidTriangle = state.isDrawSolidTriangle;
54
55 const int V0 = OFFSET(Triangle,v0);
56 const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0);
57 const int V2 = triangle ? OFFSET(Triangle,v2) : (line ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0));
58
59 int pos = state.positionRegister;
60
61 Pointer<Byte> v0 = tri + V0;
62 Pointer<Byte> v1 = tri + V1;
63 Pointer<Byte> v2 = tri + V2;
64
65 Array<Int> X(16);
66 Array<Int> Y(16);
67
68 X[0] = *Pointer<Int>(v0 + OFFSET(Vertex,X));
69 X[1] = *Pointer<Int>(v1 + OFFSET(Vertex,X));
70 X[2] = *Pointer<Int>(v2 + OFFSET(Vertex,X));
71
72 Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
73 Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
74 Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
75
76 Int d = 1; // Winding direction
77
78 // Culling
79 if(solidTriangle)
80 {
81 Float x0 = Float(X[0]);
82 Float x1 = Float(X[1]);
83 Float x2 = Float(X[2]);
84
85 Float y0 = Float(Y[0]);
86 Float y1 = Float(Y[1]);
87 Float y2 = Float(Y[2]);
88
89 Float A = (y2 - y0) * x1 + (y1 - y2) * x0 + (y0 - y1) * x2; // Area
90
John Bauman66b8ab22014-05-06 15:57:45 -040091 If(A == 0.0f)
John Bauman89401822014-05-06 15:04:28 -040092 {
93 Return(false);
94 }
95
Nicolas Capensc68df5f2014-05-07 01:14:21 -040096 Int w0w1w2 = *Pointer<Int>(v0 + pos * 16 + 12) ^
97 *Pointer<Int>(v1 + pos * 16 + 12) ^
98 *Pointer<Int>(v2 + pos * 16 + 12);
John Bauman89401822014-05-06 15:04:28 -040099
Nicolas Capensc68df5f2014-05-07 01:14:21 -0400100 A = IfThenElse(w0w1w2 < 0, -A, A);
John Bauman89401822014-05-06 15:04:28 -0400101
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400102 if(state.cullMode == CULL_CLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -0400103 {
John Bauman66b8ab22014-05-06 15:57:45 -0400104 If(A >= 0.0f) Return(false);
John Bauman89401822014-05-06 15:04:28 -0400105 }
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400106 else if(state.cullMode == CULL_COUNTERCLOCKWISE)
John Bauman89401822014-05-06 15:04:28 -0400107 {
John Bauman66b8ab22014-05-06 15:57:45 -0400108 If(A <= 0.0f) Return(false);
John Bauman89401822014-05-06 15:04:28 -0400109 }
110
John Bauman66b8ab22014-05-06 15:57:45 -0400111 d = IfThenElse(A < 0.0f, d, Int(0));
John Bauman89401822014-05-06 15:04:28 -0400112
113 if(state.twoSidedStencil)
114 {
John Bauman66b8ab22014-05-06 15:57:45 -0400115 If(A > 0.0f)
John Bauman19bac1e2014-05-06 15:23:49 -0400116 {
Nicolas Capens16b5f152016-10-13 13:39:01 -0400117 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
118 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
John Bauman19bac1e2014-05-06 15:23:49 -0400119 }
120 Else
121 {
Nicolas Capens16b5f152016-10-13 13:39:01 -0400122 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
123 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
John Bauman19bac1e2014-05-06 15:23:49 -0400124 }
John Bauman89401822014-05-06 15:04:28 -0400125 }
126
127 if(state.vFace)
128 {
John Bauman66b8ab22014-05-06 15:57:45 -0400129 *Pointer<Float>(primitive + OFFSET(Primitive,area)) = 0.5f * A;
John Bauman89401822014-05-06 15:04:28 -0400130 }
131 }
132 else
133 {
134 if(state.twoSidedStencil)
135 {
Nicolas Capens16b5f152016-10-13 13:39:01 -0400136 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
137 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
John Bauman89401822014-05-06 15:04:28 -0400138 }
139 }
140
141 Int n = *Pointer<Int>(polygon + OFFSET(Polygon,n));
142 Int m = *Pointer<Int>(polygon + OFFSET(Polygon,i));
143
144 If(m != 0 || Bool(!solidTriangle)) // Clipped triangle; reproject
145 {
146 Pointer<Byte> V = polygon + OFFSET(Polygon,P) + m * sizeof(void*) * 16;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400147
John Bauman89401822014-05-06 15:04:28 -0400148 Int i = 0;
149
150 Do
151 {
John Bauman66b8ab22014-05-06 15:57:45 -0400152 Pointer<Float4> p = *Pointer<Pointer<Float4> >(V + i * sizeof(void*));
John Bauman89401822014-05-06 15:04:28 -0400153 Float4 v = *Pointer<Float4>(p, 16);
154
155 Float w = v.w;
John Bauman66b8ab22014-05-06 15:57:45 -0400156 Float rhw = IfThenElse(w != 0.0f, 1.0f / w, Float(1.0f));
John Bauman89401822014-05-06 15:04:28 -0400157
John Bauman19bac1e2014-05-06 15:23:49 -0400158 X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,X0x16)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData,Wx16)));
159 Y[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,Y0x16)) + v.y * rhw * *Pointer<Float>(data + OFFSET(DrawData,Hx16)));
John Bauman89401822014-05-06 15:04:28 -0400160
161 i++;
162 }
163 Until(i >= n)
164 }
165
166 // Vertical range
167 Int yMin = Y[0];
168 Int yMax = Y[0];
Nicolas Capensec0936c2016-05-18 12:32:02 -0400169
John Bauman89401822014-05-06 15:04:28 -0400170 Int i = 1;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400171
John Bauman89401822014-05-06 15:04:28 -0400172 Do
173 {
John Bauman19bac1e2014-05-06 15:23:49 -0400174 yMin = Min(Y[i], yMin);
175 yMax = Max(Y[i], yMax);
John Bauman89401822014-05-06 15:04:28 -0400176
177 i++;
178 }
179 Until(i >= n)
180
181 if(state.multiSample > 1)
182 {
183 yMin = (yMin + 0x0A) >> 4;
184 yMax = (yMax + 0x14) >> 4;
185 }
186 else
187 {
188 yMin = (yMin + 0x0F) >> 4;
189 yMax = (yMax + 0x0F) >> 4;
190 }
191
Antonio Maiorano970e4f02019-04-26 10:12:49 -0400192 yMin = Max(yMin, *Pointer<Int>(data + OFFSET(DrawData,scissorY0)));
193 yMax = Min(yMax, *Pointer<Int>(data + OFFSET(DrawData,scissorY1)));
194
195 // If yMin and yMax are initially negative, the scissor clamping above will typically result
196 // in yMin == 0 and yMax unchanged. We bail as we don't need to rasterize this primitive, and
197 // code below assumes yMin < yMax.
198 If(yMin >= yMax)
John Bauman89401822014-05-06 15:04:28 -0400199 {
200 Return(false);
201 }
John Bauman19bac1e2014-05-06 15:23:49 -0400202
John Bauman89401822014-05-06 15:04:28 -0400203 For(Int q = 0, q < state.multiSample, q++)
204 {
205 Array<Int> Xq(16);
206 Array<Int> Yq(16);
207
208 Int i = 0;
209
210 Do
211 {
212 Xq[i] = X[i];
213 Yq[i] = Y[i];
214
215 if(state.multiSample > 1)
216 {
217 Xq[i] = Xq[i] + *Pointer<Int>(constants + OFFSET(Constants,Xf) + q * sizeof(int));
218 Yq[i] = Yq[i] + *Pointer<Int>(constants + OFFSET(Constants,Yf) + q * sizeof(int));
219 }
220
221 i++;
222 }
223 Until(i >= n)
224
225 Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->left)) + q * sizeof(Primitive);
226 Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->right)) + q * sizeof(Primitive);
227
228 if(state.multiSample > 1)
229 {
Alexis Hetu7a8ed2e2017-11-02 10:59:59 -0400230 Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0));
231 Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1));
232 Short x = Short(Clamp((X[0] + 0xF) >> 4, xMin, xMax));
John Bauman89401822014-05-06 15:04:28 -0400233
234 For(Int y = yMin - 1, y < yMax + 1, y++)
235 {
236 *Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x;
237 *Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x;
238 }
239 }
240
241 Xq[n] = Xq[0];
242 Yq[n] = Yq[0];
243
244 // Rasterize
245 {
246 Int i = 0;
247
248 Do
249 {
John Bauman66b8ab22014-05-06 15:57:45 -0400250 edge(primitive, data, Xq[i + 1 - d], Yq[i + 1 - d], Xq[i + d], Yq[i + d], q);
John Bauman89401822014-05-06 15:04:28 -0400251
252 i++;
253 }
254 Until(i >= n)
255 }
256
257 if(state.multiSample == 1)
258 {
Alexis Hetu7208e932016-06-02 11:19:24 -0400259 For(, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++)
John Bauman89401822014-05-06 15:04:28 -0400260 {
261 // Increments yMin
262 }
263
Alexis Hetu7208e932016-06-02 11:19:24 -0400264 For(, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--)
John Bauman89401822014-05-06 15:04:28 -0400265 {
266 // Decrements yMax
267 }
268
269 If(yMin == yMax)
270 {
271 Return(false);
272 }
273
274 *Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
275 *Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
276 *Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
277 *Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
278 }
279 }
280
281 *Pointer<Int>(primitive + OFFSET(Primitive,yMin)) = yMin;
282 *Pointer<Int>(primitive + OFFSET(Primitive,yMax)) = yMax;
283
284 // Sort by minimum y
285 if(solidTriangle && logPrecision >= WHQL)
286 {
287 Float y0 = *Pointer<Float>(v0 + pos * 16 + 4);
288 Float y1 = *Pointer<Float>(v1 + pos * 16 + 4);
289 Float y2 = *Pointer<Float>(v2 + pos * 16 + 4);
290
291 Float yMin = Min(Min(y0, y1), y2);
292
293 conditionalRotate1(yMin == y1, v0, v1, v2);
294 conditionalRotate2(yMin == y2, v0, v1, v2);
295 }
296
297 // Sort by maximum w
298 if(solidTriangle)
299 {
300 Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
301 Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
302 Float w2 = *Pointer<Float>(v2 + pos * 16 + 12);
303
304 Float wMax = Max(Max(w0, w1), w2);
305
306 conditionalRotate1(wMax == w1, v0, v1, v2);
307 conditionalRotate2(wMax == w2, v0, v1, v2);
308 }
309
Nicolas Capens00bfa182016-05-20 21:30:54 -0700310 Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
311 Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
312 Float w2 = *Pointer<Float>(v2 + pos * 16 + 12);
John Bauman89401822014-05-06 15:04:28 -0400313
314 Float4 w012;
315
316 w012.x = w0;
317 w012.y = w1;
318 w012.z = w2;
319 w012.w = 1;
320
321 Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex,W));
322
323 Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex,X));
324 Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex,X));
325 Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex,X));
326
327 Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
328 Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
329 Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
330
331 if(line)
332 {
333 X2 = X1 + Y1 - Y0;
334 Y2 = Y1 + X0 - X1;
335 }
336
John Bauman66b8ab22014-05-06 15:57:45 -0400337 Float dx = Float(X0) * (1.0f / 16.0f);
338 Float dy = Float(Y0) * (1.0f / 16.0f);
John Bauman89401822014-05-06 15:04:28 -0400339
340 X1 -= X0;
341 Y1 -= Y0;
342
343 X2 -= X0;
344 Y2 -= Y0;
345
John Bauman66b8ab22014-05-06 15:57:45 -0400346 Float x1 = w1 * (1.0f / 16.0f) * Float(X1);
347 Float y1 = w1 * (1.0f / 16.0f) * Float(Y1);
John Bauman89401822014-05-06 15:04:28 -0400348
John Bauman66b8ab22014-05-06 15:57:45 -0400349 Float x2 = w2 * (1.0f / 16.0f) * Float(X2);
350 Float y2 = w2 * (1.0f / 16.0f) * Float(Y2);
John Bauman89401822014-05-06 15:04:28 -0400351
352 Float a = x1 * y2 - x2 * y1;
353
354 Float4 xQuad = Float4(0, 1, 0, 1) - Float4(dx);
355 Float4 yQuad = Float4(0, 0, 1, 1) - Float4(dy);
356
357 *Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16) = xQuad;
358 *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16) = yQuad;
359
360 Float4 M[3];
361
362 M[0] = Float4(0, 0, 0, 0);
363 M[1] = Float4(0, 0, 0, 0);
364 M[2] = Float4(0, 0, 0, 0);
365
366 M[0].z = rhw0;
367
John Bauman66b8ab22014-05-06 15:57:45 -0400368 If(a != 0.0f)
John Bauman89401822014-05-06 15:04:28 -0400369 {
John Bauman66b8ab22014-05-06 15:57:45 -0400370 Float A = 1.0f / a;
John Bauman89401822014-05-06 15:04:28 -0400371 Float D = A * rhw0;
372
373 M[0].x = (y1 * w2 - y2 * w1) * D;
374 M[0].y = (x2 * w1 - x1 * w2) * D;
375 // M[0].z = rhw0;
376 // M[0].w = 0;
377
378 M[1].x = y2 * A;
379 M[1].y = -x2 * A;
380 // M[1].z = 0;
381 // M[1].w = 0;
382
383 M[2].x = -y1 * A;
384 M[2].y = x1 * A;
385 // M[2].z = 0;
386 // M[2].w = 0;
387 }
388
John Bauman19bac1e2014-05-06 15:23:49 -0400389 if(state.interpolateW)
John Bauman89401822014-05-06 15:04:28 -0400390 {
391 Float4 ABC = M[0] + M[1] + M[2];
392
393 Float4 A = ABC.x;
394 Float4 B = ABC.y;
395 Float4 C = ABC.z;
396
397 *Pointer<Float4>(primitive + OFFSET(Primitive,w.A), 16) = A;
398 *Pointer<Float4>(primitive + OFFSET(Primitive,w.B), 16) = B;
399 *Pointer<Float4>(primitive + OFFSET(Primitive,w.C), 16) = C;
400 }
401
John Bauman19bac1e2014-05-06 15:23:49 -0400402 if(state.interpolateZ)
John Bauman89401822014-05-06 15:04:28 -0400403 {
404 Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex,Z));
405 Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex,Z));
406 Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex,Z));
407
408 z1 -= z0;
409 z2 -= z0;
410
411 Float4 A;
412 Float4 B;
413 Float4 C;
414
415 if(!point)
416 {
John Bauman66b8ab22014-05-06 15:57:45 -0400417 Float x1 = Float(X1) * (1.0f / 16.0f);
418 Float y1 = Float(Y1) * (1.0f / 16.0f);
419 Float x2 = Float(X2) * (1.0f / 16.0f);
420 Float y2 = Float(Y2) * (1.0f / 16.0f);
John Bauman89401822014-05-06 15:04:28 -0400421
422 Float D = *Pointer<Float>(data + OFFSET(DrawData,depthRange)) / (x1 * y2 - x2 * y1);
423
424 Float a = (y2 * z1 - y1 * z2) * D;
425 Float b = (x1 * z2 - x2 * z1) * D;
426
427 A = Float4(a);
428 B = Float4(b);
429 }
430 else
431 {
432 A = Float4(0, 0, 0, 0);
433 B = Float4(0, 0, 0, 0);
434 }
435
436 *Pointer<Float4>(primitive + OFFSET(Primitive,z.A), 16) = A;
437 *Pointer<Float4>(primitive + OFFSET(Primitive,z.B), 16) = B;
438
439 Float c = z0;
440
441 if(state.isDrawTriangle && state.slopeDepthBias)
442 {
443 Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x)));
444 bias *= *Pointer<Float>(data + OFFSET(DrawData,slopeDepthBias));
445
446 if(complementaryDepthBuffer)
447 {
448 bias = -bias;
449 }
450
451 c += bias;
452 }
453
454 C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData,depthRange)) + *Pointer<Float>(data + OFFSET(DrawData,depthNear)));
455
456 *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) = C;
457 }
458
Nicolas Capens3b4c93f2016-05-18 12:51:37 -0400459 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400460 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500461 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400462 {
463 int attribute = state.gradient[interpolant][component].attribute;
464 bool flat = state.gradient[interpolant][component].flat;
465 bool wrap = state.gradient[interpolant][component].wrap;
466
Nicolas Capens66be2452015-01-27 14:58:57 -0500467 if(attribute != Unused)
John Bauman89401822014-05-06 15:04:28 -0400468 {
469 setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,v[attribute][component]), OFFSET(Primitive,V[interpolant][component]), flat, sprite, state.perspective, wrap, component);
470 }
471 }
472 }
473
Nicolas Capens66be2452015-01-27 14:58:57 -0500474 if(state.fog.attribute == Fog)
475 {
476 setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,f), OFFSET(Primitive,f), state.fog.flat, false, state.perspective, false, 0);
477 }
478
John Bauman89401822014-05-06 15:04:28 -0400479 Return(true);
480 }
481
Chris Forbes878d4b02019-01-21 10:48:35 -0800482 routine = function("SetupRoutine");
John Bauman89401822014-05-06 15:04:28 -0400483 }
484
485 void SetupRoutine::setupGradient(Pointer<Byte> &primitive, Pointer<Byte> &triangle, Float4 &w012, Float4 (&m)[3], Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2, int attribute, int planeEquation, bool flat, bool sprite, bool perspective, bool wrap, int component)
486 {
487 Float4 i;
488
489 if(!flat)
490 {
491 if(!sprite)
492 {
493 i.x = *Pointer<Float>(v0 + attribute);
494 i.y = *Pointer<Float>(v1 + attribute);
495 i.z = *Pointer<Float>(v2 + attribute);
496 i.w = 0;
497 }
498 else
499 {
John Bauman66b8ab22014-05-06 15:57:45 -0400500 if(component == 0) i.x = 0.5f;
501 if(component == 1) i.x = 0.5f;
502 if(component == 2) i.x = 0.0f;
503 if(component == 3) i.x = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400504
John Bauman66b8ab22014-05-06 15:57:45 -0400505 if(component == 0) i.y = 1.0f;
506 if(component == 1) i.y = 0.5f;
507 if(component == 2) i.y = 0.0f;
508 if(component == 3) i.y = 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400509
John Bauman66b8ab22014-05-06 15:57:45 -0400510 if(component == 0) i.z = 0.5f;
511 if(component == 1) i.z = 1.0f;
512 if(component == 2) i.z = 0.0f;
513 if(component == 3) i.z = 1.0f;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400514
John Bauman89401822014-05-06 15:04:28 -0400515 i.w = 0;
516 }
517
518 if(wrap)
519 {
520 Float m;
521
522 m = *Pointer<Float>(v0 + attribute);
523 m = Max(m, *Pointer<Float>(v1 + attribute));
524 m = Max(m, *Pointer<Float>(v2 + attribute));
John Bauman66b8ab22014-05-06 15:57:45 -0400525 m -= 0.5f;
John Bauman89401822014-05-06 15:04:28 -0400526
527 // FIXME: Vectorize
John Bauman66b8ab22014-05-06 15:57:45 -0400528 If(Float(i.x) < m) i.x = i.x + 1.0f;
529 If(Float(i.y) < m) i.y = i.y + 1.0f;
530 If(Float(i.z) < m) i.z = i.z + 1.0f;
John Bauman89401822014-05-06 15:04:28 -0400531 }
532
533 if(!perspective)
534 {
535 i *= w012;
536 }
537
John Bauman19bac1e2014-05-06 15:23:49 -0400538 Float4 A = i.xxxx * m[0];
539 Float4 B = i.yyyy * m[1];
540 Float4 C = i.zzzz * m[2];
John Bauman89401822014-05-06 15:04:28 -0400541
542 C = A + B + C;
543
544 A = C.xxxx;
545 B = C.yyyy;
546 C = C.zzzz;
547
548 *Pointer<Float4>(primitive + planeEquation + 0, 16) = A;
549 *Pointer<Float4>(primitive + planeEquation + 16, 16) = B;
550 *Pointer<Float4>(primitive + planeEquation + 32, 16) = C;
551 }
552 else
553 {
Nicolas Capens3aa46cb2015-06-03 16:33:02 -0400554 int leadingVertex = leadingVertexFirst ? OFFSET(Triangle,v0) : OFFSET(Triangle,v2);
555 Float C = *Pointer<Float>(triangle + leadingVertex + attribute);
John Bauman89401822014-05-06 15:04:28 -0400556
557 *Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0);
558 *Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0);
559 *Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C);
560 }
561 }
562
Nicolas Capens96d4e092016-11-18 14:22:38 -0500563 void SetupRoutine::edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &Xa, const Int &Ya, const Int &Xb, const Int &Yb, Int &q)
John Bauman89401822014-05-06 15:04:28 -0400564 {
Nicolas Capens96d4e092016-11-18 14:22:38 -0500565 If(Ya != Yb)
John Bauman89401822014-05-06 15:04:28 -0400566 {
Nicolas Capens96d4e092016-11-18 14:22:38 -0500567 Bool swap = Yb < Ya;
John Bauman89401822014-05-06 15:04:28 -0400568
Nicolas Capens96d4e092016-11-18 14:22:38 -0500569 Int X1 = IfThenElse(swap, Xb, Xa);
570 Int X2 = IfThenElse(swap, Xa, Xb);
571 Int Y1 = IfThenElse(swap, Yb, Ya);
572 Int Y2 = IfThenElse(swap, Ya, Yb);
John Bauman89401822014-05-06 15:04:28 -0400573
John Bauman19bac1e2014-05-06 15:23:49 -0400574 Int y1 = Max((Y1 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY0)));
575 Int y2 = Min((Y2 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY1)));
John Bauman89401822014-05-06 15:04:28 -0400576
John Bauman19bac1e2014-05-06 15:23:49 -0400577 If(y1 < y2)
John Bauman89401822014-05-06 15:04:28 -0400578 {
Nicolas Capens904f6f92017-01-05 10:11:01 -0500579 Int xMin = *Pointer<Int>(data + OFFSET(DrawData,scissorX0));
580 Int xMax = *Pointer<Int>(data + OFFSET(DrawData,scissorX1));
581
582 Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left);
583 Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right);
584 Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge);
585
John Bauman89401822014-05-06 15:04:28 -0400586 // Deltas
587 Int DX12 = X2 - X1;
588 Int DY12 = Y2 - Y1;
589
590 Int FDX12 = DX12 << 4;
591 Int FDY12 = DY12 << 4;
592
Nicolas Capensbd85ab22017-01-05 13:18:39 -0500593 Int X = DX12 * ((y1 << 4) - Y1) + (X1 & 0x0000000F) * DY12;
594 Int x = (X1 >> 4) + X / FDY12; // Edge
595 Int d = X % FDY12; // Error-term
596 Int ceil = -d >> 31; // Ceiling division: remainder <= 0
John Bauman89401822014-05-06 15:04:28 -0400597 x -= ceil;
598 d -= ceil & FDY12;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400599
John Bauman89401822014-05-06 15:04:28 -0400600 Int Q = FDX12 / FDY12; // Edge-step
601 Int R = FDX12 % FDY12; // Error-step
602 Int floor = R >> 31; // Flooring division: remainder >= 0
603 Q += floor;
604 R += floor & FDY12;
605
606 Int D = FDY12; // Error-overflow
607 Int y = y1;
608
609 Do
610 {
John Bauman19bac1e2014-05-06 15:23:49 -0400611 *Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(Clamp(x, xMin, xMax));
John Bauman89401822014-05-06 15:04:28 -0400612
613 x += Q;
614 d += R;
615
616 Int overflow = -d >> 31;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400617
John Bauman89401822014-05-06 15:04:28 -0400618 d -= D & overflow;
619 x -= overflow;
620
621 y++;
622 }
623 Until(y >= y2)
624 }
625 }
626 }
627
628 void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
629 {
630 #if 0 // Rely on LLVM optimization
631 If(condition)
632 {
633 Pointer<Byte> vX;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400634
John Bauman89401822014-05-06 15:04:28 -0400635 vX = v0;
636 v0 = v1;
637 v1 = v2;
638 v2 = vX;
639 }
640 #else
641 Pointer<Byte> vX = v0;
642 v0 = IfThenElse(condition, v1, v0);
643 v1 = IfThenElse(condition, v2, v1);
644 v2 = IfThenElse(condition, vX, v2);
645 #endif
646 }
647
648 void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
649 {
650 #if 0 // Rely on LLVM optimization
651 If(condition)
652 {
653 Pointer<Byte> vX;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400654
John Bauman89401822014-05-06 15:04:28 -0400655 vX = v2;
656 v2 = v1;
657 v1 = v0;
658 v0 = vX;
659 }
660 #else
661 Pointer<Byte> vX = v2;
662 v2 = IfThenElse(condition, v1, v2);
663 v1 = IfThenElse(condition, v0, v1);
664 v0 = IfThenElse(condition, vX, v0);
665 #endif
666 }
667
668 Routine *SetupRoutine::getRoutine()
669 {
670 return routine;
671 }
672}