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 analyzeDynamicIndexing(); 211 } 212 analyzeInput()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 analyzeOutput()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 analyzeTextureSampling()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