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