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 "PixelShader.hpp" |
16 | |
17 | #include "Common/Debug.hpp" |
18 | |
19 | #include <string.h> |
20 | |
21 | namespace sw |
22 | { |
23 | PixelShader::PixelShader(const PixelShader *ps) : Shader() |
24 | { |
25 | shaderModel = 0x0300; |
26 | vPosDeclared = false; |
27 | vFaceDeclared = false; |
28 | centroid = false; |
29 | |
30 | if(ps) // Make a copy |
31 | { |
32 | for(size_t i = 0; i < ps->getLength(); i++) |
33 | { |
34 | append(new sw::Shader::Instruction(*ps->getInstruction(i))); |
35 | } |
36 | |
37 | memcpy(input, ps->input, sizeof(input)); |
38 | vPosDeclared = ps->vPosDeclared; |
39 | vFaceDeclared = ps->vFaceDeclared; |
40 | usedSamplers = ps->usedSamplers; |
41 | |
42 | optimize(); |
43 | analyze(); |
44 | } |
45 | } |
46 | |
47 | PixelShader::PixelShader(const unsigned long *token) : Shader() |
48 | { |
49 | parse(token); |
50 | |
51 | vPosDeclared = false; |
52 | vFaceDeclared = false; |
53 | centroid = false; |
54 | |
55 | optimize(); |
56 | analyze(); |
57 | } |
58 | |
59 | PixelShader::~PixelShader() |
60 | { |
61 | } |
62 | |
63 | int PixelShader::validate(const unsigned long *const token) |
64 | { |
65 | if(!token) |
66 | { |
67 | return 0; |
68 | } |
69 | |
70 | unsigned short version = (unsigned short)(token[0] & 0x0000FFFF); |
71 | // unsigned char minorVersion = (unsigned char)(token[0] & 0x000000FF); |
72 | unsigned char majorVersion = (unsigned char)((token[0] & 0x0000FF00) >> 8); |
73 | ShaderType shaderType = (ShaderType)((token[0] & 0xFFFF0000) >> 16); |
74 | |
75 | if(shaderType != SHADER_PIXEL || majorVersion > 3) |
76 | { |
77 | return 0; |
78 | } |
79 | |
80 | int instructionCount = 1; |
81 | |
82 | for(int i = 0; token[i] != 0x0000FFFF; i++) |
83 | { |
84 | if((token[i] & 0x0000FFFF) == 0x0000FFFE) // Comment token |
85 | { |
86 | int length = (token[i] & 0x7FFF0000) >> 16; |
87 | |
88 | i += length; |
89 | } |
90 | else |
91 | { |
92 | Shader::Opcode opcode = (Shader::Opcode)(token[i] & 0x0000FFFF); |
93 | |
94 | switch(opcode) |
95 | { |
96 | case Shader::OPCODE_RESERVED0: |
97 | case Shader::OPCODE_MOVA: |
98 | return 0; // Unsupported operation |
99 | default: |
100 | instructionCount++; |
101 | break; |
102 | } |
103 | |
104 | i += size(token[i], version); |
105 | } |
106 | } |
107 | |
108 | return instructionCount; |
109 | } |
110 | |
111 | bool PixelShader::depthOverride() const |
112 | { |
113 | return zOverride; |
114 | } |
115 | |
116 | bool PixelShader::containsKill() const |
117 | { |
118 | return kill; |
119 | } |
120 | |
121 | bool PixelShader::containsCentroid() const |
122 | { |
123 | return centroid; |
124 | } |
125 | |
126 | bool PixelShader::usesDiffuse(int component) const |
127 | { |
128 | return input[0][component].active(); |
129 | } |
130 | |
131 | bool PixelShader::usesSpecular(int component) const |
132 | { |
133 | return input[1][component].active(); |
134 | } |
135 | |
136 | bool PixelShader::usesTexture(int coordinate, int component) const |
137 | { |
138 | return input[2 + coordinate][component].active(); |
139 | } |
140 | |
141 | void PixelShader::setInput(int inputIdx, int nbComponents, const sw::Shader::Semantic& semantic) |
142 | { |
143 | for(int i = 0; i < nbComponents; ++i) |
144 | { |
145 | input[inputIdx][i] = semantic; |
146 | } |
147 | } |
148 | |
149 | const sw::Shader::Semantic& PixelShader::getInput(int inputIdx, int component) const |
150 | { |
151 | return input[inputIdx][component]; |
152 | } |
153 | |
154 | void PixelShader::analyze() |
155 | { |
156 | analyzeZOverride(); |
157 | analyzeKill(); |
158 | analyzeInterpolants(); |
159 | analyzeDirtyConstants(); |
160 | analyzeDynamicBranching(); |
161 | analyzeSamplers(); |
162 | analyzeCallSites(); |
163 | analyzeIndirectAddressing(); |
164 | analyzeLimits(); |
165 | } |
166 | |
167 | void PixelShader::analyzeZOverride() |
168 | { |
169 | zOverride = false; |
170 | |
171 | for(const auto &inst : instruction) |
172 | { |
173 | if(inst->opcode == Shader::OPCODE_TEXM3X2DEPTH || |
174 | inst->opcode == Shader::OPCODE_TEXDEPTH || |
175 | inst->dst.type == Shader::PARAMETER_DEPTHOUT) |
176 | { |
177 | zOverride = true; |
178 | |
179 | break; |
180 | } |
181 | } |
182 | } |
183 | |
184 | void PixelShader::analyzeKill() |
185 | { |
186 | kill = false; |
187 | |
188 | for(const auto &inst : instruction) |
189 | { |
190 | if(inst->opcode == Shader::OPCODE_TEXKILL || |
191 | inst->opcode == Shader::OPCODE_DISCARD) |
192 | { |
193 | kill = true; |
194 | |
195 | break; |
196 | } |
197 | } |
198 | } |
199 | |
200 | void PixelShader::analyzeInterpolants() |
201 | { |
202 | if(shaderModel < 0x0300) |
203 | { |
204 | // Set default mapping; disable unused interpolants below |
205 | input[0][0] = Semantic(Shader::USAGE_COLOR, 0); |
206 | input[0][1] = Semantic(Shader::USAGE_COLOR, 0); |
207 | input[0][2] = Semantic(Shader::USAGE_COLOR, 0); |
208 | input[0][3] = Semantic(Shader::USAGE_COLOR, 0); |
209 | |
210 | input[1][0] = Semantic(Shader::USAGE_COLOR, 1); |
211 | input[1][1] = Semantic(Shader::USAGE_COLOR, 1); |
212 | input[1][2] = Semantic(Shader::USAGE_COLOR, 1); |
213 | input[1][3] = Semantic(Shader::USAGE_COLOR, 1); |
214 | |
215 | for(int i = 0; i < 8; i++) |
216 | { |
217 | input[2 + i][0] = Semantic(Shader::USAGE_TEXCOORD, i); |
218 | input[2 + i][1] = Semantic(Shader::USAGE_TEXCOORD, i); |
219 | input[2 + i][2] = Semantic(Shader::USAGE_TEXCOORD, i); |
220 | input[2 + i][3] = Semantic(Shader::USAGE_TEXCOORD, i); |
221 | } |
222 | |
223 | Shader::SamplerType samplerType[16]; |
224 | |
225 | for(int i = 0; i < 16; i++) |
226 | { |
227 | samplerType[i] = Shader::SAMPLER_UNKNOWN; |
228 | } |
229 | |
230 | for(const auto &inst : instruction) |
231 | { |
232 | if(inst->dst.type == Shader::PARAMETER_SAMPLER) |
233 | { |
234 | int sampler = inst->dst.index; |
235 | |
236 | samplerType[sampler] = inst->samplerType; |
237 | } |
238 | } |
239 | |
240 | bool interpolant[MAX_FRAGMENT_INPUTS][4] = {{false}}; // Interpolants in use |
241 | |
242 | for(const auto &inst : instruction) |
243 | { |
244 | if(inst->dst.type == Shader::PARAMETER_TEXTURE) |
245 | { |
246 | int index = inst->dst.index + 2; |
247 | |
248 | switch(inst->opcode) |
249 | { |
250 | case Shader::OPCODE_TEX: |
251 | case Shader::OPCODE_TEXBEM: |
252 | case Shader::OPCODE_TEXBEML: |
253 | case Shader::OPCODE_TEXCOORD: |
254 | case Shader::OPCODE_TEXDP3: |
255 | case Shader::OPCODE_TEXDP3TEX: |
256 | case Shader::OPCODE_TEXM3X2DEPTH: |
257 | case Shader::OPCODE_TEXM3X2PAD: |
258 | case Shader::OPCODE_TEXM3X2TEX: |
259 | case Shader::OPCODE_TEXM3X3: |
260 | case Shader::OPCODE_TEXM3X3PAD: |
261 | case Shader::OPCODE_TEXM3X3TEX: |
262 | interpolant[index][0] = true; |
263 | interpolant[index][1] = true; |
264 | interpolant[index][2] = true; |
265 | break; |
266 | case Shader::OPCODE_TEXKILL: |
267 | if(majorVersion < 2) |
268 | { |
269 | interpolant[index][0] = true; |
270 | interpolant[index][1] = true; |
271 | interpolant[index][2] = true; |
272 | } |
273 | else |
274 | { |
275 | interpolant[index][0] = true; |
276 | interpolant[index][1] = true; |
277 | interpolant[index][2] = true; |
278 | interpolant[index][3] = true; |
279 | } |
280 | break; |
281 | case Shader::OPCODE_TEXM3X3VSPEC: |
282 | interpolant[index][0] = true; |
283 | interpolant[index][1] = true; |
284 | interpolant[index][2] = true; |
285 | interpolant[index - 2][3] = true; |
286 | interpolant[index - 1][3] = true; |
287 | interpolant[index - 0][3] = true; |
288 | break; |
289 | case Shader::OPCODE_DCL: |
290 | break; // Ignore |
291 | default: // Arithmetic instruction |
292 | if(shaderModel >= 0x0104) |
293 | { |
294 | ASSERT(false); |
295 | } |
296 | } |
297 | } |
298 | |
299 | for(int argument = 0; argument < 4; argument++) |
300 | { |
301 | if(inst->src[argument].type == Shader::PARAMETER_INPUT || |
302 | inst->src[argument].type == Shader::PARAMETER_TEXTURE) |
303 | { |
304 | int index = inst->src[argument].index; |
305 | int swizzle = inst->src[argument].swizzle; |
306 | int mask = inst->dst.mask; |
307 | |
308 | if(inst->src[argument].type == Shader::PARAMETER_TEXTURE) |
309 | { |
310 | index += 2; |
311 | } |
312 | |
313 | switch(inst->opcode) |
314 | { |
315 | case Shader::OPCODE_TEX: |
316 | case Shader::OPCODE_TEXLDD: |
317 | case Shader::OPCODE_TEXLDL: |
318 | case Shader::OPCODE_TEXLOD: |
319 | case Shader::OPCODE_TEXBIAS: |
320 | case Shader::OPCODE_TEXOFFSET: |
321 | case Shader::OPCODE_TEXOFFSETBIAS: |
322 | case Shader::OPCODE_TEXLODOFFSET: |
323 | case Shader::OPCODE_TEXELFETCH: |
324 | case Shader::OPCODE_TEXELFETCHOFFSET: |
325 | case Shader::OPCODE_TEXGRAD: |
326 | case Shader::OPCODE_TEXGRADOFFSET: |
327 | { |
328 | int sampler = inst->src[1].index; |
329 | |
330 | switch(samplerType[sampler]) |
331 | { |
332 | case Shader::SAMPLER_UNKNOWN: |
333 | if(shaderModel == 0x0104) |
334 | { |
335 | if((inst->src[0].swizzle & 0x30) == 0x20) // .xyz |
336 | { |
337 | interpolant[index][0] = true; |
338 | interpolant[index][1] = true; |
339 | interpolant[index][2] = true; |
340 | } |
341 | else // .xyw |
342 | { |
343 | interpolant[index][0] = true; |
344 | interpolant[index][1] = true; |
345 | interpolant[index][3] = true; |
346 | } |
347 | } |
348 | else |
349 | { |
350 | ASSERT(false); |
351 | } |
352 | break; |
353 | case Shader::SAMPLER_1D: |
354 | interpolant[index][0] = true; |
355 | break; |
356 | case Shader::SAMPLER_2D: |
357 | interpolant[index][0] = true; |
358 | interpolant[index][1] = true; |
359 | break; |
360 | case Shader::SAMPLER_CUBE: |
361 | interpolant[index][0] = true; |
362 | interpolant[index][1] = true; |
363 | interpolant[index][2] = true; |
364 | break; |
365 | case Shader::SAMPLER_VOLUME: |
366 | interpolant[index][0] = true; |
367 | interpolant[index][1] = true; |
368 | interpolant[index][2] = true; |
369 | break; |
370 | default: |
371 | ASSERT(false); |
372 | } |
373 | |
374 | if(inst->bias) |
375 | { |
376 | interpolant[index][3] = true; |
377 | } |
378 | |
379 | if(inst->project) |
380 | { |
381 | interpolant[index][3] = true; |
382 | } |
383 | |
384 | if(shaderModel == 0x0104 && inst->opcode == Shader::OPCODE_TEX) |
385 | { |
386 | if(inst->src[0].modifier == Shader::MODIFIER_DZ) |
387 | { |
388 | interpolant[index][2] = true; |
389 | } |
390 | |
391 | if(inst->src[0].modifier == Shader::MODIFIER_DW) |
392 | { |
393 | interpolant[index][3] = true; |
394 | } |
395 | } |
396 | } |
397 | break; |
398 | case Shader::OPCODE_M3X2: |
399 | if(mask & 0x1) |
400 | { |
401 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
402 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
403 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
404 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
405 | } |
406 | |
407 | if(argument == 1) |
408 | { |
409 | if(mask & 0x2) |
410 | { |
411 | interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
412 | interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
413 | interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
414 | interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
415 | } |
416 | } |
417 | break; |
418 | case Shader::OPCODE_M3X3: |
419 | if(mask & 0x1) |
420 | { |
421 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
422 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
423 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
424 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
425 | } |
426 | |
427 | if(argument == 1) |
428 | { |
429 | if(mask & 0x2) |
430 | { |
431 | interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
432 | interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
433 | interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
434 | interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
435 | } |
436 | |
437 | if(mask & 0x4) |
438 | { |
439 | interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
440 | interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
441 | interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
442 | interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
443 | } |
444 | } |
445 | break; |
446 | case Shader::OPCODE_M3X4: |
447 | if(mask & 0x1) |
448 | { |
449 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
450 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
451 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
452 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
453 | } |
454 | |
455 | if(argument == 1) |
456 | { |
457 | if(mask & 0x2) |
458 | { |
459 | interpolant[index + 1][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
460 | interpolant[index + 1][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
461 | interpolant[index + 1][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
462 | interpolant[index + 1][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
463 | } |
464 | |
465 | if(mask & 0x4) |
466 | { |
467 | interpolant[index + 2][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
468 | interpolant[index + 2][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
469 | interpolant[index + 2][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
470 | interpolant[index + 2][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
471 | } |
472 | |
473 | if(mask & 0x8) |
474 | { |
475 | interpolant[index + 3][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
476 | interpolant[index + 3][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
477 | interpolant[index + 3][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
478 | interpolant[index + 3][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
479 | } |
480 | } |
481 | break; |
482 | case Shader::OPCODE_M4X3: |
483 | if(mask & 0x1) |
484 | { |
485 | interpolant[index][0] |= swizzleContainsComponent(swizzle, 0); |
486 | interpolant[index][1] |= swizzleContainsComponent(swizzle, 1); |
487 | interpolant[index][2] |= swizzleContainsComponent(swizzle, 2); |
488 | interpolant[index][3] |= swizzleContainsComponent(swizzle, 3); |
489 | } |
490 | |
491 | if(argument == 1) |
492 | { |
493 | if(mask & 0x2) |
494 | { |
495 | interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0); |
496 | interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1); |
497 | interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2); |
498 | interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3); |
499 | } |
500 | |
501 | if(mask & 0x4) |
502 | { |
503 | interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0); |
504 | interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1); |
505 | interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2); |
506 | interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3); |
507 | } |
508 | } |
509 | break; |
510 | case Shader::OPCODE_M4X4: |
511 | if(mask & 0x1) |
512 | { |
513 | interpolant[index][0] |= swizzleContainsComponent(swizzle, 0); |
514 | interpolant[index][1] |= swizzleContainsComponent(swizzle, 1); |
515 | interpolant[index][2] |= swizzleContainsComponent(swizzle, 2); |
516 | interpolant[index][3] |= swizzleContainsComponent(swizzle, 3); |
517 | } |
518 | |
519 | if(argument == 1) |
520 | { |
521 | if(mask & 0x2) |
522 | { |
523 | interpolant[index + 1][0] |= swizzleContainsComponent(swizzle, 0); |
524 | interpolant[index + 1][1] |= swizzleContainsComponent(swizzle, 1); |
525 | interpolant[index + 1][2] |= swizzleContainsComponent(swizzle, 2); |
526 | interpolant[index + 1][3] |= swizzleContainsComponent(swizzle, 3); |
527 | } |
528 | |
529 | if(mask & 0x4) |
530 | { |
531 | interpolant[index + 2][0] |= swizzleContainsComponent(swizzle, 0); |
532 | interpolant[index + 2][1] |= swizzleContainsComponent(swizzle, 1); |
533 | interpolant[index + 2][2] |= swizzleContainsComponent(swizzle, 2); |
534 | interpolant[index + 2][3] |= swizzleContainsComponent(swizzle, 3); |
535 | } |
536 | |
537 | if(mask & 0x8) |
538 | { |
539 | interpolant[index + 3][0] |= swizzleContainsComponent(swizzle, 0); |
540 | interpolant[index + 3][1] |= swizzleContainsComponent(swizzle, 1); |
541 | interpolant[index + 3][2] |= swizzleContainsComponent(swizzle, 2); |
542 | interpolant[index + 3][3] |= swizzleContainsComponent(swizzle, 3); |
543 | } |
544 | } |
545 | break; |
546 | case Shader::OPCODE_CRS: |
547 | if(mask & 0x1) |
548 | { |
549 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x6); |
550 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x6); |
551 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x6); |
552 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x6); |
553 | } |
554 | |
555 | if(mask & 0x2) |
556 | { |
557 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x5); |
558 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x5); |
559 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x5); |
560 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x5); |
561 | } |
562 | |
563 | if(mask & 0x4) |
564 | { |
565 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3); |
566 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3); |
567 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3); |
568 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3); |
569 | } |
570 | break; |
571 | case Shader::OPCODE_DP2ADD: |
572 | if(argument == 0 || argument == 1) |
573 | { |
574 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x3); |
575 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x3); |
576 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x3); |
577 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x3); |
578 | } |
579 | else // argument == 2 |
580 | { |
581 | interpolant[index][0] |= swizzleContainsComponent(swizzle, 0); |
582 | interpolant[index][1] |= swizzleContainsComponent(swizzle, 1); |
583 | interpolant[index][2] |= swizzleContainsComponent(swizzle, 2); |
584 | interpolant[index][3] |= swizzleContainsComponent(swizzle, 3); |
585 | } |
586 | break; |
587 | case Shader::OPCODE_DP3: |
588 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7); |
589 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7); |
590 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7); |
591 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7); |
592 | break; |
593 | case Shader::OPCODE_DP4: |
594 | interpolant[index][0] |= swizzleContainsComponent(swizzle, 0); |
595 | interpolant[index][1] |= swizzleContainsComponent(swizzle, 1); |
596 | interpolant[index][2] |= swizzleContainsComponent(swizzle, 2); |
597 | interpolant[index][3] |= swizzleContainsComponent(swizzle, 3); |
598 | break; |
599 | case Shader::OPCODE_SINCOS: |
600 | case Shader::OPCODE_EXP2X: |
601 | case Shader::OPCODE_LOG2X: |
602 | case Shader::OPCODE_POWX: |
603 | case Shader::OPCODE_RCPX: |
604 | case Shader::OPCODE_RSQX: |
605 | interpolant[index][0] |= swizzleContainsComponent(swizzle, 0); |
606 | interpolant[index][1] |= swizzleContainsComponent(swizzle, 1); |
607 | interpolant[index][2] |= swizzleContainsComponent(swizzle, 2); |
608 | interpolant[index][3] |= swizzleContainsComponent(swizzle, 3); |
609 | break; |
610 | case Shader::OPCODE_NRM3: |
611 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, 0x7 | mask); |
612 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, 0x7 | mask); |
613 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, 0x7 | mask); |
614 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, 0x7 | mask); |
615 | break; |
616 | case Shader::OPCODE_MOV: |
617 | case Shader::OPCODE_ADD: |
618 | case Shader::OPCODE_SUB: |
619 | case Shader::OPCODE_MUL: |
620 | case Shader::OPCODE_MAD: |
621 | case Shader::OPCODE_ABS: |
622 | case Shader::OPCODE_CMP0: |
623 | case Shader::OPCODE_CND: |
624 | case Shader::OPCODE_FRC: |
625 | case Shader::OPCODE_LRP: |
626 | case Shader::OPCODE_MAX: |
627 | case Shader::OPCODE_MIN: |
628 | case Shader::OPCODE_CMP: |
629 | case Shader::OPCODE_BREAKC: |
630 | case Shader::OPCODE_DFDX: |
631 | case Shader::OPCODE_DFDY: |
632 | interpolant[index][0] |= swizzleContainsComponentMasked(swizzle, 0, mask); |
633 | interpolant[index][1] |= swizzleContainsComponentMasked(swizzle, 1, mask); |
634 | interpolant[index][2] |= swizzleContainsComponentMasked(swizzle, 2, mask); |
635 | interpolant[index][3] |= swizzleContainsComponentMasked(swizzle, 3, mask); |
636 | break; |
637 | case Shader::OPCODE_TEXCOORD: |
638 | interpolant[index][0] = true; |
639 | interpolant[index][1] = true; |
640 | interpolant[index][2] = true; |
641 | interpolant[index][3] = true; |
642 | break; |
643 | case Shader::OPCODE_TEXDP3: |
644 | case Shader::OPCODE_TEXDP3TEX: |
645 | case Shader::OPCODE_TEXM3X2PAD: |
646 | case Shader::OPCODE_TEXM3X3PAD: |
647 | case Shader::OPCODE_TEXM3X2TEX: |
648 | case Shader::OPCODE_TEXM3X3SPEC: |
649 | case Shader::OPCODE_TEXM3X3VSPEC: |
650 | case Shader::OPCODE_TEXBEM: |
651 | case Shader::OPCODE_TEXBEML: |
652 | case Shader::OPCODE_TEXM3X2DEPTH: |
653 | case Shader::OPCODE_TEXM3X3: |
654 | case Shader::OPCODE_TEXM3X3TEX: |
655 | interpolant[index][0] = true; |
656 | interpolant[index][1] = true; |
657 | interpolant[index][2] = true; |
658 | break; |
659 | case Shader::OPCODE_TEXREG2AR: |
660 | case Shader::OPCODE_TEXREG2GB: |
661 | case Shader::OPCODE_TEXREG2RGB: |
662 | break; |
663 | default: |
664 | // ASSERT(false); // Refine component usage |
665 | interpolant[index][0] = true; |
666 | interpolant[index][1] = true; |
667 | interpolant[index][2] = true; |
668 | interpolant[index][3] = true; |
669 | } |
670 | } |
671 | } |
672 | } |
673 | |
674 | for(int index = 0; index < MAX_FRAGMENT_INPUTS; index++) |
675 | { |
676 | for(int component = 0; component < 4; component++) |
677 | { |
678 | if(!interpolant[index][component]) |
679 | { |
680 | input[index][component] = Semantic(); |
681 | } |
682 | } |
683 | } |
684 | } |
685 | else // Shader Model 3.0 input declaration; v# indexable |
686 | { |
687 | for(const auto &inst : instruction) |
688 | { |
689 | if(inst->opcode == Shader::OPCODE_DCL) |
690 | { |
691 | if(inst->dst.type == Shader::PARAMETER_INPUT) |
692 | { |
693 | unsigned char usage = inst->usage; |
694 | unsigned char index = inst->usageIndex; |
695 | unsigned char mask = inst->dst.mask; |
696 | unsigned char reg = inst->dst.index; |
697 | |
698 | if(mask & 0x01) input[reg][0] = Semantic(usage, index); |
699 | if(mask & 0x02) input[reg][1] = Semantic(usage, index); |
700 | if(mask & 0x04) input[reg][2] = Semantic(usage, index); |
701 | if(mask & 0x08) input[reg][3] = Semantic(usage, index); |
702 | } |
703 | else if(inst->dst.type == Shader::PARAMETER_MISCTYPE) |
704 | { |
705 | unsigned char index = inst->dst.index; |
706 | |
707 | if(index == Shader::VPosIndex) |
708 | { |
709 | vPosDeclared = true; |
710 | } |
711 | else if(index == Shader::VFaceIndex) |
712 | { |
713 | vFaceDeclared = true; |
714 | } |
715 | else ASSERT(false); |
716 | } |
717 | } |
718 | } |
719 | } |
720 | |
721 | if(shaderModel >= 0x0200) |
722 | { |
723 | for(const auto &inst : instruction) |
724 | { |
725 | if(inst->opcode == Shader::OPCODE_DCL) |
726 | { |
727 | bool centroid = inst->dst.centroid; |
728 | unsigned char reg = inst->dst.index; |
729 | |
730 | switch(inst->dst.type) |
731 | { |
732 | case Shader::PARAMETER_INPUT: |
733 | input[reg][0].centroid = centroid; |
734 | break; |
735 | case Shader::PARAMETER_TEXTURE: |
736 | input[2 + reg][0].centroid = centroid; |
737 | break; |
738 | default: |
739 | break; |
740 | } |
741 | |
742 | this->centroid = this->centroid || centroid; |
743 | } |
744 | } |
745 | } |
746 | } |
747 | } |
748 | |