1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "SetupProcessor.hpp"
17 #include "SetupRoutine.hpp"
18 #include "Primitive.hpp"
19 #include "Polygon.hpp"
20 #include "Context.hpp"
21 #include "Renderer.hpp"
22 #include "Constants.hpp"
27 extern bool complementaryDepthBuffer;
28 extern bool fullPixelPositionRegister;
30 bool precacheSetup = false;
32 unsigned int SetupProcessor::States::computeHash()
34 unsigned int *state = (unsigned int*)this;
35 unsigned int hash = 0;
37 for(unsigned int i = 0; i < sizeof(States) / 4; i++)
45 SetupProcessor::State::State(int i)
47 memset(this, 0, sizeof(State));
50 bool SetupProcessor::State::operator==(const State &state) const
52 if(hash != state.hash)
57 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
60 SetupProcessor::SetupProcessor(Context *context) : context(context)
63 setRoutineCacheSize(1024);
66 SetupProcessor::~SetupProcessor()
72 SetupProcessor::State SetupProcessor::update() const
76 bool vPosZW = (context->pixelShader && context->pixelShader->isVPosDeclared() && fullPixelPositionRegister);
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->isVFaceDeclared();
91 state.positionRegister = Pos;
92 state.pointSizeRegister = Unused;
94 state.multiSample = context->getMultiSampleCount();
95 state.rasterizerDiscard = context->rasterizerDiscard;
97 if(context->vertexShader)
99 state.positionRegister = context->vertexShader->getPositionRegister();
100 state.pointSizeRegister = context->vertexShader->getPointSizeRegister();
102 else if(context->pointSizeActive())
104 state.pointSizeRegister = Pts;
107 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
109 for(int component = 0; component < 4; component++)
111 state.gradient[interpolant][component].attribute = Unused;
112 state.gradient[interpolant][component].flat = false;
113 state.gradient[interpolant][component].wrap = false;
117 state.fog.attribute = Unused;
118 state.fog.flat = false;
119 state.fog.wrap = false;
121 const bool point = context->isDrawPoint(true);
122 const bool sprite = context->pointSpriteActive();
123 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
125 if(context->vertexShader && context->pixelShader)
127 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
129 for(int component = 0; component < 4; component++)
131 int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
132 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component - project);
134 if(semantic.active())
136 int input = interpolant;
137 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
139 if(semantic == context->vertexShader->getOutput(i, component - project))
148 switch(semantic.usage)
150 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
151 case Shader::USAGE_COLOR: flat = semantic.flat || flatShading; break;
154 state.gradient[interpolant][component].attribute = input;
155 state.gradient[interpolant][component].flat = flat;
160 else if(context->preTransformed && context->pixelShader)
162 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
164 for(int component = 0; component < 4; component++)
166 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
168 switch(semantic.usage)
172 case Shader::USAGE_TEXCOORD:
173 state.gradient[interpolant][component].attribute = T0 + semantic.index;
174 state.gradient[interpolant][component].flat = semantic.flat || (point && !sprite);
176 case Shader::USAGE_COLOR:
177 state.gradient[interpolant][component].attribute = C0 + semantic.index;
178 state.gradient[interpolant][component].flat = semantic.flat || flatShading;
186 else if(context->pixelShaderVersion() < 0x0300)
188 for(int coordinate = 0; coordinate < 8; coordinate++)
190 for(int component = 0; component < 4; component++)
192 if(context->textureActive(coordinate, component))
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;
201 for(int color = 0; color < 2; color++)
203 for(int component = 0; component < 4; component++)
205 if(context->colorActive(color, component))
207 state.color[color][component].attribute = C0 + color;
208 state.color[color][component].flat = flatShading;
215 if(context->fogActive())
217 state.fog.attribute = Fog;
218 state.fog.flat = point;
221 state.hash = state.computeHash();
226 Routine *SetupProcessor::routine(const State &state)
228 Routine *routine = routineCache->query(state);
232 SetupRoutine *generator = new SetupRoutine(state);
233 generator->generate();
234 routine = generator->getRoutine();
237 routineCache->add(state, routine);
243 void SetupProcessor::setRoutineCacheSize(int cacheSize)
246 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0);