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 "Primitive.hpp" 18 #include "Polygon.hpp" 19 #include "Context.hpp" 20 #include "Renderer.hpp" 21 #include "Shader/SetupRoutine.hpp" 22 #include "Shader/Constants.hpp" 23 #include "Common/Debug.hpp" 24 25 namespace sw 26 { 27 extern bool complementaryDepthBuffer; 28 extern bool fullPixelPositionRegister; 29 30 bool precacheSetup = false; 31 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 45 SetupProcessor::State::State(int i) 46 { 47 memset(this, 0, sizeof(State)); 48 } 49 50 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 60 SetupProcessor::SetupProcessor(Context *context) : context(context) 61 { 62 routineCache = 0; 63 setRoutineCacheSize(1024); 64 } 65 66 SetupProcessor::~SetupProcessor() 67 { 68 delete routineCache; 69 routineCache = 0; 70 } 71 72 SetupProcessor::State SetupProcessor::update() const 73 { 74 State state; 75 76 bool vPosZW = (context->pixelShader && context->pixelShader->isVPosDeclared() && 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 = context->slopeDepthBias != 0.0f; 89 state.vFace = context->pixelShader && context->pixelShader->isVFaceDeclared(); 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->getPositionRegister(); 100 state.pointSizeRegister = context->vertexShader->getPointSizeRegister(); 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 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component - project); 133 134 if(semantic.active()) 135 { 136 int input = interpolant; 137 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++) 138 { 139 if(semantic == context->vertexShader->getOutput(i, component - project)) 140 { 141 input = i; 142 break; 143 } 144 } 145 146 bool flat = point; 147 148 switch(semantic.usage) 149 { 150 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break; 151 case Shader::USAGE_COLOR: flat = semantic.flat || flatShading; break; 152 } 153 154 state.gradient[interpolant][component].attribute = input; 155 state.gradient[interpolant][component].flat = flat; 156 } 157 } 158 } 159 } 160 else if(context->preTransformed && context->pixelShader) 161 { 162 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) 163 { 164 for(int component = 0; component < 4; component++) 165 { 166 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component); 167 168 switch(semantic.usage) 169 { 170 case 0xFF: 171 break; 172 case Shader::USAGE_TEXCOORD: 173 state.gradient[interpolant][component].attribute = T0 + semantic.index; 174 state.gradient[interpolant][component].flat = semantic.flat || (point && !sprite); 175 break; 176 case Shader::USAGE_COLOR: 177 state.gradient[interpolant][component].attribute = C0 + semantic.index; 178 state.gradient[interpolant][component].flat = semantic.flat || flatShading; 179 break; 180 default: 181 ASSERT(false); 182 } 183 } 184 } 185 } 186 else if(context->pixelShaderModel() < 0x0300) 187 { 188 for(int coordinate = 0; coordinate < 8; coordinate++) 189 { 190 for(int component = 0; component < 4; component++) 191 { 192 if(context->textureActive(coordinate, component)) 193 { 194 state.texture[coordinate][component].attribute = T0 + coordinate; 195 state.texture[coordinate][component].flat = point && !sprite; 196 state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0; 197 } 198 } 199 } 200 201 for(int color = 0; color < 2; color++) 202 { 203 for(int component = 0; component < 4; component++) 204 { 205 if(context->colorActive(color, component)) 206 { 207 state.color[color][component].attribute = C0 + color; 208 state.color[color][component].flat = flatShading; 209 } 210 } 211 } 212 } 213 else ASSERT(false); 214 215 if(context->fogActive()) 216 { 217 state.fog.attribute = Fog; 218 state.fog.flat = point; 219 } 220 221 state.hash = state.computeHash(); 222 223 return state; 224 } 225 226 Routine *SetupProcessor::routine(const State &state) 227 { 228 Routine *routine = routineCache->query(state); 229 230 if(!routine) 231 { 232 SetupRoutine *generator = new SetupRoutine(state); 233 generator->generate(); 234 routine = generator->getRoutine(); 235 delete generator; 236 237 routineCache->add(state, routine); 238 } 239 240 return routine; 241 } 242 243 void SetupProcessor::setRoutineCacheSize(int cacheSize) 244 { 245 delete routineCache; 246 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0); 247 } 248 } 249