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 "SetupRoutine.hpp"
     18 #include "Primitive.hpp"
     19 #include "Polygon.hpp"
     20 #include "Context.hpp"
     21 #include "Renderer.hpp"
     22 #include "Constants.hpp"
     23 #include "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->vPosDeclared && 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 = slopeDepthBias != 0.0f;
     89 		state.vFace = context->pixelShader && context->pixelShader->vFaceDeclared;
     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->positionRegister;
    100 			state.pointSizeRegister = context->vertexShader->pointSizeRegister;
    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 
    133 					if(context->pixelShader->semantic[interpolant][component - project].active())
    134 					{
    135 						int input = interpolant;
    136 						for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
    137 						{
    138 							if(context->pixelShader->semantic[interpolant][component - project] == context->vertexShader->output[i][component - project])
    139 							{
    140 								input = i;
    141 								break;
    142 							}
    143 						}
    144 
    145 						bool flat = point;
    146 
    147 						switch(context->pixelShader->semantic[interpolant][component - project].usage)
    148 						{
    149 						case Shader::USAGE_TEXCOORD: flat = point && !sprite; break;
    150 						case Shader::USAGE_COLOR:    flat = flatShading;      break;
    151 						}
    152 
    153 						state.gradient[interpolant][component].attribute = input;
    154 						state.gradient[interpolant][component].flat = flat;
    155 					}
    156 				}
    157 			}
    158 		}
    159 		else if(context->preTransformed && context->pixelShader)
    160 		{
    161 			for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++)
    162 			{
    163 				for(int component = 0; component < 4; component++)
    164 				{
    165 					int index = context->pixelShader->semantic[interpolant][component].index;
    166 
    167 					switch(context->pixelShader->semantic[interpolant][component].usage)
    168 					{
    169 					case 0xFF:
    170 						break;
    171 					case Shader::USAGE_TEXCOORD:
    172 						state.gradient[interpolant][component].attribute = T0 + index;
    173 						state.gradient[interpolant][component].flat = point && !sprite;
    174 						break;
    175 					case Shader::USAGE_COLOR:
    176 						state.gradient[interpolant][component].attribute = C0 + index;
    177 						state.gradient[interpolant][component].flat = flatShading;
    178 						break;
    179 					default:
    180 						ASSERT(false);
    181 					}
    182 				}
    183 			}
    184 		}
    185 		else if(context->pixelShaderVersion() < 0x0300)
    186 		{
    187 			for(int coordinate = 0; coordinate < 8; coordinate++)
    188 			{
    189 				for(int component = 0; component < 4; component++)
    190 				{
    191 					if(context->textureActive(coordinate, component))
    192 					{
    193 						state.texture[coordinate][component].attribute = T0 + coordinate;
    194 						state.texture[coordinate][component].flat = point && !sprite;
    195 						state.texture[coordinate][component].wrap = (context->textureWrap[coordinate] & (1 << component)) != 0;
    196 					}
    197 				}
    198 			}
    199 
    200 			for(int color = 0; color < 2; color++)
    201 			{
    202 				for(int component = 0; component < 4; component++)
    203 				{
    204 					if(context->colorActive(color, component))
    205 					{
    206 						state.color[color][component].attribute = C0 + color;
    207 						state.color[color][component].flat = flatShading;
    208 					}
    209 				}
    210 			}
    211 		}
    212 		else ASSERT(false);
    213 
    214 		if(context->fogActive())
    215 		{
    216 			state.fog.attribute = Fog;
    217 			state.fog.flat = point;
    218 		}
    219 
    220 		state.hash = state.computeHash();
    221 
    222 		return state;
    223 	}
    224 
    225 	Routine *SetupProcessor::routine(const State &state)
    226 	{
    227 		Routine *routine = routineCache->query(state);
    228 
    229 		if(!routine)
    230 		{
    231 			SetupRoutine *generator = new SetupRoutine(state);
    232 			generator->generate();
    233 			routine = generator->getRoutine();
    234 			delete generator;
    235 
    236 			routineCache->add(state, routine);
    237 		}
    238 
    239 		return routine;
    240 	}
    241 
    242 	void SetupProcessor::setRoutineCacheSize(int cacheSize)
    243 	{
    244 		delete routineCache;
    245 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheSetup ? "sw-setup" : 0);
    246 	}
    247 }
    248