blob: 775564e4490b3c5d5c30c3327e47557575013912 [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
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 {
John Bauman19bac1e2014-05-06 15:23:49 -040057 precacheDLL = 0;
John Bauman89401822014-05-06 15:04:28 -040058 routineCache = 0;
59 setRoutineCacheSize(1024);
60 }
61
62 SetupProcessor::~SetupProcessor()
63 {
64 delete routineCache;
65 routineCache = 0;
66 }
67
68 SetupProcessor::State SetupProcessor::update() const
69 {
70 State state;
71
John Bauman19bac1e2014-05-06 15:23:49 -040072 bool vPosZW = (context->pixelShader && context->pixelShader->vPosDeclared && fullPixelPositionRegister);
73
John Bauman89401822014-05-06 15:04:28 -040074 state.isDrawPoint = context->isDrawPoint(true);
75 state.isDrawLine = context->isDrawLine(true);
76 state.isDrawTriangle = context->isDrawTriangle(false);
77 state.isDrawSolidTriangle = context->isDrawTriangle(true);
John Bauman19bac1e2014-05-06 15:23:49 -040078 state.interpolateZ = context->depthBufferActive() || context->pixelFogActive() != Context::FOG_NONE || vPosZW;
79 state.interpolateW = context->perspectiveActive() || vPosZW;
John Bauman89401822014-05-06 15:04:28 -040080 state.perspective = context->perspectiveActive();
81 state.pointSprite = context->pointSpriteActive();
82 state.cullMode = context->cullMode;
83 state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
84 state.slopeDepthBias = slopeDepthBias != 0.0f;
85 state.vFace = context->pixelShader && context->pixelShader->vFaceDeclared;
86
87 state.positionRegister = Pos;
88 state.pointSizeRegister = 0xF; // No vertex point size
89
90 state.multiSample = context->renderTarget[0]->getMultiSampleCount();
91
92 if(context->vertexShader)
93 {
94 state.positionRegister = context->vertexShader->positionRegister;
95 state.pointSizeRegister = context->vertexShader->pointSizeRegister;
96 }
97 else if(context->pointSizeActive())
98 {
99 state.pointSizeRegister = Pts;
100 }
101
102 for(int interpolant = 0; interpolant < 11; interpolant++)
103 {
104 int componentCount = interpolant < 10 ? 4 : 1; // Fog only has one component
105
106 for(int component = 0; component < componentCount; component++)
107 {
108 state.gradient[interpolant][component].attribute = 0x3F;
109 state.gradient[interpolant][component].flat = false;
110 state.gradient[interpolant][component].wrap = false;
111 }
112 }
113
114 const bool point = context->isDrawPoint(true);
115 const bool sprite = context->pointSpriteActive();
116 const bool flatShading = (context->shadingMode == Context::SHADING_FLAT) || point;
117
118 if(context->vertexShader && context->pixelShader)
119 {
120 for(int interpolant = 0; interpolant < 10; interpolant++)
121 {
122 for(int component = 0; component < 4; component++)
123 {
124 int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
125
126 if(context->pixelShader->semantic[interpolant][component - project].active())
127 {
128 int input = interpolant;
129 for(int i = 0; i < 12; i++)
130 {
131 if(context->pixelShader->semantic[interpolant][component - project] == context->vertexShader->output[i][component - project])
132 {
133 input = i;
134 break;
135 }
136 }
137
138 bool flat = point;
139
140 switch(context->pixelShader->semantic[interpolant][component - project].usage)
141 {
John Bauman19bac1e2014-05-06 15:23:49 -0400142 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
143 case Shader::USAGE_COLOR: flat = flatShading; break;
John Bauman89401822014-05-06 15:04:28 -0400144 }
145
146 state.gradient[interpolant][component].attribute = input;
147 state.gradient[interpolant][component].flat = flat;
148 }
149 }
150 }
151 }
152 else if(context->preTransformed && context->pixelShader)
153 {
154 for(int interpolant = 0; interpolant < 10; interpolant++)
155 {
156 for(int component = 0; component < 4; component++)
157 {
158 int index = context->pixelShader->semantic[interpolant][component].index;
159
160 switch(context->pixelShader->semantic[interpolant][component].usage)
161 {
162 case 0xFF:
163 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400164 case Shader::USAGE_TEXCOORD:
John Bauman89401822014-05-06 15:04:28 -0400165 state.gradient[interpolant][component].attribute = T0 + index;
166 state.gradient[interpolant][component].flat = point && !sprite;
167 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400168 case Shader::USAGE_COLOR:
John Bauman89401822014-05-06 15:04:28 -0400169 state.gradient[interpolant][component].attribute = D0 + index;
170 state.gradient[interpolant][component].flat = flatShading;
171 break;
172 default:
173 ASSERT(false);
174 }
175 }
176 }
177 }
178 else if(context->pixelShaderVersion() < 0x0300)
179 {
180 for(int coordinate = 0; coordinate < 8; coordinate++)
181 {
182 for(int component = 0; component < 4; component++)
183 {
184 if(context->textureActive(coordinate, component))
185 {
186 state.texture[coordinate][component].attribute = T0 + coordinate;
187 state.texture[coordinate][component].flat = point && !sprite;
188 state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
189 }
190 }
191 }
192
193 for(int color = 0; color < 2; color++)
194 {
195 for(int component = 0; component < 4; component++)
196 {
197 if(context->colorActive(color, component))
198 {
199 state.color[color][component].attribute = D0 + color;
200 state.color[color][component].flat = flatShading;
201 }
202 }
203 }
204 }
205 else ASSERT(false);
206
207 if(context->fogActive())
208 {
209 state.fog.attribute = Fog;
210 state.fog.flat = point;
211 }
212
213 state.hash = state.computeHash();
214
215 return state;
216 }
217
218 Routine *SetupProcessor::routine(const State &state)
219 {
220 Routine *routine = routineCache->query(state);
221
222 if(!routine)
223 {
224 SetupRoutine *generator = new SetupRoutine(state);
225 generator->generate();
226 routine = generator->getRoutine();
227 delete generator;
228
229 routineCache->add(state, routine);
230 }
231
232 return routine;
233 }
234
235 void SetupProcessor::setRoutineCacheSize(int cacheSize)
236 {
237 delete routineCache;
238 routineCache = new LRUCache<State, Routine>(clamp(cacheSize, 1, 65536));
239 }
240}