blob: 389b81a7f80636f66d9910f5b4ff7253a992b37e [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 "QuadRasterizer.hpp"
16
17#include "Primitive.hpp"
18#include "Renderer.hpp"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050019#include "Pipeline/Constants.hpp"
Ben Clayton25e06e02020-02-07 11:19:08 +000020#include "System/Debug.hpp"
Nicolas Capens1d8c8db2018-11-05 16:30:42 -050021#include "System/Math.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040022
Nicolas Capens157ba262019-12-10 17:49:14 -050023namespace sw {
24
Ben Claytonfccfc562019-12-17 20:37:31 +000025QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, SpirvShader const *spirvShader)
26 : state(state)
27 , spirvShader{ spirvShader }
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 -050031QuadRasterizer::~QuadRasterizer()
32{
33}
Nicolas Capens68a82382018-10-02 13:16:55 -040034
Nicolas Capens157ba262019-12-10 17:49:14 -050035void QuadRasterizer::generate()
36{
Ben Claytonfccfc562019-12-17 20:37:31 +000037 constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, constants));
Nicolas Capens157ba262019-12-10 17:49:14 -050038 occlusion = 0;
Nicolas Capens68a82382018-10-02 13:16:55 -040039
Nicolas Capens157ba262019-12-10 17:49:14 -050040 Do
41 {
Ben Claytonfccfc562019-12-17 20:37:31 +000042 Int yMin = *Pointer<Int>(primitive + OFFSET(Primitive, yMin));
43 Int yMax = *Pointer<Int>(primitive + OFFSET(Primitive, yMax));
Nicolas Capens157ba262019-12-10 17:49:14 -050044
45 Int cluster2 = cluster + cluster;
46 yMin += clusterCount * 2 - 2 - cluster2;
47 yMin &= -clusterCount * 2;
48 yMin += cluster2;
49
50 If(yMin < yMax)
Nicolas Capens68a82382018-10-02 13:16:55 -040051 {
Nicolas Capens157ba262019-12-10 17:49:14 -050052 rasterize(yMin, yMax);
53 }
Nicolas Capens68a82382018-10-02 13:16:55 -040054
Nicolas Capens11cb8912020-01-14 00:24:05 -050055 primitive += sizeof(Primitive) * state.multiSampleCount;
Nicolas Capens157ba262019-12-10 17:49:14 -050056 count--;
57 }
Ben Clayton71af5932019-12-11 10:05:24 +000058 Until(count == 0);
Nicolas Capens68a82382018-10-02 13:16:55 -040059
Nicolas Capens157ba262019-12-10 17:49:14 -050060 if(state.occlusionEnabled)
61 {
Ben Claytonfccfc562019-12-17 20:37:31 +000062 UInt clusterOcclusion = *Pointer<UInt>(data + OFFSET(DrawData, occlusion) + 4 * cluster);
Nicolas Capens157ba262019-12-10 17:49:14 -050063 clusterOcclusion += occlusion;
Ben Claytonfccfc562019-12-17 20:37:31 +000064 *Pointer<UInt>(data + OFFSET(DrawData, occlusion) + 4 * cluster) = clusterOcclusion;
Nicolas Capens157ba262019-12-10 17:49:14 -050065 }
66
67 Return();
68}
69
70void QuadRasterizer::rasterize(Int &yMin, Int &yMax)
71{
72 Pointer<Byte> cBuffer[RENDERTARGETS];
73 Pointer<Byte> zBuffer;
74 Pointer<Byte> sBuffer;
75
76 Int clusterCountLog2 = 31 - Ctlz(UInt(clusterCount), false);
77
78 for(int index = 0; index < RENDERTARGETS; index++)
79 {
80 if(state.colorWriteActive(index))
81 {
Ben Claytonfccfc562019-12-17 20:37:31 +000082 cBuffer[index] = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, colorBuffer[index])) + yMin * *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index]));
Nicolas Capens157ba262019-12-10 17:49:14 -050083 }
84 }
85
86 if(state.depthTestActive)
87 {
Ben Claytonfccfc562019-12-17 20:37:31 +000088 zBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, depthBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData, depthPitchB));
Nicolas Capens157ba262019-12-10 17:49:14 -050089 }
90
91 if(state.stencilActive)
92 {
Ben Claytonfccfc562019-12-17 20:37:31 +000093 sBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, stencilBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData, stencilPitchB));
Nicolas Capens157ba262019-12-10 17:49:14 -050094 }
95
96 Int y = yMin;
97
98 Do
99 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000100 Int x0a = Int(*Pointer<Short>(primitive + OFFSET(Primitive, outline->left) + (y + 0) * sizeof(Primitive::Span)));
101 Int x0b = Int(*Pointer<Short>(primitive + OFFSET(Primitive, outline->left) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capens157ba262019-12-10 17:49:14 -0500102 Int x0 = Min(x0a, x0b);
103
Nicolas Capens11cb8912020-01-14 00:24:05 -0500104 for(unsigned int q = 1; q < state.multiSampleCount; q++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500105 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000106 x0a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->left) + (y + 0) * sizeof(Primitive::Span)));
107 x0b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->left) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capens157ba262019-12-10 17:49:14 -0500108 x0 = Min(x0, Min(x0a, x0b));
109 }
110
111 x0 &= 0xFFFFFFFE;
112
Ben Claytonfccfc562019-12-17 20:37:31 +0000113 Int x1a = Int(*Pointer<Short>(primitive + OFFSET(Primitive, outline->right) + (y + 0) * sizeof(Primitive::Span)));
114 Int x1b = Int(*Pointer<Short>(primitive + OFFSET(Primitive, outline->right) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capens157ba262019-12-10 17:49:14 -0500115 Int x1 = Max(x1a, x1b);
116
Nicolas Capens11cb8912020-01-14 00:24:05 -0500117 for(unsigned int q = 1; q < state.multiSampleCount; q++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500118 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000119 x1a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->right) + (y + 0) * sizeof(Primitive::Span)));
120 x1b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline->right) + (y + 1) * sizeof(Primitive::Span)));
Nicolas Capens157ba262019-12-10 17:49:14 -0500121 x1 = Max(x1, Max(x1a, x1b));
122 }
123
Ben Claytonfccfc562019-12-17 20:37:31 +0000124 Float4 yyyy = Float4(Float(y)) + *Pointer<Float4>(primitive + OFFSET(Primitive, yQuad), 16);
Nicolas Capens157ba262019-12-10 17:49:14 -0500125
126 if(interpolateZ())
127 {
Nicolas Capens11cb8912020-01-14 00:24:05 -0500128 for(unsigned int q = 0; q < state.multiSampleCount; q++)
Nicolas Capens68a82382018-10-02 13:16:55 -0400129 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500130 Float4 y = yyyy;
131
Nicolas Capensc514ab02020-01-20 14:42:53 -0500132 if(state.enableMultiSampling)
Nicolas Capens157ba262019-12-10 17:49:14 -0500133 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000134 y -= *Pointer<Float4>(constants + OFFSET(Constants, Y) + q * sizeof(float4));
Nicolas Capens157ba262019-12-10 17:49:14 -0500135 }
136
Ben Claytonfccfc562019-12-17 20:37:31 +0000137 Dz[q] = *Pointer<Float4>(primitive + OFFSET(Primitive, z.C), 16) + y * *Pointer<Float4>(primitive + OFFSET(Primitive, z.B), 16);
Nicolas Capens157ba262019-12-10 17:49:14 -0500138 }
139 }
140
141 If(x0 < x1)
142 {
143 if(interpolateW())
144 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000145 Dw = *Pointer<Float4>(primitive + OFFSET(Primitive, w.C), 16) + yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive, w.B), 16);
Nicolas Capens68a82382018-10-02 13:16:55 -0400146 }
147
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500148 if(spirvShader)
Nicolas Capens157ba262019-12-10 17:49:14 -0500149 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500150 for(int interpolant = 0; interpolant < MAX_INTERFACE_COMPONENTS; interpolant++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500151 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500152 if(spirvShader->inputs[interpolant].Type == SpirvShader::ATTRIBTYPE_UNUSED)
Nicolas Capens157ba262019-12-10 17:49:14 -0500153 continue;
154
155 Dv[interpolant] = *Pointer<Float4>(primitive + OFFSET(Primitive, V[interpolant].C), 16);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500156 if(!spirvShader->inputs[interpolant].Flat)
Nicolas Capens157ba262019-12-10 17:49:14 -0500157 {
158 Dv[interpolant] +=
Ben Claytonfccfc562019-12-17 20:37:31 +0000159 yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive, V[interpolant].B), 16);
Nicolas Capens157ba262019-12-10 17:49:14 -0500160 }
161 }
162
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500163 for(unsigned int i = 0; i < state.numClipDistances; i++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500164 {
165 DclipDistance[i] = *Pointer<Float4>(primitive + OFFSET(Primitive, clipDistance[i].C), 16) +
Ben Claytonfccfc562019-12-17 20:37:31 +0000166 yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive, clipDistance[i].B), 16);
Nicolas Capens157ba262019-12-10 17:49:14 -0500167 }
168
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500169 for(unsigned int i = 0; i < state.numCullDistances; i++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500170 {
171 DcullDistance[i] = *Pointer<Float4>(primitive + OFFSET(Primitive, cullDistance[i].C), 16) +
Ben Claytonfccfc562019-12-17 20:37:31 +0000172 yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive, cullDistance[i].B), 16);
Nicolas Capens157ba262019-12-10 17:49:14 -0500173 }
174 }
175
176 Short4 xLeft[4];
177 Short4 xRight[4];
178
Nicolas Capens11cb8912020-01-14 00:24:05 -0500179 for(unsigned int q = 0; q < state.multiSampleCount; q++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500180 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000181 xLeft[q] = *Pointer<Short4>(primitive + q * sizeof(Primitive) + OFFSET(Primitive, outline) + y * sizeof(Primitive::Span));
Nicolas Capens157ba262019-12-10 17:49:14 -0500182 xRight[q] = xLeft[q];
183
184 xLeft[q] = Swizzle(xLeft[q], 0x0022) - Short4(1, 2, 1, 2);
185 xRight[q] = Swizzle(xRight[q], 0x1133) - Short4(0, 1, 0, 1);
186 }
187
188 For(Int x = x0, x < x1, x += 2)
189 {
190 Short4 xxxx = Short4(x);
191 Int cMask[4];
192
Nicolas Capens11cb8912020-01-14 00:24:05 -0500193 for(unsigned int q = 0; q < state.multiSampleCount; q++)
Nicolas Capens157ba262019-12-10 17:49:14 -0500194 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000195 if(state.multiSampleMask & (1 << q))
Nicolas Capens157ba262019-12-10 17:49:14 -0500196 {
Nicolas Capens11cb8912020-01-14 00:24:05 -0500197 unsigned int i = state.enableMultiSampling ? q : 0;
Nicolas Capens157ba262019-12-10 17:49:14 -0500198 Short4 mask = CmpGT(xxxx, xLeft[i]) & CmpGT(xRight[i], xxxx);
199 cMask[q] = SignMask(PackSigned(mask, mask)) & 0x0000000F;
200 }
201 else
202 {
203 cMask[q] = 0;
204 }
205 }
206
207 quad(cBuffer, zBuffer, sBuffer, cMask, x, y);
208 }
Nicolas Capens68a82382018-10-02 13:16:55 -0400209 }
Ben Claytonb5f0a4b2019-08-27 10:58:36 +0100210
Nicolas Capens68a82382018-10-02 13:16:55 -0400211 for(int index = 0; index < RENDERTARGETS; index++)
212 {
213 if(state.colorWriteActive(index))
214 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000215 cBuffer[index] += *Pointer<Int>(data + OFFSET(DrawData, colorPitchB[index])) << (1 + clusterCountLog2); // FIXME: Precompute
Nicolas Capens68a82382018-10-02 13:16:55 -0400216 }
217 }
218
219 if(state.depthTestActive)
220 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000221 zBuffer += *Pointer<Int>(data + OFFSET(DrawData, depthPitchB)) << (1 + clusterCountLog2); // FIXME: Precompute
Nicolas Capens68a82382018-10-02 13:16:55 -0400222 }
223
224 if(state.stencilActive)
225 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000226 sBuffer += *Pointer<Int>(data + OFFSET(DrawData, stencilPitchB)) << (1 + clusterCountLog2); // FIXME: Precompute
Nicolas Capens68a82382018-10-02 13:16:55 -0400227 }
228
Nicolas Capens157ba262019-12-10 17:49:14 -0500229 y += 2 * clusterCount;
Nicolas Capens68a82382018-10-02 13:16:55 -0400230 }
Ben Clayton71af5932019-12-11 10:05:24 +0000231 Until(y >= yMax);
Nicolas Capens68a82382018-10-02 13:16:55 -0400232}
Nicolas Capens157ba262019-12-10 17:49:14 -0500233
234Float4 QuadRasterizer::interpolate(Float4 &x, Float4 &D, Float4 &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective, bool clamp)
235{
236 Float4 interpolant = D;
237
238 if(!flat)
239 {
240 interpolant += x * *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation, A), 16);
241
242 if(perspective)
243 {
244 interpolant *= rhw;
245 }
246 }
247
248 if(clamp)
249 {
250 interpolant = Min(Max(interpolant, Float4(0.0f)), Float4(1.0f));
251 }
252
253 return interpolant;
254}
255
256bool QuadRasterizer::interpolateZ() const
257{
258 return state.depthTestActive || (spirvShader && spirvShader->hasBuiltinInput(spv::BuiltInFragCoord));
259}
260
261bool QuadRasterizer::interpolateW() const
262{
263 // Note: could optimize cases where there is a fragment shader but it has no
264 // perspective-correct inputs, but that's vanishingly rare.
265 return spirvShader != nullptr;
266}
267
268} // namespace sw