r600 : Initial version of glsl fc.
[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 SetActiveCFlist(R700_Shader *pShader, TypedShaderList * plstCF)
163 {
164 pShader->plstCFInstructions_active = plstCF;
165 }
166
167 void AddCFInstruction(R700_Shader *pShader, R700ControlFlowInstruction *pCFInst)
168 {
169 R700ControlFlowSXClause* pSXClause;
170 R700ControlFlowSMXClause* pSMXClause;
171
172 pCFInst->m_uIndex = pShader->plstCFInstructions_active->uNumOfNode;
173 AddInstToList(pShader->plstCFInstructions_active,
174 (R700ShaderInstruction*)pCFInst);
175 pShader->uShaderBinaryDWORDSize += GetInstructionSize(pCFInst->m_ShaderInstType);
176
177 pSXClause = NULL;
178 pSMXClause = NULL;
179 switch (pCFInst->m_ShaderInstType)
180 {
181 case SIT_CF_ALL_EXP_SX:
182 pSXClause = (R700ControlFlowSXClause*)pCFInst;
183 break;
184 case SIT_CF_ALL_EXP_SMX:
185 pSMXClause = (R700ControlFlowSMXClause*)pCFInst;
186 break;
187 default:
188 break;
189 };
190
191 if((pSXClause != NULL) && (pSXClause->m_Word0.f.type == SQ_EXPORT_PARAM))
192 {
193 pShader->nParamExports += pSXClause->m_Word1.f.burst_count + 1;
194 }
195 else if ((pSMXClause != NULL) && (pSMXClause->m_Word1.f.cf_inst == SQ_CF_INST_MEM_RING) &&
196 (pSMXClause->m_Word0.f.type == SQ_EXPORT_WRITE || pSMXClause->m_Word0.f.type == SQ_EXPORT_WRITE_IND))
197 {
198 pShader->nMemExports += pSMXClause->m_Word1.f.burst_count + 1;
199 }
200
201 pShader->bLinksDirty = GL_TRUE;
202 pShader->bNeedsAssembly = GL_TRUE;
203
204 pCFInst->useCount++;
205 }
206
207 void AddVTXInstruction(R700_Shader *pShader, R700VertexInstruction *pVTXInst)
208 {
209 pVTXInst->m_uIndex = pShader->lstVTXInstructions.uNumOfNode;
210 AddInstToList(&(pShader->lstVTXInstructions),
211 (R700ShaderInstruction*)pVTXInst);
212 pShader->uShaderBinaryDWORDSize += GetInstructionSize(pVTXInst->m_ShaderInstType);
213
214 if(pVTXInst->m_ShaderInstType == SIT_VTX_GENERIC)
215 {
216 R700VertexGenericFetch* pVTXGenericClause = (R700VertexGenericFetch*)pVTXInst;
217 pShader->nRegs = (pShader->nRegs < pVTXGenericClause->m_Word1_GPR.f.dst_gpr) ? pVTXGenericClause->m_Word1_GPR.f.dst_gpr : pShader->nRegs;
218 }
219
220 pShader->bLinksDirty = GL_TRUE;
221 pShader->bNeedsAssembly = GL_TRUE;
222
223 pVTXInst->useCount++;
224 }
225
226 void AddTEXInstruction(R700_Shader *pShader, R700TextureInstruction *pTEXInst)
227 {
228 pTEXInst->m_uIndex = pShader->lstTEXInstructions.uNumOfNode;
229 AddInstToList(&(pShader->lstTEXInstructions),
230 (R700ShaderInstruction*)pTEXInst);
231 pShader->uShaderBinaryDWORDSize += GetInstructionSize(pTEXInst->m_ShaderInstType);
232
233 pShader->nRegs = (pShader->nRegs < pTEXInst->m_Word1.f.dst_gpr) ? pTEXInst->m_Word1.f.dst_gpr : pShader->nRegs;
234
235 pShader->bLinksDirty = GL_TRUE;
236 pShader->bNeedsAssembly = GL_TRUE;
237
238 pTEXInst->useCount++;
239 }
240
241 void AddALUInstruction(R700_Shader *pShader, R700ALUInstruction *pALUInst)
242 {
243 pALUInst->m_uIndex = pShader->lstALUInstructions.uNumOfNode;
244 AddInstToList(&(pShader->lstALUInstructions),
245 (R700ShaderInstruction*)pALUInst);
246 pShader->uShaderBinaryDWORDSize += GetInstructionSize(pALUInst->m_ShaderInstType);
247
248 pShader->nRegs = (pShader->nRegs < pALUInst->m_Word1.f.dst_gpr) ? pALUInst->m_Word1.f.dst_gpr : pShader->nRegs;
249
250 pShader->bLinksDirty = GL_TRUE;
251 pShader->bNeedsAssembly = GL_TRUE;
252
253 pALUInst->useCount++;
254 }
255
256 void ResolveLinks(R700_Shader *pShader)
257 {
258 GLuint uiSize;
259 R700ShaderInstruction *pInst;
260 R700ALUInstruction *pALUinst;
261 R700TextureInstruction *pTEXinst;
262 R700VertexInstruction *pVTXinst;
263
264 GLuint vtxOffset;
265
266 GLuint cfOffset = 0x0;
267
268 GLuint aluOffset = cfOffset + pShader->lstCFInstructions.uNumOfNode * GetInstructionSize(SIT_CF);
269
270 GLuint texOffset = aluOffset; // + m_lstALUInstructions.size() * R700ALUInstruction::SIZE,
271
272 pInst = pShader->lstALUInstructions.pHead;
273 while(NULL != pInst)
274 {
275 texOffset += GetInstructionSize(pInst->m_ShaderInstType);
276
277 pInst = pInst->pNextInst;
278 };
279
280 vtxOffset = texOffset + pShader->lstTEXInstructions.uNumOfNode * GetInstructionSize(SIT_TEX);
281
282 if ( ((pShader->lstTEXInstructions.uNumOfNode > 0) && (texOffset % 4 != 0)) ||
283 ((pShader->lstVTXInstructions.uNumOfNode > 0) && (vtxOffset % 4 != 0)) )
284 {
285 pALUinst = (R700ALUInstruction*) CALLOC_STRUCT(R700ALUInstruction);
286 Init_R700ALUInstruction(pALUinst);
287 AddALUInstruction(pShader, pALUinst);
288 texOffset += GetInstructionSize(SIT_ALU);
289 vtxOffset += GetInstructionSize(SIT_ALU);
290 }
291
292 pInst = pShader->lstALUInstructions.pHead;
293 uiSize = 0;
294 while(NULL != pInst)
295 {
296 pALUinst = (R700ALUInstruction*)pInst;
297
298 if(pALUinst->m_pLinkedALUClause != NULL)
299 {
300 // This address is quad-word aligned
301 pALUinst->m_pLinkedALUClause->m_Word0.f.addr = (aluOffset + uiSize) >> 1;
302 }
303
304 uiSize += GetInstructionSize(pALUinst->m_ShaderInstType);
305
306 pInst = pInst->pNextInst;
307 };
308
309 pInst = pShader->lstTEXInstructions.pHead;
310 uiSize = 0;
311 while(NULL != pInst)
312 {
313 pTEXinst = (R700TextureInstruction*)pInst;
314
315 if (pTEXinst->m_pLinkedGenericClause != NULL)
316 {
317 pTEXinst->m_pLinkedGenericClause->m_Word0.f.addr = (texOffset + uiSize) >> 1;
318 }
319
320 uiSize += GetInstructionSize(pTEXinst->m_ShaderInstType);
321
322 pInst = pInst->pNextInst;
323 };
324
325 pInst = pShader->lstVTXInstructions.pHead;
326 uiSize = 0;
327 while(NULL != pInst)
328 {
329 pVTXinst = (R700VertexInstruction*)pInst;
330
331 if (pVTXinst->m_pLinkedGenericClause != NULL)
332 {
333 pVTXinst->m_pLinkedGenericClause->m_Word0.f.addr = (vtxOffset + uiSize) >> 1;
334 }
335
336 uiSize += GetInstructionSize(pVTXinst->m_ShaderInstType);
337
338 pInst = pInst->pNextInst;
339 };
340
341 pShader->bLinksDirty = GL_FALSE;
342 }
343
344 void Assemble(R700_Shader *pShader)
345 {
346 GLuint i;
347 GLuint *pShaderBinary;
348 GLuint size_of_program;
349 GLuint *pCurrPos;
350
351 GLuint end_of_cf_instructions;
352 GLuint number_of_alu_dwords;
353
354 R700ShaderInstruction *pInst;
355
356 if(GL_TRUE == pShader->bBinaryShader)
357 {
358 return;
359 }
360
361 if(pShader->bLinksDirty == GL_TRUE)
362 {
363 ResolveLinks(pShader);
364 }
365
366 size_of_program = pShader->uShaderBinaryDWORDSize;
367
368 pShaderBinary = (GLuint*) MALLOC(sizeof(GLuint)*size_of_program);
369
370 pCurrPos = pShaderBinary;
371
372 for (i = 0; i < size_of_program; i++)
373 {
374 pShaderBinary[i] = 0;
375 }
376
377 pInst = pShader->lstCFInstructions.pHead;
378 while(NULL != pInst)
379 {
380 switch (pInst->m_ShaderInstType)
381 {
382 case SIT_CF_GENERIC:
383 {
384 R700ControlFlowGenericClause* pCFgeneric = (R700ControlFlowGenericClause*)pInst;
385 *pCurrPos++ = pCFgeneric->m_Word0.val;
386 *pCurrPos++ = pCFgeneric->m_Word1.val;
387 }
388 break;
389 case SIT_CF_ALU:
390 {
391 R700ControlFlowALUClause* pCFalu = (R700ControlFlowALUClause*)pInst;
392 *pCurrPos++ = pCFalu->m_Word0.val;
393 *pCurrPos++ = pCFalu->m_Word1.val;
394 }
395 break;
396 case SIT_CF_ALL_EXP_SX:
397 {
398 R700ControlFlowSXClause* pCFsx = (R700ControlFlowSXClause*)pInst;
399 *pCurrPos++ = pCFsx->m_Word0.val;
400 *pCurrPos++ = (pCFsx->m_Word1.val | pCFsx->m_Word1_SWIZ.val);
401 }
402 break;
403 case SIT_CF_ALL_EXP_SMX:
404 {
405 R700ControlFlowSMXClause* pCFsmx = (R700ControlFlowSMXClause*)pInst;
406 *pCurrPos++ = pCFsmx->m_Word0.val;
407 *pCurrPos++ = (pCFsmx->m_Word1.val | pCFsmx->m_Word1_BUF.val);
408 }
409 break;
410 default:
411 break;
412 }
413
414 pInst = pInst->pNextInst;
415 };
416
417 number_of_alu_dwords = 0;
418 pInst = pShader->lstALUInstructions.pHead;
419 while(NULL != pInst)
420 {
421 switch (pInst->m_ShaderInstType)
422 {
423 case SIT_ALU:
424 {
425 R700ALUInstruction* pALU = (R700ALUInstruction*)pInst;
426
427 *pCurrPos++ = pALU->m_Word0.val;
428 *pCurrPos++ = (pALU->m_Word1.val | pALU->m_Word1_OP2.val | pALU->m_Word1_OP3.val);
429
430 number_of_alu_dwords += 2;
431 }
432 break;
433 case SIT_ALU_HALF_LIT:
434 {
435 R700ALUInstructionHalfLiteral* pALUhalf = (R700ALUInstructionHalfLiteral*)pInst;
436
437 *pCurrPos++ = pALUhalf->m_Word0.val;
438 *pCurrPos++ = (pALUhalf->m_Word1.val | pALUhalf->m_Word1_OP2.val | pALUhalf->m_Word1_OP3.val);
439 *pCurrPos++ = *((GLuint*)&(pALUhalf->m_fLiteralX));
440 *pCurrPos++ = *((GLuint*)&(pALUhalf->m_fLiteralY));
441
442 number_of_alu_dwords += 4;
443 }
444 break;
445 case SIT_ALU_FALL_LIT:
446 {
447 R700ALUInstructionFullLiteral* pALUfull = (R700ALUInstructionFullLiteral*)pInst;
448
449 *pCurrPos++ = pALUfull->m_Word0.val;
450 *pCurrPos++ = (pALUfull->m_Word1.val | pALUfull->m_Word1_OP2.val | pALUfull->m_Word1_OP3.val);
451
452 *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralX));
453 *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralY));
454 *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralZ));
455 *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralW));
456
457 number_of_alu_dwords += 6;
458 }
459 break;
460 default:
461 break;
462 }
463
464 pInst = pInst->pNextInst;
465 };
466
467 pInst = pShader->lstTEXInstructions.pHead;
468 while(NULL != pInst)
469 {
470 R700TextureInstruction* pTEX = (R700TextureInstruction*)pInst;
471
472 *pCurrPos++ = pTEX->m_Word0.val;
473 *pCurrPos++ = pTEX->m_Word1.val;
474 *pCurrPos++ = pTEX->m_Word2.val;
475 *pCurrPos++ = 0x0beadeaf;
476
477 pInst = pInst->pNextInst;
478 };
479
480 pInst = pShader->lstVTXInstructions.pHead;
481 while(NULL != pInst)
482 {
483 switch (pInst->m_ShaderInstType)
484 {
485 case SIT_VTX_SEM: //
486 {
487 R700VertexSemanticFetch* pVTXsem = (R700VertexSemanticFetch*)pInst;
488
489 *pCurrPos++ = pVTXsem->m_Word0.val;
490 *pCurrPos++ = (pVTXsem->m_Word1.val | pVTXsem->m_Word1_SEM.val);
491 *pCurrPos++ = pVTXsem->m_Word2.val;
492 *pCurrPos++ = 0x0beadeaf;
493 }
494 break;
495 case SIT_VTX_GENERIC: //
496 {
497 R700VertexGenericFetch* pVTXgeneric = (R700VertexGenericFetch*)pInst;
498
499 *pCurrPos++ = pVTXgeneric->m_Word0.val;
500 *pCurrPos++ = (pVTXgeneric->m_Word1.val | pVTXgeneric->m_Word1_GPR.val);
501 *pCurrPos++ = pVTXgeneric->m_Word2.val;
502 *pCurrPos++ = 0x0beadeaf;
503 }
504 break;
505 default:
506 break;
507 }
508
509 pInst = pInst->pNextInst;
510 };
511
512 if(NULL != pShader->pProgram)
513 {
514 FREE(pShader->pProgram);
515 }
516 pShader->pProgram = (GLubyte*)pShaderBinary;
517
518 end_of_cf_instructions = pShader->uCFOffset + pShader->lstCFInstructions.uNumOfNode * GetInstructionSize(SIT_CF);
519
520 pShader->uEndOfCF = end_of_cf_instructions >> 1;
521
522 pShader->uEndOfALU = (end_of_cf_instructions + number_of_alu_dwords) >> 1;
523
524 pShader->uEndOfFetch = (pShader->uCFOffset + pShader->uShaderBinaryDWORDSize) >> 1;
525
526 pShader->bNeedsAssembly = GL_FALSE;
527 }
528
529 void LoadProgram(R700_Shader *pShader) //context
530 {
531 }
532
533 void UpdateShaderRegisters(R700_Shader *pShader) //context
534 {
535 }
536
537 void DeleteInstructions(R700_Shader *pShader)
538 {
539 }
540
541 void DebugPrint(void)
542 {
543 }
544
545 void cleanup_vfetch_shaderinst(R700_Shader *pShader)
546 {
547 R700ShaderInstruction *pInst;
548 R700ShaderInstruction *pInstToFree;
549 R700VertexInstruction *pVTXInst;
550 R700ControlFlowInstruction *pCFInst;
551
552 pInst = pShader->lstVTXInstructions.pHead;
553 while(NULL != pInst)
554 {
555 pVTXInst = (R700VertexInstruction *)pInst;
556 pShader->uShaderBinaryDWORDSize -= GetInstructionSize(pVTXInst->m_ShaderInstType);
557
558 if(NULL != pVTXInst->m_pLinkedGenericClause)
559 {
560 pCFInst = (R700ControlFlowInstruction*)(pVTXInst->m_pLinkedGenericClause);
561
562 TakeInstOutFromList(&(pShader->lstCFInstructions),
563 (R700ShaderInstruction*)pCFInst);
564
565 pShader->uShaderBinaryDWORDSize -= GetInstructionSize(pCFInst->m_ShaderInstType);
566 }
567
568 pInst = pInst->pNextInst;
569 };
570
571 //destroy each item in pShader->lstVTXInstructions;
572 pInst = pShader->lstVTXInstructions.pHead;
573 while(NULL != pInst)
574 {
575 pInstToFree = pInst;
576 pInst = pInst->pNextInst;
577 FREE(pInstToFree);
578 };
579
580 //set NULL pShader->lstVTXInstructions
581 pShader->lstVTXInstructions.pHead=NULL;
582 pShader->lstVTXInstructions.pTail=NULL;
583 pShader->lstVTXInstructions.uNumOfNode=0;
584 }
585
586 void Clean_Up_Shader(R700_Shader *pShader)
587 {
588 FREE(pShader->pProgram);
589
590 R700ShaderInstruction *pInst;
591 R700ShaderInstruction *pInstToFree;
592
593 pInst = pShader->lstCFInstructions.pHead;
594 while(NULL != pInst)
595 {
596 pInstToFree = pInst;
597 pInst = pInst->pNextInst;
598 FREE(pInstToFree);
599 };
600 pInst = pShader->lstALUInstructions.pHead;
601 while(NULL != pInst)
602 {
603 pInstToFree = pInst;
604 pInst = pInst->pNextInst;
605 FREE(pInstToFree);
606 };
607 pInst = pShader->lstTEXInstructions.pHead;
608 while(NULL != pInst)
609 {
610 pInstToFree = pInst;
611 pInst = pInst->pNextInst;
612 FREE(pInstToFree);
613 };
614 pInst = pShader->lstVTXInstructions.pHead;
615 while(NULL != pInst)
616 {
617 pInstToFree = pInst;
618 pInst = pInst->pNextInst;
619 FREE(pInstToFree);
620 };
621 }
622