blob: 33c22416680afe971bc1fa05416da51f2ebb504b [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// 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.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "VertexShader.hpp"
16
Nicolas Capens708c24b2017-10-26 13:07:10 -040017#include "Renderer/Vertex.hpp"
18#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040019
John Bauman66b8ab22014-05-06 15:57:45 -040020#include <string.h>
21
John Bauman89401822014-05-06 15:04:28 -040022namespace sw
23{
John Bauman19bac1e2014-05-06 15:23:49 -040024 VertexShader::VertexShader(const VertexShader *vs) : Shader()
25 {
Alexis Hetu53ad4af2017-12-06 14:49:07 -050026 shaderModel = 0x0300;
John Bauman19bac1e2014-05-06 15:23:49 -040027 positionRegister = Pos;
Nicolas Capensec0936c2016-05-18 12:32:02 -040028 pointSizeRegister = Unused;
Alexis Hetu6743bbf2015-04-21 17:06:14 -040029 instanceIdDeclared = false;
Alexis Hetu877ddfc2017-07-25 17:48:00 -040030 vertexIdDeclared = false;
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040031 textureSampling = false;
John Bauman19bac1e2014-05-06 15:23:49 -040032
Nicolas Capensf0aef1a2016-05-18 14:44:21 -040033 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman19bac1e2014-05-06 15:23:49 -040034 {
Alexis Hetu1d672442016-06-23 11:24:00 -040035 input[i] = Semantic();
Alexis Hetub7508b82016-09-22 15:36:45 -040036 attribType[i] = ATTRIBTYPE_FLOAT;
John Bauman19bac1e2014-05-06 15:23:49 -040037 }
38
39 if(vs) // Make a copy
40 {
Alexis Hetu903e0252014-11-25 14:25:32 -050041 for(size_t i = 0; i < vs->getLength(); i++)
John Bauman19bac1e2014-05-06 15:23:49 -040042 {
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));
Alexis Hetub7508b82016-09-22 15:36:45 -040048 memcpy(attribType, vs->attribType, sizeof(attribType));
John Bauman19bac1e2014-05-06 15:23:49 -040049 positionRegister = vs->positionRegister;
50 pointSizeRegister = vs->pointSizeRegister;
Alexis Hetudd8df682015-06-05 17:08:39 -040051 instanceIdDeclared = vs->instanceIdDeclared;
Alexis Hetu877ddfc2017-07-25 17:48:00 -040052 vertexIdDeclared = vs->vertexIdDeclared;
John Bauman19bac1e2014-05-06 15:23:49 -040053 usedSamplers = vs->usedSamplers;
54
John Baumand4ae8632014-05-06 16:18:33 -040055 optimize();
John Bauman19bac1e2014-05-06 15:23:49 -040056 analyze();
57 }
58 }
59
60 VertexShader::VertexShader(const unsigned long *token) : Shader()
John Bauman89401822014-05-06 15:04:28 -040061 {
62 parse(token);
John Bauman19bac1e2014-05-06 15:23:49 -040063
64 positionRegister = Pos;
Nicolas Capensec0936c2016-05-18 12:32:02 -040065 pointSizeRegister = Unused;
Alexis Hetu6743bbf2015-04-21 17:06:14 -040066 instanceIdDeclared = false;
Alexis Hetu877ddfc2017-07-25 17:48:00 -040067 vertexIdDeclared = false;
Alexis Hetu02ad0aa2016-08-02 11:18:14 -040068 textureSampling = false;
John Bauman19bac1e2014-05-06 15:23:49 -040069
Nicolas Capensf0aef1a2016-05-18 14:44:21 -040070 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman19bac1e2014-05-06 15:23:49 -040071 {
Alexis Hetu1d672442016-06-23 11:24:00 -040072 input[i] = Semantic();
Alexis Hetub7508b82016-09-22 15:36:45 -040073 attribType[i] = ATTRIBTYPE_FLOAT;
John Bauman19bac1e2014-05-06 15:23:49 -040074 }
75
John Baumand4ae8632014-05-06 16:18:33 -040076 optimize();
John Bauman19bac1e2014-05-06 15:23:49 -040077 analyze();
John Bauman89401822014-05-06 15:04:28 -040078 }
79
80 VertexShader::~VertexShader()
81 {
82 }
83
John Bauman89401822014-05-06 15:04:28 -040084 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);
John Bauman89401822014-05-06 15:04:28 -040092 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 {
John Bauman19bac1e2014-05-06 15:23:49 -0400112 Shader::Opcode opcode = (Shader::Opcode)(token[i] & 0x0000FFFF);
John Bauman89401822014-05-06 15:04:28 -0400113
114 switch(opcode)
115 {
John Bauman19bac1e2014-05-06 15:23:49 -0400116 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:
John Bauman89401822014-05-06 15:04:28 -0400142 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
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500155 bool VertexShader::containsTextureSampling() const
John Bauman89401822014-05-06 15:04:28 -0400156 {
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500157 return textureSampling;
John Bauman89401822014-05-06 15:04:28 -0400158 }
159
Alexis Hetub7508b82016-09-22 15:36:45 -0400160 void VertexShader::setInput(int inputIdx, const sw::Shader::Semantic& semantic, AttribType aType)
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400161 {
162 input[inputIdx] = semantic;
Alexis Hetub7508b82016-09-22 15:36:45 -0400163 attribType[inputIdx] = aType;
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400164 }
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
Alexis Hetub7508b82016-09-22 15:36:45 -0400191 VertexShader::AttribType VertexShader::getAttribType(int inputIdx) const
192 {
193 return attribType[inputIdx];
194 }
195
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400196 const sw::Shader::Semantic& VertexShader::getOutput(int outputIdx, int component) const
197 {
198 return output[outputIdx][component];
199 }
200
John Bauman19bac1e2014-05-06 15:23:49 -0400201 void VertexShader::analyze()
202 {
203 analyzeInput();
204 analyzeOutput();
205 analyzeDirtyConstants();
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500206 analyzeTextureSampling();
John Bauman19bac1e2014-05-06 15:23:49 -0400207 analyzeDynamicBranching();
208 analyzeSamplers();
209 analyzeCallSites();
210 analyzeDynamicIndexing();
211 }
212
John Bauman89401822014-05-06 15:04:28 -0400213 void VertexShader::analyzeInput()
214 {
John Bauman19bac1e2014-05-06 15:23:49 -0400215 for(unsigned int i = 0; i < instruction.size(); i++)
John Bauman89401822014-05-06 15:04:28 -0400216 {
John Bauman19bac1e2014-05-06 15:23:49 -0400217 if(instruction[i]->opcode == Shader::OPCODE_DCL &&
218 instruction[i]->dst.type == Shader::PARAMETER_INPUT)
John Bauman89401822014-05-06 15:04:28 -0400219 {
John Bauman19bac1e2014-05-06 15:23:49 -0400220 int index = instruction[i]->dst.index;
John Bauman89401822014-05-06 15:04:28 -0400221
John Bauman19bac1e2014-05-06 15:23:49 -0400222 input[index] = Semantic(instruction[i]->usage, instruction[i]->usageIndex);
John Bauman89401822014-05-06 15:04:28 -0400223 }
224 }
225 }
226
227 void VertexShader::analyzeOutput()
228 {
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500229 if(shaderModel < 0x0300)
John Bauman89401822014-05-06 15:04:28 -0400230 {
John Bauman19bac1e2014-05-06 15:23:49 -0400231 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);
John Bauman89401822014-05-06 15:04:28 -0400235
Alexis Hetubf3fc252017-12-06 14:22:10 -0500236 for(const auto &inst : instruction)
John Bauman89401822014-05-06 15:04:28 -0400237 {
Alexis Hetubf3fc252017-12-06 14:22:10 -0500238 const DestinationParameter &dst = inst->dst;
John Bauman89401822014-05-06 15:04:28 -0400239
240 switch(dst.type)
241 {
John Bauman19bac1e2014-05-06 15:23:49 -0400242 case Shader::PARAMETER_RASTOUT:
John Bauman89401822014-05-06 15:04:28 -0400243 switch(dst.index)
244 {
245 case 0:
246 // Position already assumed written
247 break;
248 case 1:
John Bauman19bac1e2014-05-06 15:23:49 -0400249 output[Fog][0] = Semantic(Shader::USAGE_FOG, 0);
John Bauman89401822014-05-06 15:04:28 -0400250 break;
251 case 2:
John Bauman19bac1e2014-05-06 15:23:49 -0400252 output[Pts][1] = Semantic(Shader::USAGE_PSIZE, 0);
John Bauman89401822014-05-06 15:04:28 -0400253 pointSizeRegister = Pts;
254 break;
255 default: ASSERT(false);
256 }
257 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400258 case Shader::PARAMETER_ATTROUT:
John Bauman89401822014-05-06 15:04:28 -0400259 if(dst.index == 0)
260 {
Nicolas Capens995ddea2016-05-17 11:48:56 -0400261 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);
John Bauman89401822014-05-06 15:04:28 -0400265 }
266 else if(dst.index == 1)
267 {
Nicolas Capens995ddea2016-05-17 11:48:56 -0400268 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);
John Bauman89401822014-05-06 15:04:28 -0400272 }
273 else ASSERT(false);
274 break;
John Bauman19bac1e2014-05-06 15:23:49 -0400275 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);
John Bauman66b8ab22014-05-06 15:57:45 -0400279 if(dst.w) output[T0 + dst.index][3] = Semantic(Shader::USAGE_TEXCOORD, dst.index);
John Bauman89401822014-05-06 15:04:28 -0400280 break;
281 default:
282 break;
283 }
284 }
285 }
286 else // Shader Model 3.0 input declaration
287 {
Alexis Hetubf3fc252017-12-06 14:22:10 -0500288 for(const auto &inst : instruction)
John Bauman89401822014-05-06 15:04:28 -0400289 {
Alexis Hetubf3fc252017-12-06 14:22:10 -0500290 if(inst->opcode == Shader::OPCODE_DCL &&
291 inst->dst.type == Shader::PARAMETER_OUTPUT)
John Bauman89401822014-05-06 15:04:28 -0400292 {
Alexis Hetubf3fc252017-12-06 14:22:10 -0500293 unsigned char usage = inst->usage;
294 unsigned char usageIndex = inst->usageIndex;
John Bauman89401822014-05-06 15:04:28 -0400295
Alexis Hetubf3fc252017-12-06 14:22:10 -0500296 const DestinationParameter &dst = inst->dst;
John Bauman89401822014-05-06 15:04:28 -0400297
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
John Bauman19bac1e2014-05-06 15:23:49 -0400303 if(usage == Shader::USAGE_POSITION && usageIndex == 0)
John Bauman89401822014-05-06 15:04:28 -0400304 {
305 positionRegister = dst.index;
306 }
307
John Bauman19bac1e2014-05-06 15:23:49 -0400308 if(usage == Shader::USAGE_PSIZE && usageIndex == 0)
John Bauman89401822014-05-06 15:04:28 -0400309 {
310 pointSizeRegister = dst.index;
311 }
312 }
313 }
314 }
315 }
316
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500317 void VertexShader::analyzeTextureSampling()
John Bauman89401822014-05-06 15:04:28 -0400318 {
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500319 textureSampling = false;
John Bauman89401822014-05-06 15:04:28 -0400320
Alexis Hetubf3fc252017-12-06 14:22:10 -0500321 for(const auto &inst : instruction)
John Bauman89401822014-05-06 15:04:28 -0400322 {
Alexis Hetubf3fc252017-12-06 14:22:10 -0500323 if(inst->src[1].type == PARAMETER_SAMPLER)
John Bauman89401822014-05-06 15:04:28 -0400324 {
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500325 textureSampling = true;
Alexis Hetubf3fc252017-12-06 14:22:10 -0500326 break;
John Bauman89401822014-05-06 15:04:28 -0400327 }
328 }
329 }
330}