blob: 34b11be6ea91a90ab4c991c78d459ec9415c9060 [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001// SwiftShader Software Renderer
2//
John Bauman19bac1e2014-05-06 15:23:49 -04003// Copyright(c) 2005-2012 TransGaming Inc.
John Bauman89401822014-05-06 15:04:28 -04004//
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"
John Bauman89401822014-05-06 15:04:28 -040017#include "Context.hpp"
18#include "Renderer.hpp"
19#include "Constants.hpp"
20#include "Debug.hpp"
21
22namespace sw
23{
24 extern bool complementaryDepthBuffer;
John Bauman19bac1e2014-05-06 15:23:49 -040025 extern bool fullPixelPositionRegister;
John Bauman89401822014-05-06 15:04:28 -040026
John Bauman66b8ab22014-05-06 15:57:45 -040027 bool precacheSetup = false;
28
John Bauman89401822014-05-06 15:04:28 -040029 unsigned int SetupProcessor::States::computeHash()
30 {
31 unsigned int *state = (unsigned int*)this;
32 unsigned int hash = 0;
33
Nicolas Capens5d961882016-01-01 23:18:14 -050034 for(unsigned int i = 0; i < sizeof(States) / 4; i++)
John Bauman89401822014-05-06 15:04:28 -040035 {
36 hash ^= state[i];
37 }
38
39 return hash;
40 }
41
42 SetupProcessor::State::State(int i)
43 {
44 memset(this, 0, sizeof(State));
45 }
46
47 bool SetupProcessor::State::operator==(const State &state) const
48 {
49 if(hash != state.hash)
50 {
51 return false;
52 }
53
54 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
55 }
56
57 SetupProcessor::SetupProcessor(Context *context) : context(context)
58 {
59 routineCache = 0;
60 setRoutineCacheSize(1024);
61 }
62
63 SetupProcessor::~SetupProcessor()
64 {
65 delete routineCache;
66 routineCache = 0;
67 }
68
69 SetupProcessor::State SetupProcessor::update() const
70 {
71 State state;
72
John Bauman19bac1e2014-05-06 15:23:49 -040073 bool vPosZW = (context->pixelShader && context->pixelShader->vPosDeclared && fullPixelPositionRegister);
74
John Bauman89401822014-05-06 15:04:28 -040075 state.isDrawPoint = context->isDrawPoint(true);
76 state.isDrawLine = context->isDrawLine(true);
77 state.isDrawTriangle = context->isDrawTriangle(false);
78 state.isDrawSolidTriangle = context->isDrawTriangle(true);
Nicolas Capensa0f4be82014-10-22 14:35:30 -040079 state.interpolateZ = context->depthBufferActive() || context->pixelFogActive() != FOG_NONE || vPosZW;
John Bauman19bac1e2014-05-06 15:23:49 -040080 state.interpolateW = context->perspectiveActive() || vPosZW;
John Bauman89401822014-05-06 15:04:28 -040081 state.perspective = context->perspectiveActive();
82 state.pointSprite = context->pointSpriteActive();
83 state.cullMode = context->cullMode;
84 state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
85 state.slopeDepthBias = slopeDepthBias != 0.0f;
86 state.vFace = context->pixelShader && context->pixelShader->vFaceDeclared;
87
88 state.positionRegister = Pos;
89 state.pointSizeRegister = 0xF; // No vertex point size
90
John Bauman66b8ab22014-05-06 15:57:45 -040091 state.multiSample = context->getMultiSampleCount();
John Bauman89401822014-05-06 15:04:28 -040092
93 if(context->vertexShader)
94 {
95 state.positionRegister = context->vertexShader->positionRegister;
96 state.pointSizeRegister = context->vertexShader->pointSizeRegister;
97 }
98 else if(context->pointSizeActive())
99 {
100 state.pointSizeRegister = Pts;
101 }
102
Nicolas Capens66be2452015-01-27 14:58:57 -0500103 for(int interpolant = 0; interpolant < 10; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400104 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500105 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400106 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500107 state.gradient[interpolant][component].attribute = Unused;
John Bauman89401822014-05-06 15:04:28 -0400108 state.gradient[interpolant][component].flat = false;
109 state.gradient[interpolant][component].wrap = false;
110 }
111 }
112
Nicolas Capens66be2452015-01-27 14:58:57 -0500113 state.fog.attribute = Unused;
114 state.fog.flat = false;
115 state.fog.wrap = false;
116
John Bauman89401822014-05-06 15:04:28 -0400117 const bool point = context->isDrawPoint(true);
118 const bool sprite = context->pointSpriteActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400119 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
John Bauman89401822014-05-06 15:04:28 -0400120
121 if(context->vertexShader && context->pixelShader)
122 {
123 for(int interpolant = 0; interpolant < 10; interpolant++)
124 {
125 for(int component = 0; component < 4; component++)
126 {
127 int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
128
129 if(context->pixelShader->semantic[interpolant][component - project].active())
130 {
131 int input = interpolant;
132 for(int i = 0; i < 12; i++)
133 {
134 if(context->pixelShader->semantic[interpolant][component - project] == context->vertexShader->output[i][component - project])
135 {
136 input = i;
137 break;
138 }
139 }
140
141 bool flat = point;
142
143 switch(context->pixelShader->semantic[interpolant][component - project].usage)
144 {
John Bauman19bac1e2014-05-06 15:23:49 -0400145 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
146 case Shader::USAGE_COLOR: flat = flatShading; break;
John Bauman89401822014-05-06 15:04:28 -0400147 }
148
149 state.gradient[interpolant][component].attribute = input;
150 state.gradient[interpolant][component].flat = flat;
151 }
152 }
153 }
154 }
155 else if(context->preTransformed && context->pixelShader)
156 {
157 for(int interpolant = 0; interpolant < 10; interpolant++)
158 {
159 for(int component = 0; component < 4; component++)
160 {
161 int index = context->pixelShader->semantic[interpolant][component].index;
162
163 switch(context->pixelShader->semantic[interpolant][component].usage)
164 {
165 case 0xFF:
166 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400167 case Shader::USAGE_TEXCOORD:
John Bauman89401822014-05-06 15:04:28 -0400168 state.gradient[interpolant][component].attribute = T0 + index;
169 state.gradient[interpolant][component].flat = point && !sprite;
170 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400171 case Shader::USAGE_COLOR:
John Bauman89401822014-05-06 15:04:28 -0400172 state.gradient[interpolant][component].attribute = D0 + index;
173 state.gradient[interpolant][component].flat = flatShading;
174 break;
175 default:
176 ASSERT(false);
177 }
178 }
179 }
180 }
181 else if(context->pixelShaderVersion() < 0x0300)
182 {
183 for(int coordinate = 0; coordinate < 8; coordinate++)
184 {
185 for(int component = 0; component < 4; component++)
186 {
187 if(context->textureActive(coordinate, component))
188 {
189 state.texture[coordinate][component].attribute = T0 + coordinate;
190 state.texture[coordinate][component].flat = point && !sprite;
191 state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
192 }
193 }
194 }
195
196 for(int color = 0; color < 2; color++)
197 {
198 for(int component = 0; component < 4; component++)
199 {
200 if(context->colorActive(color, component))
201 {
202 state.color[color][component].attribute = D0 + color;
203 state.color[color][component].flat = flatShading;
204 }
205 }
206 }
207 }
208 else ASSERT(false);
209
210 if(context->fogActive())
211 {
212 state.fog.attribute = Fog;
213 state.fog.flat = point;
214 }
215
216 state.hash = state.computeHash();
217
218 return state;
219 }
220
221 Routine *SetupProcessor::routine(const State &state)
222 {
223 Routine *routine = routineCache->query(state);
224
225 if(!routine)
226 {
227 SetupRoutine *generator = new SetupRoutine(state);
228 generator->generate();
229 routine = generator->getRoutine();
230 delete generator;
231
232 routineCache->add(state, routine);
233 }
234
235 return routine;
236 }
237
238 void SetupProcessor::setRoutineCacheSize(int cacheSize)
239 {
240 delete routineCache;
John Bauman66b8ab22014-05-06 15:57:45 -0400241 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0);
John Bauman89401822014-05-06 15:04:28 -0400242 }
243}