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 "SetupRoutine.hpp"
18 #include "Primitive.hpp"
19 #include "Polygon.hpp"
20 #include "Context.hpp"
21 #include "Renderer.hpp"
22 #include "Constants.hpp"
23 #include "Debug.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 = 0;
63 		setRoutineCacheSize(1024);
64 	}
65 
~SetupProcessor()66 	SetupProcessor::~SetupProcessor()
67 	{
68 		delete routineCache;
69 		routineCache = 0;
70 	}
71 
update() const72 	SetupProcessor::State SetupProcessor::update() const
73 	{
74 		State state;
75 
76 		bool vPosZW = (context->pixelShader && context->pixelShader->vPosDeclared && 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 = slopeDepthBias != 0.0f;
89 		state.vFace = context->pixelShader && context->pixelShader->vFaceDeclared;
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->positionRegister;
100 			state.pointSizeRegister = context->vertexShader->pointSizeRegister;
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 
133 					if(context->pixelShader->semantic[interpolant][component - project].active())
134 					{
135 						int input = interpolant;
136 						for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
137 						{
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 						{
149 						case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
150 						case Shader::USAGE_COLOR:    flat = flatShading;      break;
151 						}
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 < MAX_FRAGMENT_INPUTS; 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;
171 					case Shader::USAGE_TEXCOORD:
172 						state.gradient[interpolant][component].attribute = T0 + index;
173 						state.gradient[interpolant][component].flat = point && !sprite;
174 						break;
175 					case Shader::USAGE_COLOR:
176 						state.gradient[interpolant][component].attribute = C0 + index;
177 						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 					{
206 						state.color[color][component].attribute = C0 + color;
207 						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 
routine(const State & state)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 
setRoutineCacheSize(int cacheSize)242 	void SetupProcessor::setRoutineCacheSize(int cacheSize)
243 	{
244 		delete routineCache;
245 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0);
246 	}
247 }
248