blob: f23068fe90a1dc1a836e1e69ffeedd6911a06282 [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
Nicolas Capens92eb0412019-08-20 14:13:17 -040025#include <cstring>
26
John Bauman89401822014-05-06 15:04:28 -040027namespace sw
28{
29 extern bool complementaryDepthBuffer;
John Bauman19bac1e2014-05-06 15:23:49 -040030 extern bool fullPixelPositionRegister;
John Bauman89401822014-05-06 15:04:28 -040031
John Bauman66b8ab22014-05-06 15:57:45 -040032 bool precacheSetup = false;
33
Nicolas Capens92eb0412019-08-20 14:13:17 -040034 uint32_t SetupProcessor::States::computeHash()
John Bauman89401822014-05-06 15:04:28 -040035 {
Nicolas Capens92eb0412019-08-20 14:13:17 -040036 uint32_t *state = reinterpret_cast<uint32_t*>(this);
37 uint32_t hash = 0;
John Bauman89401822014-05-06 15:04:28 -040038
Nicolas Capens92eb0412019-08-20 14:13:17 -040039 for(unsigned int i = 0; i < sizeof(States) / sizeof(uint32_t); i++)
John Bauman89401822014-05-06 15:04:28 -040040 {
41 hash ^= state[i];
42 }
43
44 return hash;
45 }
46
John Bauman89401822014-05-06 15:04:28 -040047 bool SetupProcessor::State::operator==(const State &state) const
48 {
49 if(hash != state.hash)
50 {
51 return false;
52 }
53
Nicolas Capens92eb0412019-08-20 14:13:17 -040054 static_assert(is_memcmparable<State>::value, "Cannot memcmp States");
John Bauman89401822014-05-06 15:04:28 -040055 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
56 }
57
58 SetupProcessor::SetupProcessor(Context *context) : context(context)
59 {
Nicolas Capens92eb0412019-08-20 14:13:17 -040060 routineCache = nullptr;
John Bauman89401822014-05-06 15:04:28 -040061 setRoutineCacheSize(1024);
62 }
63
64 SetupProcessor::~SetupProcessor()
65 {
66 delete routineCache;
Nicolas Capens92eb0412019-08-20 14:13:17 -040067 routineCache = nullptr;
John Bauman89401822014-05-06 15:04:28 -040068 }
69
70 SetupProcessor::State SetupProcessor::update() const
71 {
72 State state;
73
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040074 bool vPosZW = (context->pixelShader && context->pixelShader->isVPosDeclared() && fullPixelPositionRegister);
John Bauman19bac1e2014-05-06 15:23:49 -040075
John Bauman89401822014-05-06 15:04:28 -040076 state.isDrawPoint = context->isDrawPoint(true);
77 state.isDrawLine = context->isDrawLine(true);
78 state.isDrawTriangle = context->isDrawTriangle(false);
79 state.isDrawSolidTriangle = context->isDrawTriangle(true);
Nicolas Capensa0f4be82014-10-22 14:35:30 -040080 state.interpolateZ = context->depthBufferActive() || context->pixelFogActive() != FOG_NONE || vPosZW;
John Bauman19bac1e2014-05-06 15:23:49 -040081 state.interpolateW = context->perspectiveActive() || vPosZW;
John Bauman89401822014-05-06 15:04:28 -040082 state.perspective = context->perspectiveActive();
83 state.pointSprite = context->pointSpriteActive();
84 state.cullMode = context->cullMode;
85 state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
Nicolas Capens3cbeac52017-09-15 11:49:31 -040086 state.slopeDepthBias = context->slopeDepthBias != 0.0f;
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040087 state.vFace = context->pixelShader && context->pixelShader->isVFaceDeclared();
John Bauman89401822014-05-06 15:04:28 -040088
89 state.positionRegister = Pos;
Nicolas Capensec0936c2016-05-18 12:32:02 -040090 state.pointSizeRegister = Unused;
John Bauman89401822014-05-06 15:04:28 -040091
John Bauman66b8ab22014-05-06 15:57:45 -040092 state.multiSample = context->getMultiSampleCount();
Alexis Hetub0f247f2016-02-22 11:42:39 -050093 state.rasterizerDiscard = context->rasterizerDiscard;
John Bauman89401822014-05-06 15:04:28 -040094
95 if(context->vertexShader)
96 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040097 state.positionRegister = context->vertexShader->getPositionRegister();
98 state.pointSizeRegister = context->vertexShader->getPointSizeRegister();
John Bauman89401822014-05-06 15:04:28 -040099 }
100 else if(context->pointSizeActive())
101 {
102 state.pointSizeRegister = Pts;
103 }
104
Nicolas Capens3b4c93f2016-05-18 12:51:37 -0400105 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400106 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500107 for(int component = 0; component < 4; component++)
John Bauman89401822014-05-06 15:04:28 -0400108 {
Nicolas Capens66be2452015-01-27 14:58:57 -0500109 state.gradient[interpolant][component].attribute = Unused;
John Bauman89401822014-05-06 15:04:28 -0400110 state.gradient[interpolant][component].flat = false;
111 state.gradient[interpolant][component].wrap = false;
112 }
113 }
114
Nicolas Capens66be2452015-01-27 14:58:57 -0500115 state.fog.attribute = Unused;
116 state.fog.flat = false;
117 state.fog.wrap = false;
118
John Bauman89401822014-05-06 15:04:28 -0400119 const bool point = context->isDrawPoint(true);
120 const bool sprite = context->pointSpriteActive();
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400121 const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
John Bauman89401822014-05-06 15:04:28 -0400122
123 if(context->vertexShader && context->pixelShader)
124 {
Nicolas Capens3b4c93f2016-05-18 12:51:37 -0400125 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400126 {
127 for(int component = 0; component < 4; component++)
128 {
129 int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400130 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component - project);
John Bauman89401822014-05-06 15:04:28 -0400131
Alexis Hetu12b00502016-05-20 13:01:11 -0400132 if(semantic.active())
John Bauman89401822014-05-06 15:04:28 -0400133 {
134 int input = interpolant;
Nicolas Capensec0936c2016-05-18 12:32:02 -0400135 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400136 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400137 if(semantic == context->vertexShader->getOutput(i, component - project))
John Bauman89401822014-05-06 15:04:28 -0400138 {
139 input = i;
140 break;
141 }
142 }
143
144 bool flat = point;
145
Alexis Hetu12b00502016-05-20 13:01:11 -0400146 switch(semantic.usage)
John Bauman89401822014-05-06 15:04:28 -0400147 {
Alexis Hetu12b00502016-05-20 13:01:11 -0400148 case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
149 case Shader::USAGE_COLOR: flat = semantic.flat || flatShading; break;
John Bauman89401822014-05-06 15:04:28 -0400150 }
151
152 state.gradient[interpolant][component].attribute = input;
153 state.gradient[interpolant][component].flat = flat;
154 }
155 }
156 }
157 }
158 else if(context->preTransformed && context->pixelShader)
159 {
Nicolas Capens3b4c93f2016-05-18 12:51:37 -0400160 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
John Bauman89401822014-05-06 15:04:28 -0400161 {
162 for(int component = 0; component < 4; component++)
163 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400164 const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
John Bauman89401822014-05-06 15:04:28 -0400165
Alexis Hetu12b00502016-05-20 13:01:11 -0400166 switch(semantic.usage)
John Bauman89401822014-05-06 15:04:28 -0400167 {
168 case 0xFF:
169 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400170 case Shader::USAGE_TEXCOORD:
Alexis Hetu12b00502016-05-20 13:01:11 -0400171 state.gradient[interpolant][component].attribute = T0 + semantic.index;
172 state.gradient[interpolant][component].flat = semantic.flat || (point && !sprite);
John Bauman89401822014-05-06 15:04:28 -0400173 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400174 case Shader::USAGE_COLOR:
Alexis Hetu12b00502016-05-20 13:01:11 -0400175 state.gradient[interpolant][component].attribute = C0 + semantic.index;
176 state.gradient[interpolant][component].flat = semantic.flat || flatShading;
John Bauman89401822014-05-06 15:04:28 -0400177 break;
178 default:
179 ASSERT(false);
180 }
181 }
182 }
183 }
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500184 else if(context->pixelShaderModel() < 0x0300)
John Bauman89401822014-05-06 15:04:28 -0400185 {
186 for(int coordinate = 0; coordinate < 8; coordinate++)
187 {
188 for(int component = 0; component < 4; component++)
189 {
190 if(context->textureActive(coordinate, component))
191 {
192 state.texture[coordinate][component].attribute = T0 + coordinate;
193 state.texture[coordinate][component].flat = point && !sprite;
194 state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
195 }
196 }
197 }
198
199 for(int color = 0; color < 2; color++)
200 {
201 for(int component = 0; component < 4; component++)
202 {
203 if(context->colorActive(color, component))
204 {
Nicolas Capens995ddea2016-05-17 11:48:56 -0400205 state.color[color][component].attribute = C0 + color;
John Bauman89401822014-05-06 15:04:28 -0400206 state.color[color][component].flat = flatShading;
207 }
208 }
209 }
210 }
211 else ASSERT(false);
212
213 if(context->fogActive())
214 {
215 state.fog.attribute = Fog;
216 state.fog.flat = point;
217 }
218
219 state.hash = state.computeHash();
220
221 return state;
222 }
223
Ben Clayton6897e9b2019-07-16 17:27:27 +0100224 std::shared_ptr<Routine> SetupProcessor::routine(const State &state)
John Bauman89401822014-05-06 15:04:28 -0400225 {
Ben Clayton6897e9b2019-07-16 17:27:27 +0100226 auto routine = routineCache->query(state);
John Bauman89401822014-05-06 15:04:28 -0400227
228 if(!routine)
229 {
230 SetupRoutine *generator = new SetupRoutine(state);
231 generator->generate();
232 routine = generator->getRoutine();
233 delete generator;
234
235 routineCache->add(state, routine);
236 }
237
238 return routine;
239 }
240
241 void SetupProcessor::setRoutineCacheSize(int cacheSize)
242 {
243 delete routineCache;
Alexis Hetuf2878342019-03-12 16:32:04 -0400244 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536));
John Bauman89401822014-05-06 15:04:28 -0400245 }
246}