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 "Math.hpp" 18 #include "Primitive.hpp" 19 #include "Renderer.hpp" 20 #include "Constants.hpp" 21 #include "Debug.hpp" 22 23 namespace sw 24 { 25 extern bool veryEarlyDepthTest; 26 extern bool complementaryDepthBuffer; 27 extern bool fullPixelPositionRegister; 28 29 extern int clusterCount; 30 QuadRasterizer(const PixelProcessor::State & state,const PixelShader * pixelShader)31 QuadRasterizer::QuadRasterizer(const PixelProcessor::State &state, const PixelShader *pixelShader) : state(state), shader(pixelShader) 32 { 33 } 34 ~QuadRasterizer()35 QuadRasterizer::~QuadRasterizer() 36 { 37 } 38 generate()39 void QuadRasterizer::generate() 40 { 41 #if PERF_PROFILE 42 for(int i = 0; i < PERF_TIMERS; i++) 43 { 44 cycles[i] = 0; 45 } 46 47 Long pixelTime = Ticks(); 48 #endif 49 50 constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,constants)); 51 occlusion = 0; 52 53 Do 54 { 55 Int yMin = *Pointer<Int>(primitive + OFFSET(Primitive,yMin)); 56 Int yMax = *Pointer<Int>(primitive + OFFSET(Primitive,yMax)); 57 58 Int cluster2 = cluster + cluster; 59 yMin += clusterCount * 2 - 2 - cluster2; 60 yMin &= -clusterCount * 2; 61 yMin += cluster2; 62 63 If(yMin < yMax) 64 { 65 rasterize(yMin, yMax); 66 } 67 68 primitive += sizeof(Primitive) * state.multiSample; 69 count--; 70 } 71 Until(count == 0) 72 73 if(state.occlusionEnabled) 74 { 75 UInt clusterOcclusion = *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster); 76 clusterOcclusion += occlusion; 77 *Pointer<UInt>(data + OFFSET(DrawData,occlusion) + 4 * cluster) = clusterOcclusion; 78 } 79 80 #if PERF_PROFILE 81 cycles[PERF_PIXEL] = Ticks() - pixelTime; 82 83 for(int i = 0; i < PERF_TIMERS; i++) 84 { 85 *Pointer<Long>(data + OFFSET(DrawData,cycles[i]) + 8 * cluster) += cycles[i]; 86 } 87 #endif 88 89 Return(); 90 } 91 rasterize(Int & yMin,Int & yMax)92 void QuadRasterizer::rasterize(Int &yMin, Int &yMax) 93 { 94 Pointer<Byte> cBuffer[RENDERTARGETS]; 95 Pointer<Byte> zBuffer; 96 Pointer<Byte> sBuffer; 97 98 for(int index = 0; index < RENDERTARGETS; index++) 99 { 100 if(state.colorWriteActive(index)) 101 { 102 cBuffer[index] = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,colorBuffer[index])) + yMin * *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index])); 103 } 104 } 105 106 if(state.depthTestActive) 107 { 108 zBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,depthBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData,depthPitchB)); 109 } 110 111 if(state.stencilActive) 112 { 113 sBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,stencilBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData,stencilPitchB)); 114 } 115 116 Int y = yMin; 117 118 Do 119 { 120 Int x0a = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span))); 121 Int x0b = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span))); 122 Int x0 = Min(x0a, x0b); 123 124 for(unsigned int q = 1; q < state.multiSample; q++) 125 { 126 x0a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 0) * sizeof(Primitive::Span))); 127 x0b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left) + (y + 1) * sizeof(Primitive::Span))); 128 x0 = Min(x0, Min(x0a, x0b)); 129 } 130 131 x0 &= 0xFFFFFFFE; 132 133 Int x1a = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span))); 134 Int x1b = Int(*Pointer<Short>(primitive + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span))); 135 Int x1 = Max(x1a, x1b); 136 137 for(unsigned int q = 1; q < state.multiSample; q++) 138 { 139 x1a = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 0) * sizeof(Primitive::Span))); 140 x1b = Int(*Pointer<Short>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right) + (y + 1) * sizeof(Primitive::Span))); 141 x1 = Max(x1, Max(x1a, x1b)); 142 } 143 144 Float4 yyyy = Float4(Float(y)) + *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16); 145 146 if(interpolateZ()) 147 { 148 for(unsigned int q = 0; q < state.multiSample; q++) 149 { 150 Float4 y = yyyy; 151 152 if(state.multiSample > 1) 153 { 154 y -= *Pointer<Float4>(constants + OFFSET(Constants,Y) + q * sizeof(float4)); 155 } 156 157 Dz[q] = *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) + y * *Pointer<Float4>(primitive + OFFSET(Primitive,z.B), 16); 158 } 159 } 160 161 if(veryEarlyDepthTest && state.multiSample == 1) 162 { 163 if(!state.stencilActive && state.depthTestActive && (state.depthCompareMode == DEPTH_LESSEQUAL || state.depthCompareMode == DEPTH_LESS)) // FIXME: Both modes ok? 164 { 165 Float4 xxxx = Float4(Float(x0)) + *Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16); 166 167 Pointer<Byte> buffer; 168 Int pitch; 169 170 if(!state.quadLayoutDepthBuffer) 171 { 172 buffer = zBuffer + 4 * x0; 173 pitch = *Pointer<Int>(data + OFFSET(DrawData,depthPitchB)); 174 } 175 else 176 { 177 buffer = zBuffer + 8 * x0; 178 } 179 180 For(Int x = x0, x < x1, x += 2) 181 { 182 Float4 z = interpolate(xxxx, Dz[0], z, primitive + OFFSET(Primitive,z), false, false); 183 184 Float4 zValue; 185 186 if(!state.quadLayoutDepthBuffer) 187 { 188 // FIXME: Properly optimizes? 189 zValue.xy = *Pointer<Float4>(buffer); 190 zValue.zw = *Pointer<Float4>(buffer + pitch - 8); 191 } 192 else 193 { 194 zValue = *Pointer<Float4>(buffer, 16); 195 } 196 197 Int4 zTest; 198 199 if(complementaryDepthBuffer) 200 { 201 zTest = CmpLE(zValue, z); 202 } 203 else 204 { 205 zTest = CmpNLT(zValue, z); 206 } 207 208 Int zMask = SignMask(zTest); 209 210 If(zMask == 0) 211 { 212 x0 += 2; 213 } 214 Else 215 { 216 x = x1; 217 } 218 219 xxxx += Float4(2); 220 221 if(!state.quadLayoutDepthBuffer) 222 { 223 buffer += 8; 224 } 225 else 226 { 227 buffer += 16; 228 } 229 } 230 } 231 } 232 233 If(x0 < x1) 234 { 235 if(interpolateW()) 236 { 237 Dw = *Pointer<Float4>(primitive + OFFSET(Primitive,w.C), 16) + yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,w.B), 16); 238 } 239 240 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) 241 { 242 for(int component = 0; component < 4; component++) 243 { 244 if(state.interpolant[interpolant].component & (1 << component)) 245 { 246 Dv[interpolant][component] = *Pointer<Float4>(primitive + OFFSET(Primitive,V[interpolant][component].C), 16); 247 248 if(!(state.interpolant[interpolant].flat & (1 << component))) 249 { 250 Dv[interpolant][component] += yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,V[interpolant][component].B), 16); 251 } 252 } 253 } 254 } 255 256 if(state.fog.component) 257 { 258 Df = *Pointer<Float4>(primitive + OFFSET(Primitive,f.C), 16); 259 260 if(!state.fog.flat) 261 { 262 Df += yyyy * *Pointer<Float4>(primitive + OFFSET(Primitive,f.B), 16); 263 } 264 } 265 266 Short4 xLeft[4]; 267 Short4 xRight[4]; 268 269 for(unsigned int q = 0; q < state.multiSample; q++) 270 { 271 xLeft[q] = *Pointer<Short4>(primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline) + y * sizeof(Primitive::Span)); 272 xRight[q] = xLeft[q]; 273 274 xLeft[q] = Swizzle(xLeft[q], 0xA0) - Short4(1, 2, 1, 2); 275 xRight[q] = Swizzle(xRight[q], 0xF5) - Short4(0, 1, 0, 1); 276 } 277 278 For(Int x = x0, x < x1, x += 2) 279 { 280 Short4 xxxx = Short4(x); 281 Int cMask[4]; 282 283 for(unsigned int q = 0; q < state.multiSample; q++) 284 { 285 Short4 mask = CmpGT(xxxx, xLeft[q]) & CmpGT(xRight[q], xxxx); 286 cMask[q] = SignMask(Pack(mask, mask)) & 0x0000000F; 287 } 288 289 quad(cBuffer, zBuffer, sBuffer, cMask, x, y); 290 } 291 } 292 293 for(int index = 0; index < RENDERTARGETS; index++) 294 { 295 if(state.colorWriteActive(index)) 296 { 297 cBuffer[index] += *Pointer<Int>(data + OFFSET(DrawData,colorPitchB[index])) << (1 + sw::log2(clusterCount)); // FIXME: Precompute 298 } 299 } 300 301 if(state.depthTestActive) 302 { 303 zBuffer += *Pointer<Int>(data + OFFSET(DrawData,depthPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute 304 } 305 306 if(state.stencilActive) 307 { 308 sBuffer += *Pointer<Int>(data + OFFSET(DrawData,stencilPitchB)) << (1 + sw::log2(clusterCount)); // FIXME: Precompute 309 } 310 311 y += 2 * clusterCount; 312 } 313 Until(y >= yMax) 314 } 315 interpolate(Float4 & x,Float4 & D,Float4 & rhw,Pointer<Byte> planeEquation,bool flat,bool perspective)316 Float4 QuadRasterizer::interpolate(Float4 &x, Float4 &D, Float4 &rhw, Pointer<Byte> planeEquation, bool flat, bool perspective) 317 { 318 Float4 interpolant = D; 319 320 if(!flat) 321 { 322 interpolant += x * *Pointer<Float4>(planeEquation + OFFSET(PlaneEquation, A), 16); 323 324 if(perspective) 325 { 326 interpolant *= rhw; 327 } 328 } 329 330 return interpolant; 331 } 332 interpolateZ() const333 bool QuadRasterizer::interpolateZ() const 334 { 335 return state.depthTestActive || state.pixelFogActive() || (shader && shader->isVPosDeclared() && fullPixelPositionRegister); 336 } 337 interpolateW() const338 bool QuadRasterizer::interpolateW() const 339 { 340 return state.perspective || (shader && shader->isVPosDeclared() && fullPixelPositionRegister); 341 } 342 } 343