• 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 "VertexShader.hpp"
16 
17 #include "Renderer/Vertex.hpp"
18 #include "Common/Debug.hpp"
19 
20 #include <string.h>
21 
22 namespace sw
23 {
VertexShader(const VertexShader * vs)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 
VertexShader(const unsigned long * token)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 
~VertexShader()80 	VertexShader::~VertexShader()
81 	{
82 	}
83 
validate(const unsigned long * const token)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 
containsTextureSampling() const155 	bool VertexShader::containsTextureSampling() const
156 	{
157 		return textureSampling;
158 	}
159 
setInput(int inputIdx,const sw::Shader::Semantic & semantic,AttribType aType)160 	void VertexShader::setInput(int inputIdx, const sw::Shader::Semantic& semantic, AttribType aType)
161 	{
162 		input[inputIdx] = semantic;
163 		attribType[inputIdx] = aType;
164 	}
165 
setOutput(int outputIdx,int nbComponents,const sw::Shader::Semantic & semantic)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 
setPositionRegister(int posReg)174 	void VertexShader::setPositionRegister(int posReg)
175 	{
176 		setOutput(posReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0));
177 		positionRegister = posReg;
178 	}
179 
setPointSizeRegister(int ptSizeReg)180 	void VertexShader::setPointSizeRegister(int ptSizeReg)
181 	{
182 		setOutput(ptSizeReg, 4, sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0));
183 		pointSizeRegister = ptSizeReg;
184 	}
185 
getInput(int inputIdx) const186 	const sw::Shader::Semantic& VertexShader::getInput(int inputIdx) const
187 	{
188 		return input[inputIdx];
189 	}
190 
getAttribType(int inputIdx) const191 	VertexShader::AttribType VertexShader::getAttribType(int inputIdx) const
192 	{
193 		return attribType[inputIdx];
194 	}
195 
getOutput(int outputIdx,int component) const196 	const sw::Shader::Semantic& VertexShader::getOutput(int outputIdx, int component) const
197 	{
198 		return output[outputIdx][component];
199 	}
200 
analyze()201 	void VertexShader::analyze()
202 	{
203 		analyzeInput();
204 		analyzeOutput();
205 		analyzeDirtyConstants();
206 		analyzeTextureSampling();
207 		analyzeDynamicBranching();
208 		analyzeSamplers();
209 		analyzeCallSites();
210 		analyzeIndirectAddressing();
211 		analyzeLimits();
212 	}
213 
analyzeInput()214 	void VertexShader::analyzeInput()
215 	{
216 		for(unsigned int i = 0; i < instruction.size(); i++)
217 		{
218 			if(instruction[i]->opcode == Shader::OPCODE_DCL &&
219 			   instruction[i]->dst.type == Shader::PARAMETER_INPUT)
220 			{
221 				int index = instruction[i]->dst.index;
222 
223 				input[index] = Semantic(instruction[i]->usage, instruction[i]->usageIndex);
224 			}
225 		}
226 	}
227 
analyzeOutput()228 	void VertexShader::analyzeOutput()
229 	{
230 		if(shaderModel < 0x0300)
231 		{
232 			output[Pos][0] = Semantic(Shader::USAGE_POSITION, 0);
233 			output[Pos][1] = Semantic(Shader::USAGE_POSITION, 0);
234 			output[Pos][2] = Semantic(Shader::USAGE_POSITION, 0);
235 			output[Pos][3] = Semantic(Shader::USAGE_POSITION, 0);
236 
237 			for(const auto &inst : instruction)
238 			{
239 				const DestinationParameter &dst = inst->dst;
240 
241 				switch(dst.type)
242 				{
243 				case Shader::PARAMETER_RASTOUT:
244 					switch(dst.index)
245 					{
246 					case 0:
247 						// Position already assumed written
248 						break;
249 					case 1:
250 						output[Fog][0] = Semantic(Shader::USAGE_FOG, 0);
251 						break;
252 					case 2:
253 						output[Pts][1] = Semantic(Shader::USAGE_PSIZE, 0);
254 						pointSizeRegister = Pts;
255 						break;
256 					default: ASSERT(false);
257 					}
258 					break;
259 				case Shader::PARAMETER_ATTROUT:
260 					if(dst.index == 0)
261 					{
262 						if(dst.x) output[C0][0] = Semantic(Shader::USAGE_COLOR, 0);
263 						if(dst.y) output[C0][1] = Semantic(Shader::USAGE_COLOR, 0);
264 						if(dst.z) output[C0][2] = Semantic(Shader::USAGE_COLOR, 0);
265 						if(dst.w) output[C0][3] = Semantic(Shader::USAGE_COLOR, 0);
266 					}
267 					else if(dst.index == 1)
268 					{
269 						if(dst.x) output[C1][0] = Semantic(Shader::USAGE_COLOR, 1);
270 						if(dst.y) output[C1][1] = Semantic(Shader::USAGE_COLOR, 1);
271 						if(dst.z) output[C1][2] = Semantic(Shader::USAGE_COLOR, 1);
272 						if(dst.w) output[C1][3] = Semantic(Shader::USAGE_COLOR, 1);
273 					}
274 					else ASSERT(false);
275 					break;
276 				case Shader::PARAMETER_TEXCRDOUT:
277 					if(dst.x) output[T0 + dst.index][0] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
278 					if(dst.y) output[T0 + dst.index][1] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
279 					if(dst.z) output[T0 + dst.index][2] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
280 					if(dst.w) output[T0 + dst.index][3] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
281 					break;
282 				default:
283 					break;
284 				}
285 			}
286 		}
287 		else   // Shader Model 3.0 input declaration
288 		{
289 			for(const auto &inst : instruction)
290 			{
291 				if(inst->opcode == Shader::OPCODE_DCL &&
292 				   inst->dst.type == Shader::PARAMETER_OUTPUT)
293 				{
294 					unsigned char usage = inst->usage;
295 					unsigned char usageIndex = inst->usageIndex;
296 
297 					const DestinationParameter &dst = inst->dst;
298 
299 					if(dst.x) output[dst.index][0] = Semantic(usage, usageIndex);
300 					if(dst.y) output[dst.index][1] = Semantic(usage, usageIndex);
301 					if(dst.z) output[dst.index][2] = Semantic(usage, usageIndex);
302 					if(dst.w) output[dst.index][3] = Semantic(usage, usageIndex);
303 
304 					if(usage == Shader::USAGE_POSITION && usageIndex == 0)
305 					{
306 						positionRegister = dst.index;
307 					}
308 
309 					if(usage == Shader::USAGE_PSIZE && usageIndex == 0)
310 					{
311 						pointSizeRegister = dst.index;
312 					}
313 				}
314 			}
315 		}
316 	}
317 
analyzeTextureSampling()318 	void VertexShader::analyzeTextureSampling()
319 	{
320 		textureSampling = false;
321 
322 		for(const auto &inst : instruction)
323 		{
324 			if(inst->src[1].type == PARAMETER_SAMPLER)
325 			{
326 				textureSampling = true;
327 				break;
328 			}
329 		}
330 	}
331 }
332