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