blob: 721140626608816e1884da276e14e59a1687d816 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// 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.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "SetupProcessor.hpp"
16
John Bauman89401822014-05-06 15:04:28 -040017#include "Primitive.hpp"
18#include "Polygon.hpp"
John Bauman89401822014-05-06 15:04:28 -040019#include "Context.hpp"
20#include "Renderer.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040021#include "Shader/SetupRoutine.hpp"
22#include "Shader/Constants.hpp"
23#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040024
25namespace sw
26{
27 extern bool complementaryDepthBuffer;
John Bauman19bac1e2014-05-06 15:23:49 -040028 extern bool fullPixelPositionRegister;
John Bauman89401822014-05-06 15:04:28 -040029
John Bauman66b8ab22014-05-06 15:57:45 -040030 bool precacheSetup = false;
31
John Bauman89401822014-05-06 15:04:28 -040032 unsigned int SetupProcessor::States::computeHash()
33 {
34 unsigned int *state = (unsigned int*)this;
35 unsigned int hash = 0;
36
Nicolas Capens5d961882016-01-01 23:18:14 -050037 for(unsigned int i = 0; i < sizeof(States) / 4; i++)
John Bauman89401822014-05-06 15:04:28 -040038 {
39 hash ^= state[i];
40 }
41
42 return hash;
43 }
44
45 SetupProcessor::State::State(int i)
46 {
47 memset(this, 0, sizeof(State));
48 }
49
50 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
60 SetupProcessor::SetupProcessor(Context *context) : context(context)
61 {
62 routineCache = 0;
63 setRoutineCacheSize(1024);
64 }
65
66 SetupProcessor::~SetupProcessor()
67 {
68 delete routineCache;
69 routineCache = 0;
70 }
71
72 SetupProcessor::State SetupProcessor::update() const
73 {
74 State state;
75
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040076 bool vPosZW = (context->pixelShader && context->pixelShader->isVPosDeclared() && fullPixelPositionRegister);
John Bauman19bac1e2014-05-06 15:23:49 -040077
John Bauman89401822014-05-06 15:04:28 -040078 state.isDrawPoint = context->isDrawPoint(true);
79 state.isDrawLine = context->isDrawLine(true);
80 state.isDrawTriangle = context->isDrawTriangle(false);
81 state.isDrawSolidTriangle = context->isDrawTriangle(true);
Nicolas Capensa0f4be82014-10-22 14:35:30 -040082 state.interpolateZ = context->depthBufferActive() || context->pixelFogActive() != FOG_NONE || vPosZW;
John Bauman19bac1e2014-05-06 15:23:49 -040083 state.interpolateW = context->perspectiveActive() || vPosZW;
John Bauman89401822014-05-06 15:04:28 -040084 state.perspective = context->perspectiveActive();
85 state.pointSprite = context->pointSpriteActive();
86 state.cullMode = context->cullMode;
87 state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
Nicolas Capens3cbeac52017-09-15 11:49:31 -040088 state.slopeDepthBias = context->slopeDepthBias != 0.0f;
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040089 state.vFace = context->pixelShader && context->pixelShader->isVFaceDeclared();
John Bauman89401822014-05-06 15:04:28 -040090
91 state.positionRegister = Pos;
Nicolas Capensec0936c2016-05-18 12:32:02 -040092 state.pointSizeRegister = Unused;
John Bauman89401822014-05-06 15:04:28 -040093
John Bauman66b8ab22014-05-06 15:57:45 -040094 state.multiSample = context->getMultiSampleCount();
Alexis Hetub0f247f2016-02-22 11:42:39 -050095 state.rasterizerDiscard = context->rasterizerDiscard;
John Bauman89401822014-05-06 15:04:28 -040096
97 if(context->vertexShader)
98 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040099 state.positionRegister = context->vertexShader->getPositionRegister();
100 state.pointSizeRegister = context->vertexShader->getPointSizeRegister();
John Bauman89401822014-05-06 15:04:28 -0400101 }
102 else if(context->pointSizeActive())
103 {
104 state.pointSizeRegister = Pts;
105 }
106
Nicolas Capens3b4c93f2016-05-18 12:51:37 -0400107 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400108 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500109 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400110 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500111 state.gradient[interpolant][component].attribute = Unused;
John Bauman89401822014-05-06 15:04:28 -0400112 state.gradient[interpolant][component].flat = false;
113 state.gradient[interpolant][component].wrap = false;
114 }
115 }
116
Nicolas Capens66be2452015-01-27 14:58:57 -0500117 state.fog.attribute = Unused;
118 state.fog.flat = false;
119 state.fog.wrap = false;
120
John Bauman89401822014-05-06 15:04:28 -0400121 const bool point = context->isDrawPoint(true);
122 const bool sprite = context->pointSpriteActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400123 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
John Bauman89401822014-05-06 15:04:28 -0400124
125 if(context->vertexShader && context->pixelShader)
126 {
Nicolas Capens3b4c93f2016-05-18 12:51:37 -0400127 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400128 {
129 for(int component = 0; component < 4; component++)
130 {
131 int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400132 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component - project);
John Bauman89401822014-05-06 15:04:28 -0400133
Alexis Hetu12b00502016-05-20 13:01:11 -0400134 if(semantic.active())
John Bauman89401822014-05-06 15:04:28 -0400135 {
136 int input = interpolant;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400137 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400138 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400139 if(semantic == context->vertexShader->getOutput(i, component - project))
John Bauman89401822014-05-06 15:04:28 -0400140 {
141 input = i;
142 break;
143 }
144 }
145
146 bool flat = point;
147
Alexis Hetu12b00502016-05-20 13:01:11 -0400148 switch(semantic.usage)
John Bauman89401822014-05-06 15:04:28 -0400149 {
Alexis Hetu12b00502016-05-20 13:01:11 -0400150 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
151 case Shader::USAGE_COLOR: flat = semantic.flat || flatShading; break;
John Bauman89401822014-05-06 15:04:28 -0400152 }
153
154 state.gradient[interpolant][component].attribute = input;
155 state.gradient[interpolant][component].flat = flat;
156 }
157 }
158 }
159 }
160 else if(context->preTransformed && context->pixelShader)
161 {
Nicolas Capens3b4c93f2016-05-18 12:51:37 -0400162 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400163 {
164 for(int component = 0; component < 4; component++)
165 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400166 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
John Bauman89401822014-05-06 15:04:28 -0400167
Alexis Hetu12b00502016-05-20 13:01:11 -0400168 switch(semantic.usage)
John Bauman89401822014-05-06 15:04:28 -0400169 {
170 case 0xFF:
171 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400172 case Shader::USAGE_TEXCOORD:
Alexis Hetu12b00502016-05-20 13:01:11 -0400173 state.gradient[interpolant][component].attribute = T0 + semantic.index;
174 state.gradient[interpolant][component].flat = semantic.flat || (point && !sprite);
John Bauman89401822014-05-06 15:04:28 -0400175 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400176 case Shader::USAGE_COLOR:
Alexis Hetu12b00502016-05-20 13:01:11 -0400177 state.gradient[interpolant][component].attribute = C0 + semantic.index;
178 state.gradient[interpolant][component].flat = semantic.flat || flatShading;
John Bauman89401822014-05-06 15:04:28 -0400179 break;
180 default:
181 ASSERT(false);
182 }
183 }
184 }
185 }
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500186 else if(context->pixelShaderModel() < 0x0300)
John Bauman89401822014-05-06 15:04:28 -0400187 {
188 for(int coordinate = 0; coordinate < 8; coordinate++)
189 {
190 for(int component = 0; component < 4; component++)
191 {
192 if(context->textureActive(coordinate, component))
193 {
194 state.texture[coordinate][component].attribute = T0 + coordinate;
195 state.texture[coordinate][component].flat = point && !sprite;
196 state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
197 }
198 }
199 }
200
201 for(int color = 0; color < 2; color++)
202 {
203 for(int component = 0; component < 4; component++)
204 {
205 if(context->colorActive(color, component))
206 {
Nicolas Capens995ddea2016-05-17 11:48:56 -0400207 state.color[color][component].attribute = C0 + color;
John Bauman89401822014-05-06 15:04:28 -0400208 state.color[color][component].flat = flatShading;
209 }
210 }
211 }
212 }
213 else ASSERT(false);
214
215 if(context->fogActive())
216 {
217 state.fog.attribute = Fog;
218 state.fog.flat = point;
219 }
220
221 state.hash = state.computeHash();
222
223 return state;
224 }
225
226 Routine *SetupProcessor::routine(const State &state)
227 {
228 Routine *routine = routineCache->query(state);
229
230 if(!routine)
231 {
232 SetupRoutine *generator = new SetupRoutine(state);
233 generator->generate();
234 routine = generator->getRoutine();
235 delete generator;
236
237 routineCache->add(state, routine);
238 }
239
240 return routine;
241 }
242
243 void SetupProcessor::setRoutineCacheSize(int cacheSize)
244 {
245 delete routineCache;
Alexis Hetuf2878342019-03-12 16:32:04 -0400246 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536));
John Bauman89401822014-05-06 15:04:28 -0400247 }
248}