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