Home | History | Annotate | Download | only in Shader
      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 "VertexShader.hpp"
     16 
     17 #include "Renderer/Vertex.hpp"
     18 #include "Common/Debug.hpp"
     19 
     20 #include <string.h>
     21 
     22 namespace sw
     23 {
     24 	VertexShader::VertexShader(const VertexShader *vs) : Shader()
     25 	{
     26 		shaderModel = 0x0300;
     27 		positionRegister = Pos;
     28 		pointSizeRegister = Unused;
     29 		instanceIdDeclared = false;
     30 		vertexIdDeclared = false;
     31 		textureSampling = false;
     32 
     33 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
     34 		{
     35 			input[i] = Semantic();
     36 			attribType[i] = ATTRIBTYPE_FLOAT;
     37 		}
     38 
     39 		if(vs)   // Make a copy
     40 		{
     41 			for(size_t i = 0; i < vs->getLength(); i++)
     42 			{
     43 				append(new sw::Shader::Instruction(*vs->getInstruction(i)));
     44 			}
     45 
     46 			memcpy(output, vs->output, sizeof(output));
     47 			memcpy(input, vs->input, sizeof(input));
     48 			memcpy(attribType, vs->attribType, sizeof(attribType));
     49 			positionRegister = vs->positionRegister;
     50 			pointSizeRegister = vs->pointSizeRegister;
     51 			instanceIdDeclared = vs->instanceIdDeclared;
     52 			vertexIdDeclared = vs->vertexIdDeclared;
     53 			usedSamplers = vs->usedSamplers;
     54 
     55 			optimize();
     56 			analyze();
     57 		}
     58 	}
     59 
     60 	VertexShader::VertexShader(const unsigned long *token) : Shader()
     61 	{
     62 		parse(token);
     63 
     64 		positionRegister = Pos;
     65 		pointSizeRegister = Unused;
     66 		instanceIdDeclared = false;
     67 		vertexIdDeclared = false;
     68 		textureSampling = false;
     69 
     70 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
     71 		{
     72 			input[i] = Semantic();
     73 			attribType[i] = ATTRIBTYPE_FLOAT;
     74 		}
     75 
     76 		optimize();
     77 		analyze();
     78 	}
     79 
     80 	VertexShader::~VertexShader()
     81 	{
     82 	}
     83 
     84 	int VertexShader::validate(const unsigned long *const token)
     85 	{
     86 		if(!token)
     87 		{
     88 			return 0;
     89 		}
     90 
     91 		unsigned short version = (unsigned short)(token[0] & 0x0000FFFF);
     92 		unsigned char majorVersion = (unsigned char)((token[0] & 0x0000FF00) >> 8);
     93 		ShaderType shaderType = (ShaderType)((token[0] & 0xFFFF0000) >> 16);
     94 
     95 		if(shaderType != SHADER_VERTEX || majorVersion > 3)
     96 		{
     97 			return 0;
     98 		}
     99 
    100 		int instructionCount = 1;
    101 
    102 		for(int i = 0; token[i] != 0x0000FFFF; i++)
    103 		{
    104 			if((token[i] & 0x0000FFFF) == 0x0000FFFE)   // Comment token
    105 			{
    106 				int length = (token[i] & 0x7FFF0000) >> 16;
    107 
    108 				i += length;
    109 			}
    110 			else
    111 			{
    112 				Shader::Opcode opcode = (Shader::Opcode)(token[i] & 0x0000FFFF);
    113 
    114 				switch(opcode)
    115 				{
    116 				case Shader::OPCODE_TEXCOORD:
    117 				case Shader::OPCODE_TEXKILL:
    118 				case Shader::OPCODE_TEX:
    119 				case Shader::OPCODE_TEXBEM:
    120 				case Shader::OPCODE_TEXBEML:
    121 				case Shader::OPCODE_TEXREG2AR:
    122 				case Shader::OPCODE_TEXREG2GB:
    123 				case Shader::OPCODE_TEXM3X2PAD:
    124 				case Shader::OPCODE_TEXM3X2TEX:
    125 				case Shader::OPCODE_TEXM3X3PAD:
    126 				case Shader::OPCODE_TEXM3X3TEX:
    127 				case Shader::OPCODE_RESERVED0:
    128 				case Shader::OPCODE_TEXM3X3SPEC:
    129 				case Shader::OPCODE_TEXM3X3VSPEC:
    130 				case Shader::OPCODE_TEXREG2RGB:
    131 				case Shader::OPCODE_TEXDP3TEX:
    132 				case Shader::OPCODE_TEXM3X2DEPTH:
    133 				case Shader::OPCODE_TEXDP3:
    134 				case Shader::OPCODE_TEXM3X3:
    135 				case Shader::OPCODE_TEXDEPTH:
    136 				case Shader::OPCODE_CMP0:
    137 				case Shader::OPCODE_BEM:
    138 				case Shader::OPCODE_DP2ADD:
    139 				case Shader::OPCODE_DFDX:
    140 				case Shader::OPCODE_DFDY:
    141 				case Shader::OPCODE_TEXLDD:
    142 					return 0;   // Unsupported operation
    143 				default:
    144 					instructionCount++;
    145 					break;
    146 				}
    147 
    148 				i += size(token[i], version);
    149 			}
    150 		}
    151 
    152 		return instructionCount;
    153 	}
    154 
    155 	bool VertexShader::containsTextureSampling() const
    156 	{
    157 		return textureSampling;
    158 	}
    159 
    160 	void VertexShader::setInput(int inputIdx, const sw::Shader::Semantic& semantic, AttribType aType)
    161 	{
    162 		input[inputIdx] = semantic;
    163 		attribType[inputIdx] = aType;
    164 	}
    165 
    166 	void VertexShader::setOutput(int outputIdx, int nbComponents, const sw::Shader::Semantic& semantic)
    167 	{
    168 		for(int i = 0; i < nbComponents; ++i)
    169 		{
    170 			output[outputIdx][i] = semantic;
    171 		}
    172 	}
    173 
    174 	void VertexShader::setPositionRegister(int posReg)
    175 	{
    176 		setOutput(posReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0));
    177 		positionRegister = posReg;
    178 	}
    179 
    180 	void VertexShader::setPointSizeRegister(int ptSizeReg)
    181 	{
    182 		setOutput(ptSizeReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0));
    183 		pointSizeRegister = ptSizeReg;
    184 	}
    185 
    186 	const sw::Shader::Semantic& VertexShader::getInput(int inputIdx) const
    187 	{
    188 		return input[inputIdx];
    189 	}
    190 
    191 	VertexShader::AttribType VertexShader::getAttribType(int inputIdx) const
    192 	{
    193 		return attribType[inputIdx];
    194 	}
    195 
    196 	const sw::Shader::Semantic& VertexShader::getOutput(int outputIdx, int component) const
    197 	{
    198 		return output[outputIdx][component];
    199 	}
    200 
    201 	void VertexShader::analyze()
    202 	{
    203 		analyzeInput();
    204 		analyzeOutput();
    205 		analyzeDirtyConstants();
    206 		analyzeTextureSampling();
    207 		analyzeDynamicBranching();
    208 		analyzeSamplers();
    209 		analyzeCallSites();
    210 		analyzeDynamicIndexing();
    211 	}
    212 
    213 	void VertexShader::analyzeInput()
    214 	{
    215 		for(unsigned int i = 0; i < instruction.size(); i++)
    216 		{
    217 			if(instruction[i]->opcode == Shader::OPCODE_DCL &&
    218 			   instruction[i]->dst.type == Shader::PARAMETER_INPUT)
    219 			{
    220 				int index = instruction[i]->dst.index;
    221 
    222 				input[index] = Semantic(instruction[i]->usage, instruction[i]->usageIndex);
    223 			}
    224 		}
    225 	}
    226 
    227 	void VertexShader::analyzeOutput()
    228 	{
    229 		if(shaderModel < 0x0300)
    230 		{
    231 			output[Pos][0] = Semantic(Shader::USAGE_POSITION, 0);
    232 			output[Pos][1] = Semantic(Shader::USAGE_POSITION, 0);
    233 			output[Pos][2] = Semantic(Shader::USAGE_POSITION, 0);
    234 			output[Pos][3] = Semantic(Shader::USAGE_POSITION, 0);
    235 
    236 			for(const auto &inst : instruction)
    237 			{
    238 				const DestinationParameter &dst = inst->dst;
    239 
    240 				switch(dst.type)
    241 				{
    242 				case Shader::PARAMETER_RASTOUT:
    243 					switch(dst.index)
    244 					{
    245 					case 0:
    246 						// Position already assumed written
    247 						break;
    248 					case 1:
    249 						output[Fog][0] = Semantic(Shader::USAGE_FOG, 0);
    250 						break;
    251 					case 2:
    252 						output[Pts][1] = Semantic(Shader::USAGE_PSIZE, 0);
    253 						pointSizeRegister = Pts;
    254 						break;
    255 					default: ASSERT(false);
    256 					}
    257 					break;
    258 				case Shader::PARAMETER_ATTROUT:
    259 					if(dst.index == 0)
    260 					{
    261 						if(dst.x) output[C0][0] = Semantic(Shader::USAGE_COLOR, 0);
    262 						if(dst.y) output[C0][1] = Semantic(Shader::USAGE_COLOR, 0);
    263 						if(dst.z) output[C0][2] = Semantic(Shader::USAGE_COLOR, 0);
    264 						if(dst.w) output[C0][3] = Semantic(Shader::USAGE_COLOR, 0);
    265 					}
    266 					else if(dst.index == 1)
    267 					{
    268 						if(dst.x) output[C1][0] = Semantic(Shader::USAGE_COLOR, 1);
    269 						if(dst.y) output[C1][1] = Semantic(Shader::USAGE_COLOR, 1);
    270 						if(dst.z) output[C1][2] = Semantic(Shader::USAGE_COLOR, 1);
    271 						if(dst.w) output[C1][3] = Semantic(Shader::USAGE_COLOR, 1);
    272 					}
    273 					else ASSERT(false);
    274 					break;
    275 				case Shader::PARAMETER_TEXCRDOUT:
    276 					if(dst.x) output[T0 + dst.index][0] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
    277 					if(dst.y) output[T0 + dst.index][1] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
    278 					if(dst.z) output[T0 + dst.index][2] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
    279 					if(dst.w) output[T0 + dst.index][3] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
    280 					break;
    281 				default:
    282 					break;
    283 				}
    284 			}
    285 		}
    286 		else   // Shader Model 3.0 input declaration
    287 		{
    288 			for(const auto &inst : instruction)
    289 			{
    290 				if(inst->opcode == Shader::OPCODE_DCL &&
    291 				   inst->dst.type == Shader::PARAMETER_OUTPUT)
    292 				{
    293 					unsigned char usage = inst->usage;
    294 					unsigned char usageIndex = inst->usageIndex;
    295 
    296 					const DestinationParameter &dst = inst->dst;
    297 
    298 					if(dst.x) output[dst.index][0] = Semantic(usage, usageIndex);
    299 					if(dst.y) output[dst.index][1] = Semantic(usage, usageIndex);
    300 					if(dst.z) output[dst.index][2] = Semantic(usage, usageIndex);
    301 					if(dst.w) output[dst.index][3] = Semantic(usage, usageIndex);
    302 
    303 					if(usage == Shader::USAGE_POSITION && usageIndex == 0)
    304 					{
    305 						positionRegister = dst.index;
    306 					}
    307 
    308 					if(usage == Shader::USAGE_PSIZE && usageIndex == 0)
    309 					{
    310 						pointSizeRegister = dst.index;
    311 					}
    312 				}
    313 			}
    314 		}
    315 	}
    316 
    317 	void VertexShader::analyzeTextureSampling()
    318 	{
    319 		textureSampling = false;
    320 
    321 		for(const auto &inst : instruction)
    322 		{
    323 			if(inst->src[1].type == PARAMETER_SAMPLER)
    324 			{
    325 				textureSampling = true;
    326 				break;
    327 			}
    328 		}
    329 	}
    330 }
    331