• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // 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
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // 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.
14 
15 #include "SetupProcessor.hpp"
16 
17 #include "Primitive.hpp"
18 #include "Polygon.hpp"
19 #include "Context.hpp"
20 #include "Renderer.hpp"
21 #include "Pipeline/SetupRoutine.hpp"
22 #include "Pipeline/Constants.hpp"
23 #include "Vulkan/VkDebug.hpp"
24 
25 namespace sw
26 {
27 	extern bool complementaryDepthBuffer;
28 	extern bool fullPixelPositionRegister;
29 
30 	bool precacheSetup = false;
31 
computeHash()32 	unsigned int SetupProcessor::States::computeHash()
33 	{
34 		unsigned int *state = (unsigned int*)this;
35 		unsigned int hash = 0;
36 
37 		for(unsigned int i = 0; i < sizeof(States) / 4; i++)
38 		{
39 			hash ^= state[i];
40 		}
41 
42 		return hash;
43 	}
44 
State(int i)45 	SetupProcessor::State::State(int i)
46 	{
47 		memset(this, 0, sizeof(State));
48 	}
49 
operator ==(const State & state) const50 	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 
SetupProcessor(Context * context)60 	SetupProcessor::SetupProcessor(Context *context) : context(context)
61 	{
62 		routineCache = nullptr;
63 		setRoutineCacheSize(1024);
64 	}
65 
~SetupProcessor()66 	SetupProcessor::~SetupProcessor()
67 	{
68 		delete routineCache;
69 		routineCache = nullptr;
70 	}
71 
update() const72 	SetupProcessor::State SetupProcessor::update() const
73 	{
74 		State state;
75 
76 		bool vPosZW = (context->pixelShader && context->pixelShader->isVPosDeclared() && fullPixelPositionRegister);
77 
78 		state.isDrawPoint = context->isDrawPoint();
79 		state.isDrawLine = context->isDrawLine();
80 		state.isDrawTriangle = context->isDrawTriangle();
81 		state.interpolateZ = context->depthBufferActive() || vPosZW;
82 		state.interpolateW = context->perspectiveActive() || vPosZW;
83 		state.perspective = context->perspectiveActive();
84 		state.cullMode = context->cullMode;
85 		state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
86 		state.slopeDepthBias = context->slopeDepthBias != 0.0f;
87 		state.vFace = context->pixelShader && context->pixelShader->isVFaceDeclared();
88 
89 		state.positionRegister = Pos;
90 		state.pointSizeRegister = Unused;
91 
92 		state.multiSample = context->getMultiSampleCount();
93 		state.rasterizerDiscard = context->rasterizerDiscard;
94 
95 		state.positionRegister = context->vertexShader->getPositionRegister();
96 		state.pointSizeRegister = context->vertexShader->getPointSizeRegister();
97 
98 		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
99 		{
100 			for(int component = 0; component < 4; component++)
101 			{
102 				state.gradient[interpolant][component].attribute = Unused;
103 				state.gradient[interpolant][component].flat = false;
104 				state.gradient[interpolant][component].wrap = false;
105 			}
106 		}
107 
108 		const bool point = context->isDrawPoint();
109 
110 		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
111 		{
112 			for(int component = 0; component < 4; component++)
113 			{
114 				const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
115 
116 				if(semantic.active())
117 				{
118 					int input = interpolant;
119 					for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
120 					{
121 						if(semantic == context->vertexShader->getOutput(i, component))
122 						{
123 							input = i;
124 							break;
125 						}
126 					}
127 
128 					bool flat = point;
129 
130 					switch(semantic.usage)
131 					{
132 					case Shader::USAGE_TEXCOORD: flat = false;                  break;
133 					case Shader::USAGE_COLOR:    flat = semantic.flat || point; break;
134 					}
135 
136 					state.gradient[interpolant][component].attribute = input;
137 					state.gradient[interpolant][component].flat = flat;
138 				}
139 			}
140 		}
141 
142 		state.hash = state.computeHash();
143 
144 		return state;
145 	}
146 
routine(const State & state)147 	Routine *SetupProcessor::routine(const State &state)
148 	{
149 		Routine *routine = routineCache->query(state);
150 
151 		if(!routine)
152 		{
153 			SetupRoutine *generator = new SetupRoutine(state);
154 			generator->generate();
155 			routine = generator->getRoutine();
156 			delete generator;
157 
158 			routineCache->add(state, routine);
159 		}
160 
161 		return routine;
162 	}
163 
setRoutineCacheSize(int cacheSize)164 	void SetupProcessor::setRoutineCacheSize(int cacheSize)
165 	{
166 		delete routineCache;
167 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0);
168 	}
169 }
170