Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/codegen/nv50_ir_target_nv50.cpp
4574 views
1
/*
2
* Copyright 2011 Christoph Bumiller
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
* OTHER DEALINGS IN THE SOFTWARE.
21
*/
22
23
#include "codegen/nv50_ir_target_nv50.h"
24
25
namespace nv50_ir {
26
27
Target *getTargetNV50(unsigned int chipset)
28
{
29
return new TargetNV50(chipset);
30
}
31
32
TargetNV50::TargetNV50(unsigned int card) : Target(true, true, false)
33
{
34
chipset = card;
35
36
wposMask = 0;
37
for (unsigned int i = 0; i <= SV_LAST; ++i)
38
sysvalLocation[i] = ~0;
39
40
initOpInfo();
41
}
42
43
#if 0
44
// BULTINS / LIBRARY FUNCTIONS:
45
46
// TODO
47
static const uint32_t nvc0_builtin_code[] =
48
{
49
};
50
51
static const uint16_t nvc0_builtin_offsets[NV50_BUILTIN_COUNT] =
52
{
53
};
54
#endif
55
56
void
57
TargetNV50::getBuiltinCode(const uint32_t **code, uint32_t *size) const
58
{
59
*code = NULL;
60
*size = 0;
61
}
62
63
uint32_t
64
TargetNV50::getBuiltinOffset(int builtin) const
65
{
66
return 0;
67
}
68
69
struct nv50_opProperties
70
{
71
operation op;
72
unsigned int mNeg : 4;
73
unsigned int mAbs : 4;
74
unsigned int mNot : 4;
75
unsigned int mSat : 4;
76
unsigned int fConst : 3;
77
unsigned int fShared : 3;
78
unsigned int fAttrib : 3;
79
unsigned int fImm : 3;
80
};
81
82
static const struct nv50_opProperties _initProps[] =
83
{
84
// neg abs not sat c[] s[], a[], imm
85
{ OP_ADD, 0x3, 0x0, 0x0, 0x8, 0x2, 0x1, 0x1, 0x2 },
86
{ OP_SUB, 0x3, 0x0, 0x0, 0x8, 0x2, 0x1, 0x1, 0x2 },
87
{ OP_MUL, 0x3, 0x0, 0x0, 0x0, 0x2, 0x1, 0x1, 0x2 },
88
{ OP_MAX, 0x3, 0x3, 0x0, 0x0, 0x2, 0x1, 0x1, 0x0 },
89
{ OP_MIN, 0x3, 0x3, 0x0, 0x0, 0x2, 0x1, 0x1, 0x0 },
90
{ OP_MAD, 0x7, 0x0, 0x0, 0x8, 0x6, 0x1, 0x1, 0x0 }, // special constraint
91
{ OP_ABS, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0 },
92
{ OP_NEG, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0 },
93
{ OP_CVT, 0x1, 0x1, 0x0, 0x8, 0x0, 0x1, 0x1, 0x0 },
94
{ OP_AND, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x2 },
95
{ OP_OR, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x2 },
96
{ OP_XOR, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x2 },
97
{ OP_SHL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 },
98
{ OP_SHR, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 },
99
{ OP_SET, 0x3, 0x3, 0x0, 0x0, 0x2, 0x1, 0x1, 0x0 },
100
{ OP_PREEX2, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
101
{ OP_PRESIN, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
102
{ OP_EX2, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0 },
103
{ OP_LG2, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
104
{ OP_RCP, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
105
{ OP_RSQ, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
106
{ OP_DFDX, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
107
{ OP_DFDY, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
108
};
109
110
void TargetNV50::initOpInfo()
111
{
112
unsigned int i, j;
113
114
static const operation commutativeList[] =
115
{
116
OP_ADD, OP_MUL, OP_MAD, OP_FMA, OP_AND, OP_OR, OP_XOR, OP_MAX, OP_MIN,
117
OP_SET_AND, OP_SET_OR, OP_SET_XOR, OP_SET, OP_SELP, OP_SLCT
118
};
119
static const operation shortFormList[] =
120
{
121
OP_MOV, OP_ADD, OP_SUB, OP_MUL, OP_MAD, OP_SAD, OP_RCP, OP_LINTERP,
122
OP_PINTERP, OP_TEX, OP_TXF
123
};
124
static const operation noDestList[] =
125
{
126
OP_STORE, OP_WRSV, OP_EXPORT, OP_BRA, OP_CALL, OP_RET, OP_EXIT,
127
OP_DISCARD, OP_CONT, OP_BREAK, OP_PRECONT, OP_PREBREAK, OP_PRERET,
128
OP_JOIN, OP_JOINAT, OP_BRKPT, OP_MEMBAR, OP_EMIT, OP_RESTART,
129
OP_QUADON, OP_QUADPOP, OP_TEXBAR, OP_SUSTB, OP_SUSTP, OP_SUREDP,
130
OP_SUREDB, OP_BAR
131
};
132
static const operation noPredList[] =
133
{
134
OP_CALL, OP_PREBREAK, OP_PRERET, OP_QUADON, OP_QUADPOP, OP_JOINAT,
135
OP_EMIT, OP_RESTART
136
};
137
138
for (i = 0; i < DATA_FILE_COUNT; ++i)
139
nativeFileMap[i] = (DataFile)i;
140
nativeFileMap[FILE_PREDICATE] = FILE_FLAGS;
141
142
for (i = 0; i < OP_LAST; ++i) {
143
opInfo[i].variants = NULL;
144
opInfo[i].op = (operation)i;
145
opInfo[i].srcTypes = 1 << (int)TYPE_F32;
146
opInfo[i].dstTypes = 1 << (int)TYPE_F32;
147
opInfo[i].immdBits = 0xffffffff;
148
opInfo[i].srcNr = operationSrcNr[i];
149
150
for (j = 0; j < opInfo[i].srcNr; ++j) {
151
opInfo[i].srcMods[j] = 0;
152
opInfo[i].srcFiles[j] = 1 << (int)FILE_GPR;
153
}
154
opInfo[i].dstMods = 0;
155
opInfo[i].dstFiles = 1 << (int)FILE_GPR;
156
157
opInfo[i].hasDest = 1;
158
opInfo[i].vector = (i >= OP_TEX && i <= OP_TEXCSAA);
159
opInfo[i].commutative = false; /* set below */
160
opInfo[i].pseudo = (i < OP_MOV);
161
opInfo[i].predicate = !opInfo[i].pseudo;
162
opInfo[i].flow = (i >= OP_BRA && i <= OP_JOIN);
163
opInfo[i].minEncSize = 8; /* set below */
164
}
165
for (i = 0; i < ARRAY_SIZE(commutativeList); ++i)
166
opInfo[commutativeList[i]].commutative = true;
167
for (i = 0; i < ARRAY_SIZE(shortFormList); ++i)
168
opInfo[shortFormList[i]].minEncSize = 4;
169
for (i = 0; i < ARRAY_SIZE(noDestList); ++i)
170
opInfo[noDestList[i]].hasDest = 0;
171
for (i = 0; i < ARRAY_SIZE(noPredList); ++i)
172
opInfo[noPredList[i]].predicate = 0;
173
174
for (i = 0; i < ARRAY_SIZE(_initProps); ++i) {
175
const struct nv50_opProperties *prop = &_initProps[i];
176
177
for (int s = 0; s < 3; ++s) {
178
if (prop->mNeg & (1 << s))
179
opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_NEG;
180
if (prop->mAbs & (1 << s))
181
opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_ABS;
182
if (prop->mNot & (1 << s))
183
opInfo[prop->op].srcMods[s] |= NV50_IR_MOD_NOT;
184
if (prop->fConst & (1 << s))
185
opInfo[prop->op].srcFiles[s] |= 1 << (int)FILE_MEMORY_CONST;
186
if (prop->fShared & (1 << s))
187
opInfo[prop->op].srcFiles[s] |= 1 << (int)FILE_MEMORY_SHARED;
188
if (prop->fAttrib & (1 << s))
189
opInfo[prop->op].srcFiles[s] |= 1 << (int)FILE_SHADER_INPUT;
190
if (prop->fImm & (1 << s))
191
opInfo[prop->op].srcFiles[s] |= 1 << (int)FILE_IMMEDIATE;
192
}
193
if (prop->mSat & 8)
194
opInfo[prop->op].dstMods = NV50_IR_MOD_SAT;
195
}
196
197
if (chipset >= 0xa0)
198
opInfo[OP_MUL].dstMods = NV50_IR_MOD_SAT;
199
}
200
201
unsigned int
202
TargetNV50::getFileSize(DataFile file) const
203
{
204
switch (file) {
205
case FILE_NULL: return 0;
206
case FILE_GPR: return 254; // in 16-bit units **
207
case FILE_PREDICATE: return 0;
208
case FILE_FLAGS: return 4;
209
case FILE_ADDRESS: return 4;
210
case FILE_BARRIER: return 0;
211
case FILE_IMMEDIATE: return 0;
212
case FILE_MEMORY_CONST: return 65536;
213
case FILE_SHADER_INPUT: return 0x200;
214
case FILE_SHADER_OUTPUT: return 0x200;
215
case FILE_MEMORY_BUFFER: return 0xffffffff;
216
case FILE_MEMORY_GLOBAL: return 0xffffffff;
217
case FILE_MEMORY_SHARED: return 16 << 10;
218
case FILE_MEMORY_LOCAL: return 48 << 10;
219
case FILE_SYSTEM_VALUE: return 16;
220
default:
221
assert(!"invalid file");
222
return 0;
223
}
224
// ** only first 128 units encodable for 16-bit regs
225
}
226
227
unsigned int
228
TargetNV50::getFileUnit(DataFile file) const
229
{
230
if (file == FILE_GPR || file == FILE_ADDRESS)
231
return 1;
232
if (file == FILE_SYSTEM_VALUE)
233
return 2;
234
return 0;
235
}
236
237
uint32_t
238
TargetNV50::getSVAddress(DataFile shaderFile, const Symbol *sym) const
239
{
240
switch (sym->reg.data.sv.sv) {
241
case SV_FACE:
242
return 0x3fc;
243
case SV_POSITION:
244
{
245
uint32_t addr = sysvalLocation[sym->reg.data.sv.sv];
246
for (int c = 0; c < sym->reg.data.sv.index; ++c)
247
if (wposMask & (1 << c))
248
addr += 4;
249
return addr;
250
}
251
case SV_PRIMITIVE_ID:
252
return shaderFile == FILE_SHADER_INPUT ? 0x18 :
253
sysvalLocation[sym->reg.data.sv.sv];
254
case SV_NCTAID:
255
return sym->reg.data.sv.index >= 2 ? 0x10 : 0x8 + 2 * sym->reg.data.sv.index;
256
case SV_CTAID:
257
return sym->reg.data.sv.index >= 2 ? 0x12 : 0xc + 2 * sym->reg.data.sv.index;
258
case SV_NTID:
259
return 0x2 + 2 * sym->reg.data.sv.index;
260
case SV_TID:
261
case SV_COMBINED_TID:
262
return 0;
263
case SV_SAMPLE_POS:
264
return 0; /* sample position is handled differently */
265
case SV_THREAD_KILL:
266
return 0;
267
default:
268
return sysvalLocation[sym->reg.data.sv.sv];
269
}
270
}
271
272
// long: rrr, arr, rcr, acr, rrc, arc, gcr, grr
273
// short: rr, ar, rc, gr
274
// immd: ri, gi
275
bool
276
TargetNV50::insnCanLoad(const Instruction *i, int s,
277
const Instruction *ld) const
278
{
279
DataFile sf = ld->src(0).getFile();
280
281
// immediate 0 can be represented by GPR $r63/$r127
282
// this does not work with global memory ld/st/atom
283
if (sf == FILE_IMMEDIATE && ld->getSrc(0)->reg.data.u64 == 0)
284
return (!i->isPseudo() &&
285
!i->asTex() &&
286
i->op != OP_EXPORT &&
287
i->op != OP_STORE &&
288
((i->op != OP_ATOM && i->op != OP_LOAD) ||
289
i->src(0).getFile() != FILE_MEMORY_GLOBAL));
290
291
if (sf == FILE_IMMEDIATE && (i->predSrc >= 0 || i->flagsDef >= 0))
292
return false;
293
if (s >= opInfo[i->op].srcNr)
294
return false;
295
if (!(opInfo[i->op].srcFiles[s] & (1 << (int)sf)))
296
return false;
297
if (s == 2 && i->src(1).getFile() != FILE_GPR)
298
return false;
299
300
// NOTE: don't rely on flagsDef
301
if (sf == FILE_IMMEDIATE)
302
for (int d = 0; i->defExists(d); ++d)
303
if (i->def(d).getFile() == FILE_FLAGS)
304
return false;
305
306
unsigned mode = 0;
307
308
for (int z = 0; z < Target::operationSrcNr[i->op]; ++z) {
309
DataFile zf = (z == s) ? sf : i->src(z).getFile();
310
switch (zf) {
311
case FILE_GPR:
312
break;
313
case FILE_MEMORY_SHARED:
314
case FILE_SHADER_INPUT:
315
mode |= 1 << (z * 2);
316
break;
317
case FILE_MEMORY_CONST:
318
mode |= 2 << (z * 2);
319
break;
320
case FILE_IMMEDIATE:
321
mode |= 3 << (z * 2);
322
default:
323
break;
324
}
325
}
326
327
switch (mode) {
328
case 0x00:
329
case 0x01:
330
case 0x03:
331
case 0x08:
332
case 0x0c:
333
case 0x20:
334
case 0x21:
335
break;
336
case 0x09:
337
// Shader inputs get transformed to p[] in geometry shaders, and those
338
// aren't allowed to be used at the same time as c[].
339
if (ld->bb->getProgram()->getType() == Program::TYPE_GEOMETRY)
340
return false;
341
break;
342
case 0x0d:
343
if (ld->bb->getProgram()->getType() != Program::TYPE_GEOMETRY)
344
return false;
345
break;
346
default:
347
return false;
348
}
349
350
uint8_t ldSize;
351
352
if ((i->op == OP_MUL || i->op == OP_MAD) && !isFloatType(i->dType)) {
353
// 32-bit MUL will be split into 16-bit MULs
354
if (ld->src(0).isIndirect(0))
355
return false;
356
if (sf == FILE_IMMEDIATE)
357
return false;
358
if (i->subOp == NV50_IR_SUBOP_MUL_HIGH && sf == FILE_MEMORY_CONST)
359
return false;
360
ldSize = 2;
361
} else {
362
ldSize = typeSizeof(ld->dType);
363
}
364
365
if (sf == FILE_IMMEDIATE) {
366
if (ldSize == 2 && (i->op == OP_AND || i->op == OP_OR || i->op == OP_XOR))
367
return false;
368
return ldSize <= 4;
369
}
370
371
372
// Check if memory access is encodable:
373
374
if (ldSize < 4 && sf == FILE_SHADER_INPUT) // no < 4-byte aligned a[] access
375
return false;
376
if (ld->getSrc(0)->reg.data.offset > (int32_t)(127 * ldSize))
377
return false;
378
379
if (ld->src(0).isIndirect(0)) {
380
for (int z = 0; i->srcExists(z); ++z)
381
if (i->src(z).isIndirect(0))
382
return false;
383
384
// s[] access only possible in CP, $aX always applies
385
if (sf == FILE_MEMORY_SHARED)
386
return true;
387
if (!ld->bb) // can't check type ...
388
return false;
389
Program::Type pt = ld->bb->getProgram()->getType();
390
391
// $aX applies to c[] only in VP, FP, GP if p[] is not accessed
392
if (pt == Program::TYPE_COMPUTE)
393
return false;
394
if (pt == Program::TYPE_GEOMETRY) {
395
if (sf == FILE_MEMORY_CONST)
396
return i->src(s).getFile() != FILE_SHADER_INPUT;
397
return sf == FILE_SHADER_INPUT;
398
}
399
return sf == FILE_MEMORY_CONST;
400
}
401
return true;
402
}
403
404
bool
405
TargetNV50::insnCanLoadOffset(const Instruction *i, int s, int offset) const
406
{
407
if (!i->src(s).isIndirect(0))
408
return true;
409
offset += i->src(s).get()->reg.data.offset;
410
if (i->op == OP_LOAD || i->op == OP_STORE || i->op == OP_ATOM) {
411
// There are some restrictions in theory, but in practice they're never
412
// going to be hit. However offsets on global/shared memory are just
413
// plain not supported.
414
return i->src(s).getFile() != FILE_MEMORY_GLOBAL &&
415
i->src(s).getFile() != FILE_MEMORY_SHARED;
416
}
417
return offset >= 0 && offset <= (int32_t)(127 * i->src(s).get()->reg.size);
418
}
419
420
bool
421
TargetNV50::isAccessSupported(DataFile file, DataType ty) const
422
{
423
if (ty == TYPE_B96 || ty == TYPE_NONE)
424
return false;
425
if (typeSizeof(ty) > 4)
426
return (file == FILE_MEMORY_LOCAL) || (file == FILE_MEMORY_GLOBAL) ||
427
(file == FILE_MEMORY_BUFFER);
428
return true;
429
}
430
431
bool
432
TargetNV50::isOpSupported(operation op, DataType ty) const
433
{
434
if (ty == TYPE_F64 && chipset < 0xa0)
435
return false;
436
437
switch (op) {
438
case OP_PRERET:
439
return chipset >= 0xa0;
440
case OP_TXG:
441
return chipset >= 0xa3 && chipset != 0xaa && chipset != 0xac;
442
case OP_POW:
443
case OP_SQRT:
444
case OP_DIV:
445
case OP_MOD:
446
case OP_SET_AND:
447
case OP_SET_OR:
448
case OP_SET_XOR:
449
case OP_SLCT:
450
case OP_SELP:
451
case OP_POPCNT:
452
case OP_INSBF:
453
case OP_EXTBF:
454
case OP_EXIT: // want exit modifier instead (on NOP if required)
455
case OP_MEMBAR:
456
case OP_SHLADD:
457
case OP_XMAD:
458
return false;
459
case OP_SAD:
460
return ty == TYPE_S32;
461
case OP_SET:
462
return !isFloatType(ty);
463
default:
464
return true;
465
}
466
}
467
468
bool
469
TargetNV50::isModSupported(const Instruction *insn, int s, Modifier mod) const
470
{
471
if (!isFloatType(insn->dType)) {
472
switch (insn->op) {
473
case OP_ABS:
474
case OP_NEG:
475
case OP_CVT:
476
case OP_CEIL:
477
case OP_FLOOR:
478
case OP_TRUNC:
479
case OP_AND:
480
case OP_OR:
481
case OP_XOR:
482
break;
483
case OP_ADD:
484
if (insn->src(s ? 0 : 1).mod.neg())
485
return false;
486
break;
487
case OP_SUB:
488
if (s == 0)
489
return insn->src(1).mod.neg() ? false : true;
490
break;
491
case OP_SET:
492
if (insn->sType != TYPE_F32)
493
return false;
494
break;
495
default:
496
return false;
497
}
498
}
499
if (s >= opInfo[insn->op].srcNr || s >= 3)
500
return false;
501
return (mod & Modifier(opInfo[insn->op].srcMods[s])) == mod;
502
}
503
504
bool
505
TargetNV50::mayPredicate(const Instruction *insn, const Value *pred) const
506
{
507
if (insn->getPredicate() || insn->flagsSrc >= 0)
508
return false;
509
for (int s = 0; insn->srcExists(s); ++s)
510
if (insn->src(s).getFile() == FILE_IMMEDIATE)
511
return false;
512
return opInfo[insn->op].predicate;
513
}
514
515
bool
516
TargetNV50::isSatSupported(const Instruction *insn) const
517
{
518
if (insn->op == OP_CVT)
519
return true;
520
if (insn->dType != TYPE_F32)
521
return false;
522
return opInfo[insn->op].dstMods & NV50_IR_MOD_SAT;
523
}
524
525
int TargetNV50::getLatency(const Instruction *i) const
526
{
527
// TODO: tune these values
528
if (i->op == OP_LOAD) {
529
switch (i->src(0).getFile()) {
530
case FILE_MEMORY_LOCAL:
531
case FILE_MEMORY_GLOBAL:
532
case FILE_MEMORY_BUFFER:
533
return 100; // really 400 to 800
534
default:
535
return 22;
536
}
537
}
538
return 22;
539
}
540
541
// These are "inverse" throughput values, i.e. the number of cycles required
542
// to issue a specific instruction for a full warp (32 threads).
543
//
544
// Assuming we have more than 1 warp in flight, a higher issue latency results
545
// in a lower result latency since the MP will have spent more time with other
546
// warps.
547
// This also helps to determine the number of cycles between instructions in
548
// a single warp.
549
//
550
int TargetNV50::getThroughput(const Instruction *i) const
551
{
552
// TODO: tune these values
553
if (i->dType == TYPE_F32) {
554
switch (i->op) {
555
case OP_RCP:
556
case OP_RSQ:
557
case OP_LG2:
558
case OP_SIN:
559
case OP_COS:
560
case OP_PRESIN:
561
case OP_PREEX2:
562
return 16;
563
default:
564
return 4;
565
}
566
} else
567
if (i->dType == TYPE_U32 || i->dType == TYPE_S32) {
568
return 4;
569
} else
570
if (i->dType == TYPE_F64) {
571
return 32;
572
} else {
573
return 1;
574
}
575
}
576
577
static void
578
recordLocation(uint16_t *locs, uint8_t *masks,
579
const struct nv50_ir_varying *var)
580
{
581
uint16_t addr = var->slot[0] * 4;
582
583
switch (var->sn) {
584
case TGSI_SEMANTIC_POSITION: locs[SV_POSITION] = addr; break;
585
case TGSI_SEMANTIC_INSTANCEID: locs[SV_INSTANCE_ID] = addr; break;
586
case TGSI_SEMANTIC_VERTEXID: locs[SV_VERTEX_ID] = addr; break;
587
case TGSI_SEMANTIC_PRIMID: locs[SV_PRIMITIVE_ID] = addr; break;
588
case TGSI_SEMANTIC_LAYER: locs[SV_LAYER] = addr; break;
589
case TGSI_SEMANTIC_VIEWPORT_INDEX: locs[SV_VIEWPORT_INDEX] = addr; break;
590
default:
591
break;
592
}
593
if (var->sn == TGSI_SEMANTIC_POSITION && masks)
594
masks[0] = var->mask;
595
}
596
597
void
598
TargetNV50::parseDriverInfo(const struct nv50_ir_prog_info *info,
599
const struct nv50_ir_prog_info_out *info_out)
600
{
601
unsigned int i;
602
for (i = 0; i < info_out->numOutputs; ++i)
603
recordLocation(sysvalLocation, NULL, &info_out->out[i]);
604
for (i = 0; i < info_out->numInputs; ++i)
605
recordLocation(sysvalLocation, &wposMask, &info_out->in[i]);
606
for (i = 0; i < info_out->numSysVals; ++i)
607
recordLocation(sysvalLocation, NULL, &info_out->sv[i]);
608
609
if (sysvalLocation[SV_POSITION] >= 0x200) {
610
// not assigned by driver, but we need it internally
611
wposMask = 0x8;
612
sysvalLocation[SV_POSITION] = 0;
613
}
614
615
Target::parseDriverInfo(info, info_out);
616
}
617
618
} // namespace nv50_ir
619
620