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 "SetupProcessor.hpp" 16 17 #include "SetupRoutine.hpp" 18 #include "Primitive.hpp" 19 #include "Polygon.hpp" 20 #include "Context.hpp" 21 #include "Renderer.hpp" 22 #include "Constants.hpp" 23 #include "Debug.hpp" 24 25 namespace sw 26 { 27 extern bool complementaryDepthBuffer; 28 extern bool fullPixelPositionRegister; 29 30 bool precacheSetup = false; 31 computeHash()32 unsigned int SetupProcessor::States::computeHash() 33 { 34 unsigned int *state = (unsigned int*)this; 35 unsigned int hash = 0; 36 37 for(unsigned int i = 0; i < sizeof(States) / 4; i++) 38 { 39 hash ^= state[i]; 40 } 41 42 return hash; 43 } 44 State(int i)45 SetupProcessor::State::State(int i) 46 { 47 memset(this, 0, sizeof(State)); 48 } 49 operator ==(const State & state) const50 bool SetupProcessor::State::operator==(const State &state) const 51 { 52 if(hash != state.hash) 53 { 54 return false; 55 } 56 57 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0; 58 } 59 SetupProcessor(Context * context)60 SetupProcessor::SetupProcessor(Context *context) : context(context) 61 { 62 routineCache = 0; 63 setRoutineCacheSize(1024); 64 } 65 ~SetupProcessor()66 SetupProcessor::~SetupProcessor() 67 { 68 delete routineCache; 69 routineCache = 0; 70 } 71 update() const72 SetupProcessor::State SetupProcessor::update() const 73 { 74 State state; 75 76 bool vPosZW = (context->pixelShader && context->pixelShader->vPosDeclared && fullPixelPositionRegister); 77 78 state.isDrawPoint = context->isDrawPoint(true); 79 state.isDrawLine = context->isDrawLine(true); 80 state.isDrawTriangle = context->isDrawTriangle(false); 81 state.isDrawSolidTriangle = context->isDrawTriangle(true); 82 state.interpolateZ = context->depthBufferActive() || context->pixelFogActive() != FOG_NONE || vPosZW; 83 state.interpolateW = context->perspectiveActive() || vPosZW; 84 state.perspective = context->perspectiveActive(); 85 state.pointSprite = context->pointSpriteActive(); 86 state.cullMode = context->cullMode; 87 state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil; 88 state.slopeDepthBias = slopeDepthBias != 0.0f; 89 state.vFace = context->pixelShader && context->pixelShader->vFaceDeclared; 90 91 state.positionRegister = Pos; 92 state.pointSizeRegister = Unused; 93 94 state.multiSample = context->getMultiSampleCount(); 95 state.rasterizerDiscard = context->rasterizerDiscard; 96 97 if(context->vertexShader) 98 { 99 state.positionRegister = context->vertexShader->positionRegister; 100 state.pointSizeRegister = context->vertexShader->pointSizeRegister; 101 } 102 else if(context->pointSizeActive()) 103 { 104 state.pointSizeRegister = Pts; 105 } 106 107 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) 108 { 109 for(int component = 0; component < 4; component++) 110 { 111 state.gradient[interpolant][component].attribute = Unused; 112 state.gradient[interpolant][component].flat = false; 113 state.gradient[interpolant][component].wrap = false; 114 } 115 } 116 117 state.fog.attribute = Unused; 118 state.fog.flat = false; 119 state.fog.wrap = false; 120 121 const bool point = context->isDrawPoint(true); 122 const bool sprite = context->pointSpriteActive(); 123 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point; 124 125 if(context->vertexShader && context->pixelShader) 126 { 127 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) 128 { 129 for(int component = 0; component < 4; component++) 130 { 131 int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0; 132 133 if(context->pixelShader->semantic[interpolant][component - project].active()) 134 { 135 int input = interpolant; 136 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++) 137 { 138 if(context->pixelShader->semantic[interpolant][component - project] == context->vertexShader->output[i][component - project]) 139 { 140 input = i; 141 break; 142 } 143 } 144 145 bool flat = point; 146 147 switch(context->pixelShader->semantic[interpolant][component - project].usage) 148 { 149 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break; 150 case Shader::USAGE_COLOR: flat = flatShading; break; 151 } 152 153 state.gradient[interpolant][component].attribute = input; 154 state.gradient[interpolant][component].flat = flat; 155 } 156 } 157 } 158 } 159 else if(context->preTransformed && context->pixelShader) 160 { 161 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) 162 { 163 for(int component = 0; component < 4; component++) 164 { 165 int index = context->pixelShader->semantic[interpolant][component].index; 166 167 switch(context->pixelShader->semantic[interpolant][component].usage) 168 { 169 case 0xFF: 170 break; 171 case Shader::USAGE_TEXCOORD: 172 state.gradient[interpolant][component].attribute = T0 + index; 173 state.gradient[interpolant][component].flat = point && !sprite; 174 break; 175 case Shader::USAGE_COLOR: 176 state.gradient[interpolant][component].attribute = C0 + index; 177 state.gradient[interpolant][component].flat = flatShading; 178 break; 179 default: 180 ASSERT(false); 181 } 182 } 183 } 184 } 185 else if(context->pixelShaderVersion() < 0x0300) 186 { 187 for(int coordinate = 0; coordinate < 8; coordinate++) 188 { 189 for(int component = 0; component < 4; component++) 190 { 191 if(context->textureActive(coordinate, component)) 192 { 193 state.texture[coordinate][component].attribute = T0 + coordinate; 194 state.texture[coordinate][component].flat = point && !sprite; 195 state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0; 196 } 197 } 198 } 199 200 for(int color = 0; color < 2; color++) 201 { 202 for(int component = 0; component < 4; component++) 203 { 204 if(context->colorActive(color, component)) 205 { 206 state.color[color][component].attribute = C0 + color; 207 state.color[color][component].flat = flatShading; 208 } 209 } 210 } 211 } 212 else ASSERT(false); 213 214 if(context->fogActive()) 215 { 216 state.fog.attribute = Fog; 217 state.fog.flat = point; 218 } 219 220 state.hash = state.computeHash(); 221 222 return state; 223 } 224 routine(const State & state)225 Routine *SetupProcessor::routine(const State &state) 226 { 227 Routine *routine = routineCache->query(state); 228 229 if(!routine) 230 { 231 SetupRoutine *generator = new SetupRoutine(state); 232 generator->generate(); 233 routine = generator->getRoutine(); 234 delete generator; 235 236 routineCache->add(state, routine); 237 } 238 239 return routine; 240 } 241 setRoutineCacheSize(int cacheSize)242 void SetupProcessor::setRoutineCacheSize(int cacheSize) 243 { 244 delete routineCache; 245 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0); 246 } 247 } 248