Home | History | Annotate | Download | only in Renderer
      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 "Shader/SetupRoutine.hpp"
     22 #include "Shader/Constants.hpp"
     23 #include "Common/Debug.hpp"
     24 
     25 namespace sw
     26 {
     27 	extern bool complementaryDepthBuffer;
     28 	extern bool fullPixelPositionRegister;
     29 
     30 	bool precacheSetup = false;
     31 
     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 
     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 
     76 		bool vPosZW = (context->pixelShader && context->pixelShader->isVPosDeclared() && fullPixelPositionRegister);
     77 
     78 		state.isDrawPoint = context->isDrawPoint(true);
     79 		state.isDrawLine = context->isDrawLine(true);
     80 		state.isDrawTriangle = context->isDrawTriangle(false);
     81 		state.isDrawSolidTriangle = context->isDrawTriangle(true);
     82 		state.interpolateZ = context->depthBufferActive() || context->pixelFogActive() != FOG_NONE || vPosZW;
     83 		state.interpolateW = context->perspectiveActive() || vPosZW;
     84 		state.perspective = context->perspectiveActive();
     85 		state.pointSprite = context->pointSpriteActive();
     86 		state.cullMode = context->cullMode;
     87 		state.twoSidedStencil = context->stencilActive() && context->twoSidedStencil;
     88 		state.slopeDepthBias = context->slopeDepthBias != 0.0f;
     89 		state.vFace = context->pixelShader && context->pixelShader->isVFaceDeclared();
     90 
     91 		state.positionRegister = Pos;
     92 		state.pointSizeRegister = Unused;
     93 
     94 		state.multiSample = context->getMultiSampleCount();
     95 		state.rasterizerDiscard = context->rasterizerDiscard;
     96 
     97 		if(context->vertexShader)
     98 		{
     99 			state.positionRegister = context->vertexShader->getPositionRegister();
    100 			state.pointSizeRegister = context->vertexShader->getPointSizeRegister();
    101 		}
    102 		else if(context->pointSizeActive())
    103 		{
    104 			state.pointSizeRegister = Pts;
    105 		}
    106 
    107 		for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
    108 		{
    109 			for(int component = 0; component < 4; component++)
    110 			{
    111 				state.gradient[interpolant][component].attribute = Unused;
    112 				state.gradient[interpolant][component].flat = false;
    113 				state.gradient[interpolant][component].wrap = false;
    114 			}
    115 		}
    116 
    117 		state.fog.attribute = Unused;
    118 		state.fog.flat = false;
    119 		state.fog.wrap = false;
    120 
    121 		const bool point = context->isDrawPoint(true);
    122 		const bool sprite = context->pointSpriteActive();
    123 		const bool flatShading = (context->shadingMode == SHADING_FLAT) || point;
    124 
    125 		if(context->vertexShader && context->pixelShader)
    126 		{
    127 			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
    128 			{
    129 				for(int component = 0; component < 4; component++)
    130 				{
    131 					int project = context->isProjectionComponent(interpolant - 2, component) ? 1 : 0;
    132 					const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component - project);
    133 
    134 					if(semantic.active())
    135 					{
    136 						int input = interpolant;
    137 						for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
    138 						{
    139 							if(semantic == context->vertexShader->getOutput(i, component - project))
    140 							{
    141 								input = i;
    142 								break;
    143 							}
    144 						}
    145 
    146 						bool flat = point;
    147 
    148 						switch(semantic.usage)
    149 						{
    150 						case Shader::USAGE_TEXCOORD: flat = point && !sprite;             break;
    151 						case Shader::USAGE_COLOR:    flat = semantic.flat || flatShading; break;
    152 						}
    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 		{
    162 			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
    163 			{
    164 				for(int component = 0; component < 4; component++)
    165 				{
    166 					const Shader::Semantic& semantic = context->pixelShader->getInput(interpolant, component);
    167 
    168 					switch(semantic.usage)
    169 					{
    170 					case 0xFF:
    171 						break;
    172 					case Shader::USAGE_TEXCOORD:
    173 						state.gradient[interpolant][component].attribute = T0 + semantic.index;
    174 						state.gradient[interpolant][component].flat = semantic.flat || (point && !sprite);
    175 						break;
    176 					case Shader::USAGE_COLOR:
    177 						state.gradient[interpolant][component].attribute = C0 + semantic.index;
    178 						state.gradient[interpolant][component].flat = semantic.flat || flatShading;
    179 						break;
    180 					default:
    181 						ASSERT(false);
    182 					}
    183 				}
    184 			}
    185 		}
    186 		else if(context->pixelShaderModel() < 0x0300)
    187 		{
    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 					{
    207 						state.color[color][component].attribute = C0 + color;
    208 						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;
    246 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0);
    247 	}
    248 }
    249