blob: 1e737a4764d0df31ead0538c108bcc0f69b2b709 [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
3// Copyright(c) 2005-2011 TransGaming Inc.
4//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11
12#include "SetupProcessor.hpp"
13
14#include "SetupRoutine.hpp"
15#include "Primitive.hpp"
16#include "Polygon.hpp"
17#include "Viewport.hpp"
18#include "Context.hpp"
19#include "Renderer.hpp"
20#include "Constants.hpp"
21#include "Debug.hpp"
22
23namespace sw
24{
25 extern bool complementaryDepthBuffer;
26
27 unsigned int SetupProcessor::States::computeHash()
28 {
29 unsigned int *state = (unsigned int*)this;
30 unsigned int hash = 0;
31
32 for(int i = 0; i < sizeof(States) / 4; i++)
33 {
34 hash ^= state[i];
35 }
36
37 return hash;
38 }
39
40 SetupProcessor::State::State(int i)
41 {
42 memset(this, 0, sizeof(State));
43 }
44
45 bool SetupProcessor::State::operator==(const State &state) const
46 {
47 if(hash != state.hash)
48 {
49 return false;
50 }
51
52 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
53 }
54
55 SetupProcessor::SetupProcessor(Context *context) : context(context)
56 {
57 routineCache = 0;
58 setRoutineCacheSize(1024);
59 }
60
61 SetupProcessor::~SetupProcessor()
62 {
63 delete routineCache;
64 routineCache = 0;
65 }
66
67 SetupProcessor::State SetupProcessor::update() const
68 {
69 State state;
70
71 state.isDrawPoint = context->isDrawPoint(true);
72 state.isDrawLine = context->isDrawLine(true);
73 state.isDrawTriangle = context->isDrawTriangle(false);
74 state.isDrawSolidTriangle = context->isDrawTriangle(true);
75 state.interpolateDepth = context->depthBufferActive() || context->pixelFogActive() != Context::FOG_NONE;
76 state.perspective = context->perspectiveActive();
77 state.pointSprite = context->pointSpriteActive();
78 state.cullMode = context->cullMode;
79 state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
80 state.slopeDepthBias = slopeDepthBias != 0.0f;
81 state.vFace = context->pixelShader && context->pixelShader->vFaceDeclared;
82
83 state.positionRegister = Pos;
84 state.pointSizeRegister = 0xF; // No vertex point size
85
86 state.multiSample = context->renderTarget[0]->getMultiSampleCount();
87
88 if(context->vertexShader)
89 {
90 state.positionRegister = context->vertexShader->positionRegister;
91 state.pointSizeRegister = context->vertexShader->pointSizeRegister;
92 }
93 else if(context->pointSizeActive())
94 {
95 state.pointSizeRegister = Pts;
96 }
97
98 for(int interpolant = 0; interpolant < 11; interpolant++)
99 {
100 int componentCount = interpolant < 10 ? 4 : 1; // Fog only has one component
101
102 for(int component = 0; component < componentCount; component++)
103 {
104 state.gradient[interpolant][component].attribute = 0x3F;
105 state.gradient[interpolant][component].flat = false;
106 state.gradient[interpolant][component].wrap = false;
107 }
108 }
109
110 const bool point = context->isDrawPoint(true);
111 const bool sprite = context->pointSpriteActive();
112 const bool flatShading = (context->shadingMode == Context::SHADING_FLAT) || point;
113
114 if(context->vertexShader && context->pixelShader)
115 {
116 for(int interpolant = 0; interpolant < 10; interpolant++)
117 {
118 for(int component = 0; component < 4; component++)
119 {
120 int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
121
122 if(context->pixelShader->semantic[interpolant][component - project].active())
123 {
124 int input = interpolant;
125 for(int i = 0; i < 12; i++)
126 {
127 if(context->pixelShader->semantic[interpolant][component - project] == context->vertexShader->output[i][component - project])
128 {
129 input = i;
130 break;
131 }
132 }
133
134 bool flat = point;
135
136 switch(context->pixelShader->semantic[interpolant][component - project].usage)
137 {
138 case ShaderOperation::USAGE_TEXCOORD: flat = point && !sprite; break;
139 case ShaderOperation::USAGE_COLOR: flat = flatShading; break;
140 }
141
142 state.gradient[interpolant][component].attribute = input;
143 state.gradient[interpolant][component].flat = flat;
144 }
145 }
146 }
147 }
148 else if(context->preTransformed && context->pixelShader)
149 {
150 for(int interpolant = 0; interpolant < 10; interpolant++)
151 {
152 for(int component = 0; component < 4; component++)
153 {
154 int index = context->pixelShader->semantic[interpolant][component].index;
155
156 switch(context->pixelShader->semantic[interpolant][component].usage)
157 {
158 case 0xFF:
159 break;
160 case ShaderOperation::USAGE_TEXCOORD:
161 state.gradient[interpolant][component].attribute = T0 + index;
162 state.gradient[interpolant][component].flat = point && !sprite;
163 break;
164 case ShaderOperation::USAGE_COLOR:
165 state.gradient[interpolant][component].attribute = D0 + index;
166 state.gradient[interpolant][component].flat = flatShading;
167 break;
168 default:
169 ASSERT(false);
170 }
171 }
172 }
173 }
174 else if(context->pixelShaderVersion() < 0x0300)
175 {
176 for(int coordinate = 0; coordinate < 8; coordinate++)
177 {
178 for(int component = 0; component < 4; component++)
179 {
180 if(context->textureActive(coordinate, component))
181 {
182 state.texture[coordinate][component].attribute = T0 + coordinate;
183 state.texture[coordinate][component].flat = point && !sprite;
184 state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
185 }
186 }
187 }
188
189 for(int color = 0; color < 2; color++)
190 {
191 for(int component = 0; component < 4; component++)
192 {
193 if(context->colorActive(color, component))
194 {
195 state.color[color][component].attribute = D0 + color;
196 state.color[color][component].flat = flatShading;
197 }
198 }
199 }
200 }
201 else ASSERT(false);
202
203 if(context->fogActive())
204 {
205 state.fog.attribute = Fog;
206 state.fog.flat = point;
207 }
208
209 state.hash = state.computeHash();
210
211 return state;
212 }
213
214 Routine *SetupProcessor::routine(const State &state)
215 {
216 Routine *routine = routineCache->query(state);
217
218 if(!routine)
219 {
220 SetupRoutine *generator = new SetupRoutine(state);
221 generator->generate();
222 routine = generator->getRoutine();
223 delete generator;
224
225 routineCache->add(state, routine);
226 }
227
228 return routine;
229 }
230
231 void SetupProcessor::setRoutineCacheSize(int cacheSize)
232 {
233 delete routineCache;
234 routineCache = new LRUCache<State, Routine>(clamp(cacheSize, 1, 65536));
235 }
236}