blob: b673dd72fc7425b04129388352e34923952e2a83 [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
34 for(int i = 0; i < sizeof(States) / 4; i++)
35 {
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
103 for(int interpolant = 0; interpolant < 11; interpolant++)
104 {
105 int componentCount = interpolant < 10 ? 4 : 1; // Fog only has one component
106
107 for(int component = 0; component < componentCount; component++)
108 {
109 state.gradient[interpolant][component].attribute = 0x3F;
110 state.gradient[interpolant][component].flat = false;
111 state.gradient[interpolant][component].wrap = false;
112 }
113 }
114
115 const bool point = context->isDrawPoint(true);
116 const bool sprite = context->pointSpriteActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400117 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
John Bauman89401822014-05-06 15:04:28 -0400118
119 if(context->vertexShader && context->pixelShader)
120 {
121 for(int interpolant = 0; interpolant < 10; interpolant++)
122 {
123 for(int component = 0; component < 4; component++)
124 {
125 int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
126
127 if(context->pixelShader->semantic[interpolant][component - project].active())
128 {
129 int input = interpolant;
130 for(int i = 0; i < 12; i++)
131 {
132 if(context->pixelShader->semantic[interpolant][component - project] == context->vertexShader->output[i][component - project])
133 {
134 input = i;
135 break;
136 }
137 }
138
139 bool flat = point;
140
141 switch(context->pixelShader->semantic[interpolant][component - project].usage)
142 {
John Bauman19bac1e2014-05-06 15:23:49 -0400143 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
144 case Shader::USAGE_COLOR: flat = flatShading; break;
John Bauman89401822014-05-06 15:04:28 -0400145 }
146
147 state.gradient[interpolant][component].attribute = input;
148 state.gradient[interpolant][component].flat = flat;
149 }
150 }
151 }
152 }
153 else if(context->preTransformed && context->pixelShader)
154 {
155 for(int interpolant = 0; interpolant < 10; interpolant++)
156 {
157 for(int component = 0; component < 4; component++)
158 {
159 int index = context->pixelShader->semantic[interpolant][component].index;
160
161 switch(context->pixelShader->semantic[interpolant][component].usage)
162 {
163 case 0xFF:
164 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400165 case Shader::USAGE_TEXCOORD:
John Bauman89401822014-05-06 15:04:28 -0400166 state.gradient[interpolant][component].attribute = T0 + index;
167 state.gradient[interpolant][component].flat = point && !sprite;
168 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400169 case Shader::USAGE_COLOR:
John Bauman89401822014-05-06 15:04:28 -0400170 state.gradient[interpolant][component].attribute = D0 + index;
171 state.gradient[interpolant][component].flat = flatShading;
172 break;
173 default:
174 ASSERT(false);
175 }
176 }
177 }
178 }
179 else if(context->pixelShaderVersion() < 0x0300)
180 {
181 for(int coordinate = 0; coordinate < 8; coordinate++)
182 {
183 for(int component = 0; component < 4; component++)
184 {
185 if(context->textureActive(coordinate, component))
186 {
187 state.texture[coordinate][component].attribute = T0 + coordinate;
188 state.texture[coordinate][component].flat = point && !sprite;
189 state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
190 }
191 }
192 }
193
194 for(int color = 0; color < 2; color++)
195 {
196 for(int component = 0; component < 4; component++)
197 {
198 if(context->colorActive(color, component))
199 {
200 state.color[color][component].attribute = D0 + color;
201 state.color[color][component].flat = flatShading;
202 }
203 }
204 }
205 }
206 else ASSERT(false);
207
208 if(context->fogActive())
209 {
210 state.fog.attribute = Fog;
211 state.fog.flat = point;
212 }
213
214 state.hash = state.computeHash();
215
216 return state;
217 }
218
219 Routine *SetupProcessor::routine(const State &state)
220 {
221 Routine *routine = routineCache->query(state);
222
223 if(!routine)
224 {
225 SetupRoutine *generator = new SetupRoutine(state);
226 generator->generate();
227 routine = generator->getRoutine();
228 delete generator;
229
230 routineCache->add(state, routine);
231 }
232
233 return routine;
234 }
235
236 void SetupProcessor::setRoutineCacheSize(int cacheSize)
237 {
238 delete routineCache;
John Bauman66b8ab22014-05-06 15:57:45 -0400239 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0);
John Bauman89401822014-05-06 15:04:28 -0400240 }
241}