blob: a34c489f8d1b44b14cfb9fdbe3dbbf41c22fe1fb [file] [log] [blame]
Nicolas Capens68a82382018-10-02 13:16:55 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// 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
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// 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.
14
15#include "SetupRoutine.hpp"
Ben Claytonbc1c0672019-12-17 20:37:37 +000016#include <Device/Vertex.hpp>
Nicolas Capens68a82382018-10-02 13:16:55 -040017
18#include "Constants.hpp"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050019#include "Device/Polygon.hpp"
Ben Claytonbc1c0672019-12-17 20:37:37 +000020#include "Device/Primitive.hpp"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050021#include "Device/Renderer.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040022#include "Reactor/Reactor.hpp"
23
Nicolas Capens157ba262019-12-10 17:49:14 -050024namespace sw {
25
Ben Claytonbc1c0672019-12-17 20:37:37 +000026SetupRoutine::SetupRoutine(const SetupProcessor::State &state)
27 : state(state)
Nicolas Capens68a82382018-10-02 13:16:55 -040028{
Nicolas Capens157ba262019-12-10 17:49:14 -050029}
Nicolas Capens68a82382018-10-02 13:16:55 -040030
Nicolas Capens157ba262019-12-10 17:49:14 -050031SetupRoutine::~SetupRoutine()
32{
33}
Nicolas Capens68a82382018-10-02 13:16:55 -040034
Nicolas Capens157ba262019-12-10 17:49:14 -050035void SetupRoutine::generate()
36{
37 SetupFunction function;
Nicolas Capens68a82382018-10-02 13:16:55 -040038 {
Nicolas Capens157ba262019-12-10 17:49:14 -050039 Pointer<Byte> primitive(function.Arg<0>());
40 Pointer<Byte> tri(function.Arg<1>());
41 Pointer<Byte> polygon(function.Arg<2>());
42 Pointer<Byte> data(function.Arg<3>());
43
Ben Claytonbc1c0672019-12-17 20:37:37 +000044 Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData, constants));
Nicolas Capens157ba262019-12-10 17:49:14 -050045
46 const bool point = state.isDrawPoint;
47 const bool line = state.isDrawLine;
48 const bool triangle = state.isDrawTriangle;
49
Ben Claytonbc1c0672019-12-17 20:37:37 +000050 const int V0 = OFFSET(Triangle, v0);
51 const int V1 = (triangle || line) ? OFFSET(Triangle, v1) : OFFSET(Triangle, v0);
52 const int V2 = triangle ? OFFSET(Triangle, v2) : (line ? OFFSET(Triangle, v1) : OFFSET(Triangle, v0));
Nicolas Capens157ba262019-12-10 17:49:14 -050053
54 Pointer<Byte> v0 = tri + V0;
55 Pointer<Byte> v1 = tri + V1;
56 Pointer<Byte> v2 = tri + V2;
57
58 Array<Int> X(16);
59 Array<Int> Y(16);
60
Ben Claytonbc1c0672019-12-17 20:37:37 +000061 X[0] = *Pointer<Int>(v0 + OFFSET(Vertex, projected.x));
62 X[1] = *Pointer<Int>(v1 + OFFSET(Vertex, projected.x));
63 X[2] = *Pointer<Int>(v2 + OFFSET(Vertex, projected.x));
Nicolas Capens157ba262019-12-10 17:49:14 -050064
Ben Claytonbc1c0672019-12-17 20:37:37 +000065 Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex, projected.y));
66 Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex, projected.y));
67 Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex, projected.y));
Nicolas Capens157ba262019-12-10 17:49:14 -050068
Ben Claytonbc1c0672019-12-17 20:37:37 +000069 Int d = 1; // Winding direction
Nicolas Capens157ba262019-12-10 17:49:14 -050070
71 // Culling
72 if(triangle)
Nicolas Capens68a82382018-10-02 13:16:55 -040073 {
Nicolas Capens157ba262019-12-10 17:49:14 -050074 Float x0 = Float(X[0]);
75 Float x1 = Float(X[1]);
76 Float x2 = Float(X[2]);
Nicolas Capens68a82382018-10-02 13:16:55 -040077
Nicolas Capens157ba262019-12-10 17:49:14 -050078 Float y0 = Float(Y[0]);
79 Float y1 = Float(Y[1]);
80 Float y2 = Float(Y[2]);
Nicolas Capens68a82382018-10-02 13:16:55 -040081
Ben Claytonbc1c0672019-12-17 20:37:37 +000082 Float A = (y0 - y2) * x1 + (y2 - y1) * x0 + (y1 - y0) * x2; // Area
Nicolas Capens68a82382018-10-02 13:16:55 -040083
Nicolas Capens157ba262019-12-10 17:49:14 -050084 If(A == 0.0f)
Nicolas Capens68a82382018-10-02 13:16:55 -040085 {
Nicolas Capens157ba262019-12-10 17:49:14 -050086 Return(0);
Chris Forbes25be5bb2019-04-15 15:20:27 -070087 }
Nicolas Capens157ba262019-12-10 17:49:14 -050088
89 Int w0w1w2 = *Pointer<Int>(v0 + OFFSET(Vertex, w)) ^
90 *Pointer<Int>(v1 + OFFSET(Vertex, w)) ^
91 *Pointer<Int>(v2 + OFFSET(Vertex, w));
92
93 A = IfThenElse(w0w1w2 < 0, -A, A);
94
95 Bool frontFacing = (state.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE) ? A > 0.0f : A < 0.0f;
96
97 if(state.cullMode & VK_CULL_MODE_FRONT_BIT)
98 {
99 If(frontFacing) Return(0);
100 }
101 if(state.cullMode & VK_CULL_MODE_BACK_BIT)
102 {
103 If(!frontFacing) Return(0);
104 }
105
106 d = IfThenElse(A > 0.0f, d, Int(0));
107
108 If(frontFacing)
Chris Forbes25be5bb2019-04-15 15:20:27 -0700109 {
Ben Claytonbc1c0672019-12-17 20:37:37 +0000110 *Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
111 *Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
Nicolas Capens68a82382018-10-02 13:16:55 -0400112 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500113 Else
Nicolas Capens68a82382018-10-02 13:16:55 -0400114 {
Ben Claytonbc1c0672019-12-17 20:37:37 +0000115 *Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
116 *Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
Nicolas Capens68a82382018-10-02 13:16:55 -0400117 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500118 }
119 else
120 {
Ben Claytonbc1c0672019-12-17 20:37:37 +0000121 *Pointer<Byte8>(primitive + OFFSET(Primitive, clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
122 *Pointer<Byte8>(primitive + OFFSET(Primitive, invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
Nicolas Capens157ba262019-12-10 17:49:14 -0500123 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400124
Ben Claytonbc1c0672019-12-17 20:37:37 +0000125 Int n = *Pointer<Int>(polygon + OFFSET(Polygon, n));
126 Int m = *Pointer<Int>(polygon + OFFSET(Polygon, i));
Nicolas Capens68a82382018-10-02 13:16:55 -0400127
Ben Claytonbc1c0672019-12-17 20:37:37 +0000128 If(m != 0 || Bool(!triangle)) // Clipped triangle; reproject
Nicolas Capens157ba262019-12-10 17:49:14 -0500129 {
Ben Claytonbc1c0672019-12-17 20:37:37 +0000130 Pointer<Byte> V = polygon + OFFSET(Polygon, P) + m * sizeof(void *) * 16;
Nicolas Capens157ba262019-12-10 17:49:14 -0500131
132 Int i = 0;
Nicolas Capens68a82382018-10-02 13:16:55 -0400133
134 Do
135 {
Ben Claytonbc1c0672019-12-17 20:37:37 +0000136 Pointer<Float4> p = *Pointer<Pointer<Float4> >(V + i * sizeof(void *));
Nicolas Capens157ba262019-12-10 17:49:14 -0500137 Float4 v = *Pointer<Float4>(p, 16);
138
139 Float w = v.w;
140 Float rhw = IfThenElse(w != 0.0f, 1.0f / w, Float(1.0f));
141
Ben Claytonbc1c0672019-12-17 20:37:37 +0000142 X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData, X0xF)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData, WxF)));
143 Y[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData, Y0xF)) + v.y * rhw * *Pointer<Float>(data + OFFSET(DrawData, HxF)));
Nicolas Capens157ba262019-12-10 17:49:14 -0500144
145 i++;
146 }
Ben Clayton71af5932019-12-11 10:05:24 +0000147 Until(i >= n);
Nicolas Capens157ba262019-12-10 17:49:14 -0500148 }
149
150 // Vertical range
151 Int yMin = Y[0];
152 Int yMax = Y[0];
153
154 Int i = 1;
155
156 Do
157 {
158 yMin = Min(Y[i], yMin);
159 yMax = Max(Y[i], yMax);
160
161 i++;
162 }
Ben Clayton71af5932019-12-11 10:05:24 +0000163 Until(i >= n);
Nicolas Capens157ba262019-12-10 17:49:14 -0500164
165 constexpr int subPixB = vk::SUBPIXEL_PRECISION_BITS;
166 constexpr int subPixM = vk::SUBPIXEL_PRECISION_MASK;
167 constexpr float subPixF = vk::SUBPIXEL_PRECISION_FACTOR;
168
Nicolas Capens177d85d2020-01-14 00:36:46 -0500169 if(state.enableMultiSampling)
Nicolas Capens157ba262019-12-10 17:49:14 -0500170 {
171 yMin = (yMin + Constants::yMinMultiSampleOffset) >> subPixB;
172 yMax = (yMax + Constants::yMaxMultiSampleOffset) >> subPixB;
173 }
174 else
175 {
176 yMin = (yMin + subPixM) >> subPixB;
177 yMax = (yMax + subPixM) >> subPixB;
178 }
179
Ben Claytonbc1c0672019-12-17 20:37:37 +0000180 yMin = Max(yMin, *Pointer<Int>(data + OFFSET(DrawData, scissorY0)));
181 yMax = Min(yMax, *Pointer<Int>(data + OFFSET(DrawData, scissorY1)));
Nicolas Capens157ba262019-12-10 17:49:14 -0500182
183 // If yMin and yMax are initially negative, the scissor clamping above will typically result
184 // in yMin == 0 and yMax unchanged. We bail as we don't need to rasterize this primitive, and
185 // code below assumes yMin < yMax.
186 If(yMin >= yMax)
187 {
188 Return(0);
189 }
190
Nicolas Capens11cb8912020-01-14 00:24:05 -0500191 For(Int q = 0, q < state.multiSampleCount, q++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500192 {
193 Array<Int> Xq(16);
194 Array<Int> Yq(16);
195
196 Int i = 0;
197
198 Do
199 {
200 Xq[i] = X[i];
201 Yq[i] = Y[i];
202
Nicolas Capens177d85d2020-01-14 00:36:46 -0500203 if(state.enableMultiSampling)
Nicolas Capens157ba262019-12-10 17:49:14 -0500204 {
Alexis Hetub9fc42d2020-01-23 17:00:58 -0500205 // The subtraction here is because we're not moving the point, we're testing the edge against it
206 Xq[i] = Xq[i] - *Pointer<Int>(constants + OFFSET(Constants, Xf) + q * sizeof(int));
207 Yq[i] = Yq[i] - *Pointer<Int>(constants + OFFSET(Constants, Yf) + q * sizeof(int));
Nicolas Capens157ba262019-12-10 17:49:14 -0500208 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400209
210 i++;
211 }
Ben Clayton71af5932019-12-11 10:05:24 +0000212 Until(i >= n);
Nicolas Capens68a82382018-10-02 13:16:55 -0400213
Ben Claytonbc1c0672019-12-17 20:37:37 +0000214 Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive, outline->left)) + q * sizeof(Primitive);
215 Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive, outline->right)) + q * sizeof(Primitive);
Antonio Maioranoae022fa2019-10-07 12:57:19 -0400216
Nicolas Capens177d85d2020-01-14 00:36:46 -0500217 if(state.enableMultiSampling)
Nicolas Capens68a82382018-10-02 13:16:55 -0400218 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500219 Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0));
220 Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1));
221 Short x = Short(Clamp((X[0] + subPixM) >> subPixB, xMin, xMax));
222
223 For(Int y = yMin - 1, y < yMax + 1, y++)
224 {
225 *Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x;
226 *Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x;
227 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400228 }
229
Nicolas Capens157ba262019-12-10 17:49:14 -0500230 Xq[n] = Xq[0];
231 Yq[n] = Yq[0];
Antonio Maiorano970e4f02019-04-26 10:12:49 -0400232
Nicolas Capens157ba262019-12-10 17:49:14 -0500233 // Rasterize
Nicolas Capens68a82382018-10-02 13:16:55 -0400234 {
Nicolas Capens68a82382018-10-02 13:16:55 -0400235 Int i = 0;
236
237 Do
238 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500239 edge(primitive, data, Xq[i + 1 - d], Yq[i + 1 - d], Xq[i + d], Yq[i + d], q);
Nicolas Capens68a82382018-10-02 13:16:55 -0400240
241 i++;
242 }
Ben Clayton71af5932019-12-11 10:05:24 +0000243 Until(i >= n);
Nicolas Capens68a82382018-10-02 13:16:55 -0400244 }
245
Nicolas Capens177d85d2020-01-14 00:36:46 -0500246 if(!state.enableMultiSampling)
Nicolas Capens68a82382018-10-02 13:16:55 -0400247 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500248 For(, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++)
249 {
250 // Increments yMin
251 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400252
Nicolas Capens157ba262019-12-10 17:49:14 -0500253 For(, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--)
254 {
255 // Decrements yMax
256 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400257
Nicolas Capens157ba262019-12-10 17:49:14 -0500258 If(yMin == yMax)
259 {
260 Return(0);
261 }
262
263 *Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
264 *Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
265 *Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
266 *Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
Nicolas Capens68a82382018-10-02 13:16:55 -0400267 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500268 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400269
Ben Claytonbc1c0672019-12-17 20:37:37 +0000270 *Pointer<Int>(primitive + OFFSET(Primitive, yMin)) = yMin;
271 *Pointer<Int>(primitive + OFFSET(Primitive, yMax)) = yMax;
Nicolas Capens68a82382018-10-02 13:16:55 -0400272
Nicolas Capens157ba262019-12-10 17:49:14 -0500273 // Sort by minimum y
274 if(triangle)
275 {
276 Float y0 = *Pointer<Float>(v0 + OFFSET(Vertex, y));
277 Float y1 = *Pointer<Float>(v1 + OFFSET(Vertex, y));
278 Float y2 = *Pointer<Float>(v2 + OFFSET(Vertex, y));
Nicolas Capens68a82382018-10-02 13:16:55 -0400279
Nicolas Capens157ba262019-12-10 17:49:14 -0500280 Float yMin = Min(Min(y0, y1), y2);
Nicolas Capens68a82382018-10-02 13:16:55 -0400281
Nicolas Capens157ba262019-12-10 17:49:14 -0500282 conditionalRotate1(yMin == y1, v0, v1, v2);
283 conditionalRotate2(yMin == y2, v0, v1, v2);
284 }
285
286 // Sort by maximum w
287 if(triangle)
288 {
Nicolas Capens18c9ac42019-08-27 09:28:27 -0400289 Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, w));
290 Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, w));
291 Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, w));
Nicolas Capens68a82382018-10-02 13:16:55 -0400292
Nicolas Capens157ba262019-12-10 17:49:14 -0500293 Float wMax = Max(Max(w0, w1), w2);
Nicolas Capens68a82382018-10-02 13:16:55 -0400294
Nicolas Capens157ba262019-12-10 17:49:14 -0500295 conditionalRotate1(wMax == w1, v0, v1, v2);
296 conditionalRotate2(wMax == w2, v0, v1, v2);
297 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400298
Nicolas Capens157ba262019-12-10 17:49:14 -0500299 Float w0 = *Pointer<Float>(v0 + OFFSET(Vertex, w));
300 Float w1 = *Pointer<Float>(v1 + OFFSET(Vertex, w));
301 Float w2 = *Pointer<Float>(v2 + OFFSET(Vertex, w));
Nicolas Capens68a82382018-10-02 13:16:55 -0400302
Nicolas Capens157ba262019-12-10 17:49:14 -0500303 Float4 w012;
Nicolas Capens68a82382018-10-02 13:16:55 -0400304
Nicolas Capens157ba262019-12-10 17:49:14 -0500305 w012.x = w0;
306 w012.y = w1;
307 w012.z = w2;
308 w012.w = 1;
Nicolas Capens68a82382018-10-02 13:16:55 -0400309
Ben Claytonbc1c0672019-12-17 20:37:37 +0000310 Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex, projected.w));
Nicolas Capens157ba262019-12-10 17:49:14 -0500311
Ben Claytonbc1c0672019-12-17 20:37:37 +0000312 Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex, projected.x));
313 Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex, projected.x));
314 Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex, projected.x));
Nicolas Capens157ba262019-12-10 17:49:14 -0500315
Ben Claytonbc1c0672019-12-17 20:37:37 +0000316 Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex, projected.y));
317 Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex, projected.y));
318 Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex, projected.y));
Nicolas Capens157ba262019-12-10 17:49:14 -0500319
320 if(point)
321 {
322 *Pointer<Float>(primitive + OFFSET(Primitive, pointCoordX)) = Float(1.0f / subPixF) * Float(X0);
323 *Pointer<Float>(primitive + OFFSET(Primitive, pointCoordY)) = Float(1.0f / subPixF) * Float(Y0);
324 }
325
326 if(line)
327 {
328 X2 = X1 + Y1 - Y0;
329 Y2 = Y1 + X0 - X1;
330 }
331
332 Float dx = Float(X0) * (1.0f / subPixF);
333 Float dy = Float(Y0) * (1.0f / subPixF);
334
335 X1 -= X0;
336 Y1 -= Y0;
337
338 X2 -= X0;
339 Y2 -= Y0;
340
341 Float x1 = w1 * (1.0f / subPixF) * Float(X1);
342 Float y1 = w1 * (1.0f / subPixF) * Float(Y1);
343
344 Float x2 = w2 * (1.0f / subPixF) * Float(X2);
345 Float y2 = w2 * (1.0f / subPixF) * Float(Y2);
346
347 Float a = x1 * y2 - x2 * y1;
348
349 Float4 xQuad = Float4(0, 1, 0, 1) - Float4(dx);
350 Float4 yQuad = Float4(0, 0, 1, 1) - Float4(dy);
351
Ben Claytonbc1c0672019-12-17 20:37:37 +0000352 *Pointer<Float4>(primitive + OFFSET(Primitive, xQuad), 16) = xQuad;
353 *Pointer<Float4>(primitive + OFFSET(Primitive, yQuad), 16) = yQuad;
Nicolas Capens157ba262019-12-10 17:49:14 -0500354
355 Float4 M[3];
356
357 M[0] = Float4(0, 0, 0, 0);
358 M[1] = Float4(0, 0, 0, 0);
359 M[2] = Float4(0, 0, 0, 0);
360
361 M[0].z = rhw0;
362
363 If(a != 0.0f)
364 {
365 Float A = 1.0f / a;
366 Float D = A * rhw0;
367
368 M[0].x = (y1 * w2 - y2 * w1) * D;
369 M[0].y = (x2 * w1 - x1 * w2) * D;
Ben Claytonbc1c0672019-12-17 20:37:37 +0000370 // M[0].z = rhw0;
371 // M[0].w = 0;
Nicolas Capens157ba262019-12-10 17:49:14 -0500372
373 M[1].x = y2 * A;
374 M[1].y = -x2 * A;
Ben Claytonbc1c0672019-12-17 20:37:37 +0000375 // M[1].z = 0;
376 // M[1].w = 0;
Nicolas Capens157ba262019-12-10 17:49:14 -0500377
378 M[2].x = -y1 * A;
379 M[2].y = x1 * A;
Ben Claytonbc1c0672019-12-17 20:37:37 +0000380 // M[2].z = 0;
381 // M[2].w = 0;
Nicolas Capens157ba262019-12-10 17:49:14 -0500382 }
383
384 if(state.interpolateW)
385 {
386 Float4 ABC = M[0] + M[1] + M[2];
387
388 Float4 A = ABC.x;
389 Float4 B = ABC.y;
390 Float4 C = ABC.z;
391
Ben Claytonbc1c0672019-12-17 20:37:37 +0000392 *Pointer<Float4>(primitive + OFFSET(Primitive, w.A), 16) = A;
393 *Pointer<Float4>(primitive + OFFSET(Primitive, w.B), 16) = B;
394 *Pointer<Float4>(primitive + OFFSET(Primitive, w.C), 16) = C;
Nicolas Capens157ba262019-12-10 17:49:14 -0500395 }
396
397 if(state.interpolateZ)
398 {
Ben Claytonbc1c0672019-12-17 20:37:37 +0000399 Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex, projected.z));
400 Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex, projected.z));
401 Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex, projected.z));
Nicolas Capens157ba262019-12-10 17:49:14 -0500402
403 z1 -= z0;
404 z2 -= z0;
405
406 Float4 A;
407 Float4 B;
408 Float4 C;
409
410 if(!point)
Chris Forbesef55c4e2019-09-08 14:17:43 +0100411 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500412 Float x1 = Float(X1) * (1.0f / subPixF);
413 Float y1 = Float(Y1) * (1.0f / subPixF);
414 Float x2 = Float(X2) * (1.0f / subPixF);
415 Float y2 = Float(Y2) * (1.0f / subPixF);
416
Ben Claytonbc1c0672019-12-17 20:37:37 +0000417 Float D = *Pointer<Float>(data + OFFSET(DrawData, depthRange)) / (x1 * y2 - x2 * y1);
Nicolas Capens157ba262019-12-10 17:49:14 -0500418
419 Float a = (y2 * z1 - y1 * z2) * D;
420 Float b = (x1 * z2 - x2 * z1) * D;
421
422 A = Float4(a);
423 B = Float4(b);
424 }
425 else
426 {
427 A = Float4(0, 0, 0, 0);
428 B = Float4(0, 0, 0, 0);
Chris Forbesef55c4e2019-09-08 14:17:43 +0100429 }
430
Ben Claytonbc1c0672019-12-17 20:37:37 +0000431 *Pointer<Float4>(primitive + OFFSET(Primitive, z.A), 16) = A;
432 *Pointer<Float4>(primitive + OFFSET(Primitive, z.B), 16) = B;
Nicolas Capens157ba262019-12-10 17:49:14 -0500433
434 Float c = z0;
435
436 if(state.applySlopeDepthBias)
Nicolas Capens68a82382018-10-02 13:16:55 -0400437 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500438 Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x)));
Ben Claytonbc1c0672019-12-17 20:37:37 +0000439 bias *= *Pointer<Float>(data + OFFSET(DrawData, slopeDepthBias));
Nicolas Capens157ba262019-12-10 17:49:14 -0500440
441 c += bias;
Nicolas Capens68a82382018-10-02 13:16:55 -0400442 }
443
Ben Claytonbc1c0672019-12-17 20:37:37 +0000444 C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData, depthRange)) + *Pointer<Float>(data + OFFSET(DrawData, depthNear)));
Nicolas Capens68a82382018-10-02 13:16:55 -0400445
Ben Claytonbc1c0672019-12-17 20:37:37 +0000446 *Pointer<Float4>(primitive + OFFSET(Primitive, z.C), 16) = C;
Nicolas Capens157ba262019-12-10 17:49:14 -0500447 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400448
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500449 for(int interpolant = 0; interpolant < MAX_INTERFACE_COMPONENTS; interpolant++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500450 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500451 if(state.gradient[interpolant].Type != SpirvShader::ATTRIBTYPE_UNUSED)
Ben Clayton9ad035b2019-08-09 23:44:09 +0100452 {
453 setupGradient(primitive, tri, w012, M, v0, v1, v2,
Ben Claytonbc1c0672019-12-17 20:37:37 +0000454 OFFSET(Vertex, v[interpolant]),
455 OFFSET(Primitive, V[interpolant]),
456 state.gradient[interpolant].Flat,
457 !state.gradient[interpolant].NoPerspective);
Ben Clayton9ad035b2019-08-09 23:44:09 +0100458 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400459 }
460
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500461 for(unsigned int i = 0; i < state.numClipDistances; i++)
Nicolas Capens68a82382018-10-02 13:16:55 -0400462 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500463 setupGradient(primitive, tri, w012, M, v0, v1, v2,
Ben Claytonbc1c0672019-12-17 20:37:37 +0000464 OFFSET(Vertex, clipDistance[i]),
465 OFFSET(Primitive, clipDistance[i]),
466 false, true);
Nicolas Capens68a82382018-10-02 13:16:55 -0400467 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500468
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500469 for(unsigned int i = 0; i < state.numCullDistances; i++)
Nicolas Capens68a82382018-10-02 13:16:55 -0400470 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500471 setupGradient(primitive, tri, w012, M, v0, v1, v2,
Ben Claytonbc1c0672019-12-17 20:37:37 +0000472 OFFSET(Vertex, cullDistance[i]),
473 OFFSET(Primitive, cullDistance[i]),
474 false, true);
Nicolas Capens68a82382018-10-02 13:16:55 -0400475 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500476
477 Return(1);
Nicolas Capens68a82382018-10-02 13:16:55 -0400478 }
479
Nicolas Capens157ba262019-12-10 17:49:14 -0500480 routine = function("SetupRoutine");
481}
482
483void 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 perspective)
484{
485 if(!flat)
Nicolas Capens68a82382018-10-02 13:16:55 -0400486 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500487 Float4 i;
488 i.x = *Pointer<Float>(v0 + attribute);
489 i.y = *Pointer<Float>(v1 + attribute);
490 i.z = *Pointer<Float>(v2 + attribute);
491 i.w = 0;
492
493 if(!perspective)
Nicolas Capens68a82382018-10-02 13:16:55 -0400494 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500495 i *= w012;
Nicolas Capens68a82382018-10-02 13:16:55 -0400496 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500497
498 Float4 A = i.xxxx * m[0];
499 Float4 B = i.yyyy * m[1];
500 Float4 C = i.zzzz * m[2];
501
502 C = A + B + C;
503
504 A = C.xxxx;
505 B = C.yyyy;
506 C = C.zzzz;
507
508 *Pointer<Float4>(primitive + planeEquation + 0, 16) = A;
509 *Pointer<Float4>(primitive + planeEquation + 16, 16) = B;
510 *Pointer<Float4>(primitive + planeEquation + 32, 16) = C;
Nicolas Capens68a82382018-10-02 13:16:55 -0400511 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500512 else
Nicolas Capens68a82382018-10-02 13:16:55 -0400513 {
Ben Claytonbc1c0672019-12-17 20:37:37 +0000514 int leadingVertex = OFFSET(Triangle, v0);
Nicolas Capens157ba262019-12-10 17:49:14 -0500515 Float C = *Pointer<Float>(triangle + leadingVertex + attribute);
Nicolas Capens68a82382018-10-02 13:16:55 -0400516
Nicolas Capens157ba262019-12-10 17:49:14 -0500517 *Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0);
518 *Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0);
519 *Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C);
Nicolas Capens68a82382018-10-02 13:16:55 -0400520 }
521}
Nicolas Capens157ba262019-12-10 17:49:14 -0500522
523void SetupRoutine::edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &Xa, const Int &Ya, const Int &Xb, const Int &Yb, Int &q)
524{
525 If(Ya != Yb)
526 {
527 Bool swap = Yb < Ya;
528
529 Int X1 = IfThenElse(swap, Xb, Xa);
530 Int X2 = IfThenElse(swap, Xa, Xb);
531 Int Y1 = IfThenElse(swap, Yb, Ya);
532 Int Y2 = IfThenElse(swap, Ya, Yb);
533
534 constexpr int subPixB = vk::SUBPIXEL_PRECISION_BITS;
535 constexpr int subPixM = vk::SUBPIXEL_PRECISION_MASK;
536
Ben Claytonbc1c0672019-12-17 20:37:37 +0000537 Int y1 = Max((Y1 + subPixM) >> subPixB, *Pointer<Int>(data + OFFSET(DrawData, scissorY0)));
538 Int y2 = Min((Y2 + subPixM) >> subPixB, *Pointer<Int>(data + OFFSET(DrawData, scissorY1)));
Nicolas Capens157ba262019-12-10 17:49:14 -0500539
540 If(y1 < y2)
541 {
Ben Claytonbc1c0672019-12-17 20:37:37 +0000542 Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0));
543 Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1));
Nicolas Capens157ba262019-12-10 17:49:14 -0500544
Ben Claytonbc1c0672019-12-17 20:37:37 +0000545 Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->left);
546 Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->right);
Nicolas Capens157ba262019-12-10 17:49:14 -0500547 Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge);
548
549 // Deltas
550 Int DX12 = X2 - X1;
551 Int DY12 = Y2 - Y1;
552
553 Int FDX12 = DX12 << subPixB;
554 Int FDY12 = DY12 << subPixB;
555
556 Int X = DX12 * ((y1 << subPixB) - Y1) + (X1 & subPixM) * DY12;
Ben Claytonbc1c0672019-12-17 20:37:37 +0000557 Int x = (X1 >> subPixB) + X / FDY12; // Edge
558 Int d = X % FDY12; // Error-term
559 Int ceil = -d >> 31; // Ceiling division: remainder <= 0
Nicolas Capens157ba262019-12-10 17:49:14 -0500560 x -= ceil;
561 d -= ceil & FDY12;
562
Ben Claytonbc1c0672019-12-17 20:37:37 +0000563 Int Q = FDX12 / FDY12; // Edge-step
564 Int R = FDX12 % FDY12; // Error-step
565 Int floor = R >> 31; // Flooring division: remainder >= 0
Nicolas Capens157ba262019-12-10 17:49:14 -0500566 Q += floor;
567 R += floor & FDY12;
568
Ben Claytonbc1c0672019-12-17 20:37:37 +0000569 Int D = FDY12; // Error-overflow
Nicolas Capens157ba262019-12-10 17:49:14 -0500570 Int y = y1;
571
572 Do
573 {
574 *Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(Clamp(x, xMin, xMax));
575
576 x += Q;
577 d += R;
578
579 Int overflow = -d >> 31;
580
581 d -= D & overflow;
582 x -= overflow;
583
584 y++;
585 }
Ben Clayton71af5932019-12-11 10:05:24 +0000586 Until(y >= y2);
Nicolas Capens157ba262019-12-10 17:49:14 -0500587 }
588 }
589}
590
591void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
592{
Ben Claytonbc1c0672019-12-17 20:37:37 +0000593#if 0 // Rely on LLVM optimization
Nicolas Capens157ba262019-12-10 17:49:14 -0500594 If(condition)
595 {
596 Pointer<Byte> vX;
597
598 vX = v0;
599 v0 = v1;
600 v1 = v2;
601 v2 = vX;
602 }
Ben Claytonbc1c0672019-12-17 20:37:37 +0000603#else
604 Pointer<Byte> vX = v0;
605 v0 = IfThenElse(condition, v1, v0);
606 v1 = IfThenElse(condition, v2, v1);
607 v2 = IfThenElse(condition, vX, v2);
608#endif
Nicolas Capens157ba262019-12-10 17:49:14 -0500609}
610
611void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
612{
Ben Claytonbc1c0672019-12-17 20:37:37 +0000613#if 0 // Rely on LLVM optimization
Nicolas Capens157ba262019-12-10 17:49:14 -0500614 If(condition)
615 {
616 Pointer<Byte> vX;
617
618 vX = v2;
619 v2 = v1;
620 v1 = v0;
621 v0 = vX;
622 }
Ben Claytonbc1c0672019-12-17 20:37:37 +0000623#else
624 Pointer<Byte> vX = v2;
625 v2 = IfThenElse(condition, v1, v2);
626 v1 = IfThenElse(condition, v0, v1);
627 v0 = IfThenElse(condition, vX, v0);
628#endif
Nicolas Capens157ba262019-12-10 17:49:14 -0500629}
630
631SetupFunction::RoutineType SetupRoutine::getRoutine()
632{
633 return routine;
634}
635
636} // namespace sw