OSDN Git Service

gl_VertexID implementation
[android-x86/external-swiftshader.git] / src / Shader / VertexShader.cpp
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 "Vertex.hpp"
18 #include "Debug.hpp"
19
20 #include <string.h>
21
22 namespace sw
23 {
24         VertexShader::VertexShader(const VertexShader *vs) : Shader()
25         {
26                 version = 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(version < 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(unsigned int i = 0; i < instruction.size(); i++)
237                         {
238                                 const DestinationParameter &dst = instruction[i]->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(unsigned int i = 0; i < instruction.size(); i++)
289                         {
290                                 if(instruction[i]->opcode == Shader::OPCODE_DCL &&
291                                    instruction[i]->dst.type == Shader::PARAMETER_OUTPUT)
292                                 {
293                                         unsigned char usage = instruction[i]->usage;
294                                         unsigned char usageIndex = instruction[i]->usageIndex;
295
296                                         const DestinationParameter &dst = instruction[i]->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(unsigned int i = 0; i < instruction.size() && !textureSampling; i++)
322                 {
323                         if(instruction[i]->src[1].type == PARAMETER_SAMPLER)
324                         {
325                                 textureSampling = true;
326                         }
327                 }
328         }
329 }