blob: 6dccc8d79eaf3c683c2df07b1e68676adcb46ecd [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// 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.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "SetupProcessor.hpp"
16
17#include "SetupRoutine.hpp"
18#include "Primitive.hpp"
19#include "Polygon.hpp"
John Bauman89401822014-05-06 15:04:28 -040020#include "Context.hpp"
21#include "Renderer.hpp"
22#include "Constants.hpp"
23#include "Debug.hpp"
24
25namespace sw
26{
27 extern bool complementaryDepthBuffer;
John Bauman19bac1e2014-05-06 15:23:49 -040028 extern bool fullPixelPositionRegister;
John Bauman89401822014-05-06 15:04:28 -040029
John Bauman66b8ab22014-05-06 15:57:45 -040030 bool precacheSetup = false;
31
John Bauman89401822014-05-06 15:04:28 -040032 unsigned int SetupProcessor::States::computeHash()
33 {
34 unsigned int *state = (unsigned int*)this;
35 unsigned int hash = 0;
36
Nicolas Capens5d961882016-01-01 23:18:14 -050037 for(unsigned int i = 0; i < sizeof(States) / 4; i++)
John Bauman89401822014-05-06 15:04:28 -040038 {
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
John Bauman19bac1e2014-05-06 15:23:49 -040076 bool vPosZW = (context->pixelShader && context->pixelShader->vPosDeclared && fullPixelPositionRegister);
77
John Bauman89401822014-05-06 15:04:28 -040078 state.isDrawPoint = context->isDrawPoint(true);
79 state.isDrawLine = context->isDrawLine(true);
80 state.isDrawTriangle = context->isDrawTriangle(false);
81 state.isDrawSolidTriangle = context->isDrawTriangle(true);
Nicolas Capensa0f4be82014-10-22 14:35:30 -040082 state.interpolateZ = context->depthBufferActive() || context->pixelFogActive() != FOG_NONE || vPosZW;
John Bauman19bac1e2014-05-06 15:23:49 -040083 state.interpolateW = context->perspectiveActive() || vPosZW;
John Bauman89401822014-05-06 15:04:28 -040084 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;
Nicolas Capensec0936c2016-05-18 12:32:02 -040092 state.pointSizeRegister = Unused;
John Bauman89401822014-05-06 15:04:28 -040093
John Bauman66b8ab22014-05-06 15:57:45 -040094 state.multiSample = context->getMultiSampleCount();
Alexis Hetub0f247f2016-02-22 11:42:39 -050095 state.rasterizerDiscard = context->rasterizerDiscard;
John Bauman89401822014-05-06 15:04:28 -040096
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
Nicolas Capens66be2452015-01-27 14:58:57 -0500107 for(int interpolant = 0; interpolant < 10; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400108 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500109 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400110 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500111 state.gradient[interpolant][component].attribute = Unused;
John Bauman89401822014-05-06 15:04:28 -0400112 state.gradient[interpolant][component].flat = false;
113 state.gradient[interpolant][component].wrap = false;
114 }
115 }
116
Nicolas Capens66be2452015-01-27 14:58:57 -0500117 state.fog.attribute = Unused;
118 state.fog.flat = false;
119 state.fog.wrap = false;
120
John Bauman89401822014-05-06 15:04:28 -0400121 const bool point = context->isDrawPoint(true);
122 const bool sprite = context->pointSpriteActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400123 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
John Bauman89401822014-05-06 15:04:28 -0400124
125 if(context->vertexShader && context->pixelShader)
126 {
127 for(int interpolant = 0; interpolant < 10; 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;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400136 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400137 {
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 {
John Bauman19bac1e2014-05-06 15:23:49 -0400149 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
150 case Shader::USAGE_COLOR: flat = flatShading; break;
John Bauman89401822014-05-06 15:04:28 -0400151 }
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 < 10; 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;
John Bauman19bac1e2014-05-06 15:23:49 -0400171 case Shader::USAGE_TEXCOORD:
John Bauman89401822014-05-06 15:04:28 -0400172 state.gradient[interpolant][component].attribute = T0 + index;
173 state.gradient[interpolant][component].flat = point && !sprite;
174 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400175 case Shader::USAGE_COLOR:
Nicolas Capens995ddea2016-05-17 11:48:56 -0400176 state.gradient[interpolant][component].attribute = C0 + index;
John Bauman89401822014-05-06 15:04:28 -0400177 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 {
Nicolas Capens995ddea2016-05-17 11:48:56 -0400206 state.color[color][component].attribute = C0 + color;
John Bauman89401822014-05-06 15:04:28 -0400207 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
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
242 void SetupProcessor::setRoutineCacheSize(int cacheSize)
243 {
244 delete routineCache;
John Bauman66b8ab22014-05-06 15:57:45 -0400245 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0);
John Bauman89401822014-05-06 15:04:28 -0400246 }
247}