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 "Pipeline/SetupRoutine.hpp" 22 #include "Pipeline/Constants.hpp" 23 #include "Vulkan/VkDebug.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 = nullptr; 63 setRoutineCacheSize(1024); 64 } 65 ~SetupProcessor()66 SetupProcessor::~SetupProcessor() 67 { 68 delete routineCache; 69 routineCache = nullptr; 70 } 71 update() const72 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(); 79 state.isDrawLine = context->isDrawLine(); 80 state.isDrawTriangle = context->isDrawTriangle(); 81 state.interpolateZ = context->depthBufferActive() || vPosZW; 82 state.interpolateW = context->perspectiveActive() || vPosZW; 83 state.perspective = context->perspectiveActive(); 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 state.positionRegister = context->vertexShader->getPositionRegister(); 96 state.pointSizeRegister = context->vertexShader->getPointSizeRegister(); 97 98 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) 99 { 100 for(int component = 0; component < 4; component++) 101 { 102 state.gradient[interpolant][component].attribute = Unused; 103 state.gradient[interpolant][component].flat = false; 104 state.gradient[interpolant][component].wrap = false; 105 } 106 } 107 108 const bool point = context->isDrawPoint(); 109 110 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) 111 { 112 for(int component = 0; component < 4; component++) 113 { 114 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component); 115 116 if(semantic.active()) 117 { 118 int input = interpolant; 119 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++) 120 { 121 if(semantic == context->vertexShader->getOutput(i, component)) 122 { 123 input = i; 124 break; 125 } 126 } 127 128 bool flat = point; 129 130 switch(semantic.usage) 131 { 132 case Shader::USAGE_TEXCOORD: flat = false; break; 133 case Shader::USAGE_COLOR: flat = semantic.flat || point; break; 134 } 135 136 state.gradient[interpolant][component].attribute = input; 137 state.gradient[interpolant][component].flat = flat; 138 } 139 } 140 } 141 142 state.hash = state.computeHash(); 143 144 return state; 145 } 146 routine(const State & state)147 Routine *SetupProcessor::routine(const State &state) 148 { 149 Routine *routine = routineCache->query(state); 150 151 if(!routine) 152 { 153 SetupRoutine *generator = new SetupRoutine(state); 154 generator->generate(); 155 routine = generator->getRoutine(); 156 delete generator; 157 158 routineCache->add(state, routine); 159 } 160 161 return routine; 162 } 163 setRoutineCacheSize(int cacheSize)164 void SetupProcessor::setRoutineCacheSize(int cacheSize) 165 { 166 delete routineCache; 167 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0); 168 } 169 } 170