955ea4e4e1da925398c4f72de2ba4f9f04937ba5
[mesa.git] / src / mesa / drivers / dri / r600 / r700_shader.c
1 /*
2 * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
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
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22 /*
23 * Authors:
24 * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
25 */
26
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
32
33 #include "main/imports.h"
34
35 #include "main/glheader.h"
36
37 #include "r600_context.h"
38 #include "r700_debug.h"
39
40 #include "r700_shader.h"
41
42 void r700ShaderInit(GLcontext * ctx)
43 {
44 }
45
46 void AddInstToList(TypedShaderList * plstCFInstructions, R700ShaderInstruction * pInst)
47 {
48 if(NULL == plstCFInstructions->pTail)
49 { //first
50 plstCFInstructions->pHead = pInst;
51 plstCFInstructions->pTail = pInst;
52 }
53 else
54 {
55 plstCFInstructions->pTail->pNextInst = pInst;
56 plstCFInstructions->pTail = pInst;
57 }
58 pInst->pNextInst = NULL;
59
60 plstCFInstructions->uNumOfNode++;
61 }
62
63 void TakeInstOutFromList(TypedShaderList * plstCFInstructions, R700ShaderInstruction * pInst)
64 {
65 GLuint ulIndex = 0;
66 GLboolean bFound = GL_FALSE;
67 R700ShaderInstruction * pPrevInst = NULL;
68 R700ShaderInstruction * pCurInst = plstCFInstructions->pHead;
69
70 /* Need go thro list to make sure pInst is there. */
71 while(NULL != pCurInst)
72 {
73 if(pCurInst == pInst)
74 {
75 bFound = GL_TRUE;
76 break;
77 }
78
79 pPrevInst = pCurInst;
80 pCurInst = pCurInst->pNextInst;
81 }
82 if(GL_TRUE == bFound)
83 {
84 plstCFInstructions->uNumOfNode--;
85
86 pCurInst = pInst->pNextInst;
87 ulIndex = pInst->m_uIndex;
88 while(NULL != pCurInst)
89 {
90 pCurInst->m_uIndex = ulIndex;
91 ulIndex++;
92 pCurInst = pCurInst->pNextInst;
93 }
94
95 if(plstCFInstructions->pHead == pInst)
96 {
97 plstCFInstructions->pHead = pInst->pNextInst;
98 }
99 if(plstCFInstructions->pTail == pInst)
100 {
101 plstCFInstructions->pTail = pPrevInst;
102 }
103 if(NULL != pPrevInst)
104 {
105 pPrevInst->pNextInst = pInst->pNextInst;
106 }
107
108 FREE(pInst);
109 }
110 }
111
112 void Init_R700_Shader(R700_Shader * pShader)
113 {
114 pShader->Type = R700_SHADER_INVALID;
115 pShader->pProgram = NULL;
116 pShader->bBinaryShader = GL_FALSE;
117 pShader->bFetchShaderRequired = GL_FALSE;
118 pShader->bNeedsAssembly = GL_FALSE;
119 pShader->bLinksDirty = GL_TRUE;
120 pShader->uShaderBinaryDWORDSize = 0;
121 pShader->nRegs = 0;
122 pShader->nParamExports = 0;
123 pShader->nMemExports = 0;
124 pShader->resource = 0;
125
126 pShader->exportMode = 0;
127 pShader->depthIsImported = GL_FALSE;
128
129 pShader->positionVectorIsExported = GL_FALSE;
130 pShader->miscVectorIsExported = GL_FALSE;
131 pShader->renderTargetArrayIndexIsExported = GL_FALSE;
132 pShader->ccDist0VectorIsExported = GL_FALSE;
133 pShader->ccDist1VectorIsExported = GL_FALSE;
134
135
136 pShader->depthIsExported = GL_FALSE;
137 pShader->stencilRefIsExported = GL_FALSE;
138 pShader->coverageToMaskIsExported = GL_FALSE;
139 pShader->maskIsExported = GL_FALSE;
140 pShader->killIsUsed = GL_FALSE;
141
142 pShader->uCFOffset = 0;
143 pShader->uStackSize = 0;
144 pShader->uMaxCallDepth = 0;
145
146 pShader->bSurfAllocated = GL_FALSE;
147
148 pShader->lstCFInstructions.pHead=NULL;
149 pShader->lstCFInstructions.pTail=NULL;
150 pShader->lstCFInstructions.uNumOfNode=0;
151 pShader->lstALUInstructions.pHead=NULL;
152 pShader->lstALUInstructions.pTail=NULL;
153 pShader->lstALUInstructions.uNumOfNode=0;
154 pShader->lstTEXInstructions.pHead=NULL;
155 pShader->lstTEXInstructions.pTail=NULL;
156 pShader->lstTEXInstructions.uNumOfNode=0;
157 pShader->lstVTXInstructions.pHead=NULL;
158 pShader->lstVTXInstructions.pTail=NULL;
159 pShader->lstVTXInstructions.uNumOfNode=0;
160 }
161
162 void AddCFInstruction(R700_Shader *pShader, R700ControlFlowInstruction *pCFInst)
163 {
164 R700ControlFlowSXClause* pSXClause;
165 R700ControlFlowSMXClause* pSMXClause;
166
167 pCFInst->m_uIndex = pShader->lstCFInstructions.uNumOfNode;
168 AddInstToList(&(pShader->lstCFInstructions),
169 (R700ShaderInstruction*)pCFInst);
170 pShader->uShaderBinaryDWORDSize += GetInstructionSize(pCFInst->m_ShaderInstType);
171
172 pSXClause = NULL;
173 pSMXClause = NULL;
174 switch (pCFInst->m_ShaderInstType)
175 {
176 case SIT_CF_ALL_EXP_SX:
177 pSXClause = (R700ControlFlowSXClause*)pCFInst;
178 break;
179 case SIT_CF_ALL_EXP_SMX:
180 pSMXClause = (R700ControlFlowSMXClause*)pCFInst;
181 break;
182 default:
183 break;
184 };
185
186 if((pSXClause != NULL) && (pSXClause->m_Word0.f.type == SQ_EXPORT_PARAM))
187 {
188 pShader->nParamExports += pSXClause->m_Word1.f.burst_count + 1;
189 }
190 else if ((pSMXClause != NULL) && (pSMXClause->m_Word1.f.cf_inst == SQ_CF_INST_MEM_RING) &&
191 (pSMXClause->m_Word0.f.type == SQ_EXPORT_WRITE || pSMXClause->m_Word0.f.type == SQ_EXPORT_WRITE_IND))
192 {
193 pShader->nMemExports += pSMXClause->m_Word1.f.burst_count + 1;
194 }
195
196 pShader->bLinksDirty = GL_TRUE;
197 pShader->bNeedsAssembly = GL_TRUE;
198
199 pCFInst->useCount++;
200 }
201
202 void AddVTXInstruction(R700_Shader *pShader, R700VertexInstruction *pVTXInst)
203 {
204 pVTXInst->m_uIndex = pShader->lstVTXInstructions.uNumOfNode;
205 AddInstToList(&(pShader->lstVTXInstructions),
206 (R700ShaderInstruction*)pVTXInst);
207 pShader->uShaderBinaryDWORDSize += GetInstructionSize(pVTXInst->m_ShaderInstType);
208
209 if(pVTXInst->m_ShaderInstType == SIT_VTX_GENERIC)
210 {
211 R700VertexGenericFetch* pVTXGenericClause = (R700VertexGenericFetch*)pVTXInst;
212 pShader->nRegs = (pShader->nRegs < pVTXGenericClause->m_Word1_GPR.f.dst_gpr) ? pVTXGenericClause->m_Word1_GPR.f.dst_gpr : pShader->nRegs;
213 }
214
215 pShader->bLinksDirty = GL_TRUE;
216 pShader->bNeedsAssembly = GL_TRUE;
217
218 pVTXInst->useCount++;
219 }
220
221 void AddTEXInstruction(R700_Shader *pShader, R700TextureInstruction *pTEXInst)
222 {
223 pTEXInst->m_uIndex = pShader->lstTEXInstructions.uNumOfNode;
224 AddInstToList(&(pShader->lstTEXInstructions),
225 (R700ShaderInstruction*)pTEXInst);
226 pShader->uShaderBinaryDWORDSize += GetInstructionSize(pTEXInst->m_ShaderInstType);
227
228 pShader->nRegs = (pShader->nRegs < pTEXInst->m_Word1.f.dst_gpr) ? pTEXInst->m_Word1.f.dst_gpr : pShader->nRegs;
229
230 pShader->bLinksDirty = GL_TRUE;
231 pShader->bNeedsAssembly = GL_TRUE;
232
233 pTEXInst->useCount++;
234 }
235
236 void AddALUInstruction(R700_Shader *pShader, R700ALUInstruction *pALUInst)
237 {
238 pALUInst->m_uIndex = pShader->lstALUInstructions.uNumOfNode;
239 AddInstToList(&(pShader->lstALUInstructions),
240 (R700ShaderInstruction*)pALUInst);
241 pShader->uShaderBinaryDWORDSize += GetInstructionSize(pALUInst->m_ShaderInstType);
242
243 pShader->nRegs = (pShader->nRegs < pALUInst->m_Word1.f.dst_gpr) ? pALUInst->m_Word1.f.dst_gpr : pShader->nRegs;
244
245 pShader->bLinksDirty = GL_TRUE;
246 pShader->bNeedsAssembly = GL_TRUE;
247
248 pALUInst->useCount++;
249 }
250
251 void ResolveLinks(R700_Shader *pShader)
252 {
253 GLuint uiSize;
254 R700ShaderInstruction *pInst;
255 R700ALUInstruction *pALUinst;
256 R700TextureInstruction *pTEXinst;
257 R700VertexInstruction *pVTXinst;
258
259 GLuint vtxOffset;
260
261 GLuint cfOffset = 0x0;
262
263 GLuint aluOffset = cfOffset + pShader->lstCFInstructions.uNumOfNode * GetInstructionSize(SIT_CF);
264
265 GLuint texOffset = aluOffset; // + m_lstALUInstructions.size() * R700ALUInstruction::SIZE,
266
267 pInst = pShader->lstALUInstructions.pHead;
268 while(NULL != pInst)
269 {
270 texOffset += GetInstructionSize(pInst->m_ShaderInstType);
271
272 pInst = pInst->pNextInst;
273 };
274
275 vtxOffset = texOffset + pShader->lstTEXInstructions.uNumOfNode * GetInstructionSize(SIT_TEX);
276
277 if ( ((pShader->lstTEXInstructions.uNumOfNode > 0) && (texOffset % 4 != 0)) ||
278 ((pShader->lstVTXInstructions.uNumOfNode > 0) && (vtxOffset % 4 != 0)) )
279 {
280 pALUinst = (R700ALUInstruction*) CALLOC_STRUCT(R700ALUInstruction);
281 Init_R700ALUInstruction(pALUinst);
282 AddALUInstruction(pShader, pALUinst);
283 texOffset += GetInstructionSize(SIT_ALU);
284 vtxOffset += GetInstructionSize(SIT_ALU);
285 }
286
287 pInst = pShader->lstALUInstructions.pHead;
288 uiSize = 0;
289 while(NULL != pInst)
290 {
291 pALUinst = (R700ALUInstruction*)pInst;
292
293 if(pALUinst->m_pLinkedALUClause != NULL)
294 {
295 // This address is quad-word aligned
296 pALUinst->m_pLinkedALUClause->m_Word0.f.addr = (aluOffset + uiSize) >> 1;
297 }
298
299 uiSize += GetInstructionSize(pALUinst->m_ShaderInstType);
300
301 pInst = pInst->pNextInst;
302 };
303
304 pInst = pShader->lstTEXInstructions.pHead;
305 uiSize = 0;
306 while(NULL != pInst)
307 {
308 pTEXinst = (R700TextureInstruction*)pInst;
309
310 if (pTEXinst->m_pLinkedGenericClause != NULL)
311 {
312 pTEXinst->m_pLinkedGenericClause->m_Word0.f.addr = (texOffset + uiSize) >> 1;
313 }
314
315 uiSize += GetInstructionSize(pTEXinst->m_ShaderInstType);
316
317 pInst = pInst->pNextInst;
318 };
319
320 pInst = pShader->lstVTXInstructions.pHead;
321 uiSize = 0;
322 while(NULL != pInst)
323 {
324 pVTXinst = (R700VertexInstruction*)pInst;
325
326 if (pVTXinst->m_pLinkedGenericClause != NULL)
327 {
328 pVTXinst->m_pLinkedGenericClause->m_Word0.f.addr = (vtxOffset + uiSize) >> 1;
329 }
330
331 uiSize += GetInstructionSize(pVTXinst->m_ShaderInstType);
332
333 pInst = pInst->pNextInst;
334 };
335
336 pShader->bLinksDirty = GL_FALSE;
337 }
338
339 void Assemble(R700_Shader *pShader)
340 {
341 GLuint i;
342 GLuint *pShaderBinary;
343 GLuint size_of_program;
344 GLuint *pCurrPos;
345
346 GLuint end_of_cf_instructions;
347 GLuint number_of_alu_dwords;
348
349 R700ShaderInstruction *pInst;
350
351 if(GL_TRUE == pShader->bBinaryShader)
352 {
353 return;
354 }
355
356 if(pShader->bLinksDirty == GL_TRUE)
357 {
358 ResolveLinks(pShader);
359 }
360
361 size_of_program = pShader->uShaderBinaryDWORDSize;
362
363 pShaderBinary = (GLuint*) MALLOC(sizeof(GLuint)*size_of_program);
364
365 pCurrPos = pShaderBinary;
366
367 for (i = 0; i < size_of_program; i++)
368 {
369 pShaderBinary[i] = 0;
370 }
371
372 pInst = pShader->lstCFInstructions.pHead;
373 while(NULL != pInst)
374 {
375 switch (pInst->m_ShaderInstType)
376 {
377 case SIT_CF_GENERIC:
378 {
379 R700ControlFlowGenericClause* pCFgeneric = (R700ControlFlowGenericClause*)pInst;
380 *pCurrPos++ = pCFgeneric->m_Word0.val;
381 *pCurrPos++ = pCFgeneric->m_Word1.val;
382 }
383 break;
384 case SIT_CF_ALU:
385 {
386 R700ControlFlowALUClause* pCFalu = (R700ControlFlowALUClause*)pInst;
387 *pCurrPos++ = pCFalu->m_Word0.val;
388 *pCurrPos++ = pCFalu->m_Word1.val;
389 }
390 break;
391 case SIT_CF_ALL_EXP_SX:
392 {
393 R700ControlFlowSXClause* pCFsx = (R700ControlFlowSXClause*)pInst;
394 *pCurrPos++ = pCFsx->m_Word0.val;
395 *pCurrPos++ = (pCFsx->m_Word1.val | pCFsx->m_Word1_SWIZ.val);
396 }
397 break;
398 case SIT_CF_ALL_EXP_SMX:
399 {
400 R700ControlFlowSMXClause* pCFsmx = (R700ControlFlowSMXClause*)pInst;
401 *pCurrPos++ = pCFsmx->m_Word0.val;
402 *pCurrPos++ = (pCFsmx->m_Word1.val | pCFsmx->m_Word1_BUF.val);
403 }
404 break;
405 default:
406 break;
407 }
408
409 pInst = pInst->pNextInst;
410 };
411
412 number_of_alu_dwords = 0;
413 pInst = pShader->lstALUInstructions.pHead;
414 while(NULL != pInst)
415 {
416 switch (pInst->m_ShaderInstType)
417 {
418 case SIT_ALU:
419 {
420 R700ALUInstruction* pALU = (R700ALUInstruction*)pInst;
421
422 *pCurrPos++ = pALU->m_Word0.val;
423 *pCurrPos++ = (pALU->m_Word1.val | pALU->m_Word1_OP2.val | pALU->m_Word1_OP3.val);
424
425 number_of_alu_dwords += 2;
426 }
427 break;
428 case SIT_ALU_HALF_LIT:
429 {
430 R700ALUInstructionHalfLiteral* pALUhalf = (R700ALUInstructionHalfLiteral*)pInst;
431
432 *pCurrPos++ = pALUhalf->m_Word0.val;
433 *pCurrPos++ = (pALUhalf->m_Word1.val | pALUhalf->m_Word1_OP2.val | pALUhalf->m_Word1_OP3.val);
434 *pCurrPos++ = *((GLuint*)&(pALUhalf->m_fLiteralX));
435 *pCurrPos++ = *((GLuint*)&(pALUhalf->m_fLiteralY));
436
437 number_of_alu_dwords += 4;
438 }
439 break;
440 case SIT_ALU_FALL_LIT:
441 {
442 R700ALUInstructionFullLiteral* pALUfull = (R700ALUInstructionFullLiteral*)pInst;
443
444 *pCurrPos++ = pALUfull->m_Word0.val;
445 *pCurrPos++ = (pALUfull->m_Word1.val | pALUfull->m_Word1_OP2.val | pALUfull->m_Word1_OP3.val);
446
447 *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralX));
448 *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralY));
449 *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralZ));
450 *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralW));
451
452 number_of_alu_dwords += 6;
453 }
454 break;
455 default:
456 break;
457 }
458
459 pInst = pInst->pNextInst;
460 };
461
462 pInst = pShader->lstTEXInstructions.pHead;
463 while(NULL != pInst)
464 {
465 R700TextureInstruction* pTEX = (R700TextureInstruction*)pInst;
466
467 *pCurrPos++ = pTEX->m_Word0.val;
468 *pCurrPos++ = pTEX->m_Word1.val;
469 *pCurrPos++ = pTEX->m_Word2.val;
470 *pCurrPos++ = 0x0beadeaf;
471
472 pInst = pInst->pNextInst;
473 };
474
475 pInst = pShader->lstVTXInstructions.pHead;
476 while(NULL != pInst)
477 {
478 switch (pInst->m_ShaderInstType)
479 {
480 case SIT_VTX_SEM: //
481 {
482 R700VertexSemanticFetch* pVTXsem = (R700VertexSemanticFetch*)pInst;
483
484 *pCurrPos++ = pVTXsem->m_Word0.val;
485 *pCurrPos++ = (pVTXsem->m_Word1.val | pVTXsem->m_Word1_SEM.val);
486 *pCurrPos++ = pVTXsem->m_Word2.val;
487 *pCurrPos++ = 0x0beadeaf;
488 }
489 break;
490 case SIT_VTX_GENERIC: //
491 {
492 R700VertexGenericFetch* pVTXgeneric = (R700VertexGenericFetch*)pInst;
493
494 *pCurrPos++ = pVTXgeneric->m_Word0.val;
495 *pCurrPos++ = (pVTXgeneric->m_Word1.val | pVTXgeneric->m_Word1_GPR.val);
496 *pCurrPos++ = pVTXgeneric->m_Word2.val;
497 *pCurrPos++ = 0x0beadeaf;
498 }
499 break;
500 default:
501 break;
502 }
503
504 pInst = pInst->pNextInst;
505 };
506
507 if(NULL != pShader->pProgram)
508 {
509 FREE(pShader->pProgram);
510 }
511 pShader->pProgram = (GLubyte*)pShaderBinary;
512
513 end_of_cf_instructions = pShader->uCFOffset + pShader->lstCFInstructions.uNumOfNode * GetInstructionSize(SIT_CF);
514
515 pShader->uEndOfCF = end_of_cf_instructions >> 1;
516
517 pShader->uEndOfALU = (end_of_cf_instructions + number_of_alu_dwords) >> 1;
518
519 pShader->uEndOfFetch = (pShader->uCFOffset + pShader->uShaderBinaryDWORDSize) >> 1;
520
521 pShader->bNeedsAssembly = GL_FALSE;
522 }
523
524 void LoadProgram(R700_Shader *pShader) //context
525 {
526 }
527
528 void UpdateShaderRegisters(R700_Shader *pShader) //context
529 {
530 }
531
532 void DeleteInstructions(R700_Shader *pShader)
533 {
534 }
535
536 void DebugPrint(void)
537 {
538 }
539
540 void cleanup_vfetch_shaderinst(R700_Shader *pShader)
541 {
542 R700ShaderInstruction *pInst;
543 R700ShaderInstruction *pInstToFree;
544 R700VertexInstruction *pVTXInst;
545 R700ControlFlowInstruction *pCFInst;
546
547 pInst = pShader->lstVTXInstructions.pHead;
548 while(NULL != pInst)
549 {
550 pVTXInst = (R700VertexInstruction *)pInst;
551 pShader->uShaderBinaryDWORDSize -= GetInstructionSize(pVTXInst->m_ShaderInstType);
552
553 if(NULL != pVTXInst->m_pLinkedGenericClause)
554 {
555 pCFInst = (R700ControlFlowInstruction*)(pVTXInst->m_pLinkedGenericClause);
556
557 TakeInstOutFromList(&(pShader->lstCFInstructions),
558 (R700ShaderInstruction*)pCFInst);
559
560 pShader->uShaderBinaryDWORDSize -= GetInstructionSize(pCFInst->m_ShaderInstType);
561 }
562
563 pInst = pInst->pNextInst;
564 };
565
566 //destroy each item in pShader->lstVTXInstructions;
567 pInst = pShader->lstVTXInstructions.pHead;
568 while(NULL != pInst)
569 {
570 pInstToFree = pInst;
571 pInst = pInst->pNextInst;
572 FREE(pInstToFree);
573 };
574
575 //set NULL pShader->lstVTXInstructions
576 pShader->lstVTXInstructions.pHead=NULL;
577 pShader->lstVTXInstructions.pTail=NULL;
578 pShader->lstVTXInstructions.uNumOfNode=0;
579 }
580
581 void Clean_Up_Shader(R700_Shader *pShader)
582 {
583 FREE(pShader->pProgram);
584
585 R700ShaderInstruction *pInst;
586 R700ShaderInstruction *pInstToFree;
587
588 pInst = pShader->lstCFInstructions.pHead;
589 while(NULL != pInst)
590 {
591 pInstToFree = pInst;
592 pInst = pInst->pNextInst;
593 FREE(pInstToFree);
594 };
595 pInst = pShader->lstALUInstructions.pHead;
596 while(NULL != pInst)
597 {
598 pInstToFree = pInst;
599 pInst = pInst->pNextInst;
600 FREE(pInstToFree);
601 };
602 pInst = pShader->lstTEXInstructions.pHead;
603 while(NULL != pInst)
604 {
605 pInstToFree = pInst;
606 pInst = pInst->pNextInst;
607 FREE(pInstToFree);
608 };
609 pInst = pShader->lstVTXInstructions.pHead;
610 while(NULL != pInst)
611 {
612 pInstToFree = pInst;
613 pInst = pInst->pNextInst;
614 FREE(pInstToFree);
615 };
616 }
617