blob: ed752d21bf801ac27dca9688020deba2d224dbd2 [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"
20#include "System/Math.hpp"
Chris Forbesebe5f7f2019-01-16 10:38:34 -080021#include "Vulkan/VkDebug.hpp"
Nicolas Capens68a82382018-10-02 13:16:55 -040022
23namespace sw
24{
Nicolas Capens68a82382018-10-02 13:16:55 -040025 extern bool fullPixelPositionRegister;
26
27 extern int clusterCount;
28
Chris Forbes1845d5e2018-12-27 11:50:15 -080029 QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, SpirvShader const *spirvShader) : state(state), spirvShader{spirvShader}
Nicolas Capens68a82382018-10-02 13:16:55 -040030 {
31 }
32
33 QuadRasterizer::~QuadRasterizer()
34 {
35 }
36
37 void QuadRasterizer::generate()
38 {
39 #if PERF_PROFILE
40 for(int i = 0; i < PERF_TIMERS; i++)
41 {
42 cycles[i] = 0;
43 }
44
45 Long pixelTime = Ticks();
46 #endif
47
48 constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,constants));
49 occlusion = 0;
50 int clusterCount = Renderer::getClusterCount();
51
52 Do
53 {
54 Int yMin = *Pointer<Int>(primitive + OFFSET(Primitive,yMin));
55 Int yMax = *Pointer<Int>(primitive + OFFSET(Primitive,yMax));
56
57 Int cluster2 = cluster + cluster;
58 yMin += clusterCount * 2 - 2 - cluster2;
59 yMin &= -clusterCount * 2;
60 yMin += cluster2;
61
62 If(yMin < yMax)
63 {
64 rasterize(yMin, yMax);
65 }
66
67 primitive += sizeof(Primitive) * state.multiSample;
68 count--;
69 }
70 Until(count == 0)
71
72 if(state.occlusionEnabled)
73 {
74 UInt clusterOcclusion = *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster);
75 clusterOcclusion += occlusion;
76 *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster) = clusterOcclusion;
77 }
78
79 #if PERF_PROFILE
80 cycles[PERF_PIXEL] = Ticks() - pixelTime;
81
82 for(int i = 0; i < PERF_TIMERS; i++)
83 {
84 *Pointer<Long>(data + OFFSET(DrawData,cycles[i]) + 8 * cluster) += cycles[i];
85 }
86 #endif
87
88 Return();
89 }
90
91 void QuadRasterizer::rasterize(Int &yMin, Int &yMax)
92 {
93 Pointer<Byte> cBuffer[RENDERTARGETS];
94 Pointer<Byte> zBuffer;
95 Pointer<Byte> sBuffer;
96
97 for(int index = 0; index < RENDERTARGETS; index++)
98 {
99 if(state.colorWriteActive(index))
100 {
101 cBuffer[index] = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,colorBuffer[index])) + yMin * *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index]));
102 }
103 }
104
105 if(state.depthTestActive)
106 {
107 zBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,depthBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData,depthPitchB));
108 }
109
110 if(state.stencilActive)
111 {
112 sBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,stencilBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData,stencilPitchB));
113 }
114
115 Int y = yMin;
116
117 Do
118 {
119 Int x0a = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
120 Int x0b = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
121 Int x0 = Min(x0a, x0b);
122
123 for(unsigned int q = 1; q < state.multiSample; q++)
124 {
125 x0a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span)));
126 x0b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span)));
127 x0 = Min(x0, Min(x0a, x0b));
128 }
129
130 x0 &= 0xFFFFFFFE;
131
132 Int x1a = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
133 Int x1b = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
134 Int x1 = Max(x1a, x1b);
135
136 for(unsigned int q = 1; q < state.multiSample; q++)
137 {
138 x1a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span)));
139 x1b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span)));
140 x1 = Max(x1, Max(x1a, x1b));
141 }
142
143 Float4 yyyy = Float4(Float(y)) + *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16);
144
145 if(interpolateZ())
146 {
147 for(unsigned int q = 0; q < state.multiSample; q++)
148 {
149 Float4 y = yyyy;
150
151 if(state.multiSample > 1)
152 {
153 y -= *Pointer<Float4>(constants + OFFSET(Constants,Y) + q * sizeof(float4));
154 }
155
156 Dz[q] = *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) + y * *Pointer<Float4>(primitive + OFFSET(Primitive,z.B), 16);
157 }
158 }
159
Nicolas Capens68a82382018-10-02 13:16:55 -0400160 If(x0 < x1)
161 {
162 if(interpolateW())
163 {
164 Dw = *Pointer<Float4>(primitive + OFFSET(Primitive,w.C), 16) + yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,w.B), 16);
165 }
166
Chris Forbes5d61a1c2019-02-10 21:03:00 +0000167 for (int interpolant = 0; interpolant < MAX_INTERFACE_COMPONENTS; interpolant++)
Nicolas Capens68a82382018-10-02 13:16:55 -0400168 {
Chris Forbes5d61a1c2019-02-10 21:03:00 +0000169 if (spirvShader->inputs[interpolant].Type == SpirvShader::ATTRIBTYPE_UNUSED)
170 continue;
Nicolas Capens68a82382018-10-02 13:16:55 -0400171
Chris Forbes5d61a1c2019-02-10 21:03:00 +0000172 Dv[interpolant] = *Pointer<Float4>(primitive + OFFSET(Primitive, V[interpolant].C), 16);
173 if (!spirvShader->inputs[interpolant].Flat)
174 {
175 Dv[interpolant] += yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive, V[interpolant].B), 16);
Nicolas Capens68a82382018-10-02 13:16:55 -0400176 }
177 }
178
Nicolas Capens68a82382018-10-02 13:16:55 -0400179 Short4 xLeft[4];
180 Short4 xRight[4];
181
182 for(unsigned int q = 0; q < state.multiSample; q++)
183 {
184 xLeft[q] = *Pointer<Short4>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline) + y * sizeof(Primitive::Span));
185 xRight[q] = xLeft[q];
186
187 xLeft[q] = Swizzle(xLeft[q], 0xA0) - Short4(1, 2, 1, 2);
188 xRight[q] = Swizzle(xRight[q], 0xF5) - Short4(0, 1, 0, 1);
189 }
190
191 For(Int x = x0, x < x1, x += 2)
192 {
193 Short4 xxxx = Short4(x);
194 Int cMask[4];
195
196 for(unsigned int q = 0; q < state.multiSample; q++)
197 {
198 Short4 mask = CmpGT(xxxx, xLeft[q]) & CmpGT(xRight[q], xxxx);
199 cMask[q] = SignMask(PackSigned(mask, mask)) & 0x0000000F;
200 }
201
202 quad(cBuffer, zBuffer, sBuffer, cMask, x, y);
203 }
204 }
205
206 int clusterCount = Renderer::getClusterCount();
207
208 for(int index = 0; index < RENDERTARGETS; index++)
209 {
210 if(state.colorWriteActive(index))
211 {
212 cBuffer[index] += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index])) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
213 }
214 }
215
216 if(state.depthTestActive)
217 {
218 zBuffer += *Pointer<Int>(data + OFFSET(DrawData,depthPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
219 }
220
221 if(state.stencilActive)
222 {
223 sBuffer += *Pointer<Int>(data + OFFSET(DrawData,stencilPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute
224 }
225
226 y += 2 * clusterCount;
227 }
228 Until(y >= yMax)
229 }
230
231 Float4 QuadRasterizer::interpolate(Float4 &x, Float4 &D, Float4 &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective, bool clamp)
232 {
233 Float4 interpolant = D;
234
235 if(!flat)
236 {
237 interpolant += x * *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation, A), 16);
238
239 if(perspective)
240 {
241 interpolant *= rhw;
242 }
243 }
244
245 if(clamp)
246 {
247 interpolant = Min(Max(interpolant, Float4(0.0f)), Float4(1.0f));
248 }
249
250 return interpolant;
251 }
252
253 bool QuadRasterizer::interpolateZ() const
254 {
Chris Forbes1845d5e2018-12-27 11:50:15 -0800255 return state.depthTestActive || (spirvShader && spirvShader->hasBuiltinInput(spv::BuiltInPosition));
Nicolas Capens68a82382018-10-02 13:16:55 -0400256 }
257
258 bool QuadRasterizer::interpolateW() const
259 {
Chris Forbes1845d5e2018-12-27 11:50:15 -0800260 return state.perspective || (spirvShader && spirvShader->hasBuiltinInput(spv::BuiltInPosition));
Nicolas Capens68a82382018-10-02 13:16:55 -0400261 }
262}