2 * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
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.
24 * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
33 #include "main/imports.h"
35 #include "main/glheader.h"
37 #include "r600_context.h"
38 #include "r700_debug.h"
40 #include "r700_shader.h"
42 void r700ShaderInit(GLcontext
* ctx
)
46 void AddInstToList(TypedShaderList
* plstCFInstructions
, R700ShaderInstruction
* pInst
)
48 if(NULL
== plstCFInstructions
->pTail
)
50 plstCFInstructions
->pHead
= pInst
;
51 plstCFInstructions
->pTail
= pInst
;
55 plstCFInstructions
->pTail
->pNextInst
= pInst
;
56 plstCFInstructions
->pTail
= pInst
;
58 pInst
->pNextInst
= NULL
;
60 plstCFInstructions
->uNumOfNode
++;
63 void TakeInstOutFromList(TypedShaderList
* plstCFInstructions
, R700ShaderInstruction
* pInst
)
66 GLboolean bFound
= GL_FALSE
;
67 R700ShaderInstruction
* pPrevInst
= NULL
;
68 R700ShaderInstruction
* pCurInst
= plstCFInstructions
->pHead
;
70 /* Need go thro list to make sure pInst is there. */
71 while(NULL
!= pCurInst
)
80 pCurInst
= pCurInst
->pNextInst
;
84 plstCFInstructions
->uNumOfNode
--;
86 pCurInst
= pInst
->pNextInst
;
87 ulIndex
= pInst
->m_uIndex
;
88 while(NULL
!= pCurInst
)
90 pCurInst
->m_uIndex
= ulIndex
;
92 pCurInst
= pCurInst
->pNextInst
;
95 if(plstCFInstructions
->pHead
== pInst
)
97 plstCFInstructions
->pHead
= pInst
->pNextInst
;
99 if(plstCFInstructions
->pTail
== pInst
)
101 plstCFInstructions
->pTail
= pPrevInst
;
103 if(NULL
!= pPrevInst
)
105 pPrevInst
->pNextInst
= pInst
->pNextInst
;
112 void Init_R700_Shader(R700_Shader
* pShader
)
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;
122 pShader
->nParamExports
= 0;
123 pShader
->nMemExports
= 0;
124 pShader
->resource
= 0;
126 pShader
->exportMode
= 0;
127 pShader
->depthIsImported
= GL_FALSE
;
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
;
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
;
142 pShader
->uCFOffset
= 0;
143 pShader
->uStackSize
= 0;
144 pShader
->uMaxCallDepth
= 0;
146 pShader
->bSurfAllocated
= GL_FALSE
;
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;
162 void AddCFInstruction(R700_Shader
*pShader
, R700ControlFlowInstruction
*pCFInst
)
164 R700ControlFlowSXClause
* pSXClause
;
165 R700ControlFlowSMXClause
* pSMXClause
;
167 pCFInst
->m_uIndex
= pShader
->lstCFInstructions
.uNumOfNode
;
168 AddInstToList(&(pShader
->lstCFInstructions
),
169 (R700ShaderInstruction
*)pCFInst
);
170 pShader
->uShaderBinaryDWORDSize
+= GetInstructionSize(pCFInst
->m_ShaderInstType
);
174 switch (pCFInst
->m_ShaderInstType
)
176 case SIT_CF_ALL_EXP_SX
:
177 pSXClause
= (R700ControlFlowSXClause
*)pCFInst
;
179 case SIT_CF_ALL_EXP_SMX
:
180 pSMXClause
= (R700ControlFlowSMXClause
*)pCFInst
;
186 if((pSXClause
!= NULL
) && (pSXClause
->m_Word0
.f
.type
== SQ_EXPORT_PARAM
))
188 pShader
->nParamExports
+= pSXClause
->m_Word1
.f
.burst_count
+ 1;
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
))
193 pShader
->nMemExports
+= pSMXClause
->m_Word1
.f
.burst_count
+ 1;
196 pShader
->bLinksDirty
= GL_TRUE
;
197 pShader
->bNeedsAssembly
= GL_TRUE
;
202 void AddVTXInstruction(R700_Shader
*pShader
, R700VertexInstruction
*pVTXInst
)
204 pVTXInst
->m_uIndex
= pShader
->lstVTXInstructions
.uNumOfNode
;
205 AddInstToList(&(pShader
->lstVTXInstructions
),
206 (R700ShaderInstruction
*)pVTXInst
);
207 pShader
->uShaderBinaryDWORDSize
+= GetInstructionSize(pVTXInst
->m_ShaderInstType
);
209 if(pVTXInst
->m_ShaderInstType
== SIT_VTX_GENERIC
)
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
;
215 pShader
->bLinksDirty
= GL_TRUE
;
216 pShader
->bNeedsAssembly
= GL_TRUE
;
218 pVTXInst
->useCount
++;
221 void AddTEXInstruction(R700_Shader
*pShader
, R700TextureInstruction
*pTEXInst
)
223 pTEXInst
->m_uIndex
= pShader
->lstTEXInstructions
.uNumOfNode
;
224 AddInstToList(&(pShader
->lstTEXInstructions
),
225 (R700ShaderInstruction
*)pTEXInst
);
226 pShader
->uShaderBinaryDWORDSize
+= GetInstructionSize(pTEXInst
->m_ShaderInstType
);
228 pShader
->nRegs
= (pShader
->nRegs
< pTEXInst
->m_Word1
.f
.dst_gpr
) ? pTEXInst
->m_Word1
.f
.dst_gpr
: pShader
->nRegs
;
230 pShader
->bLinksDirty
= GL_TRUE
;
231 pShader
->bNeedsAssembly
= GL_TRUE
;
233 pTEXInst
->useCount
++;
236 void AddALUInstruction(R700_Shader
*pShader
, R700ALUInstruction
*pALUInst
)
238 pALUInst
->m_uIndex
= pShader
->lstALUInstructions
.uNumOfNode
;
239 AddInstToList(&(pShader
->lstALUInstructions
),
240 (R700ShaderInstruction
*)pALUInst
);
241 pShader
->uShaderBinaryDWORDSize
+= GetInstructionSize(pALUInst
->m_ShaderInstType
);
243 pShader
->nRegs
= (pShader
->nRegs
< pALUInst
->m_Word1
.f
.dst_gpr
) ? pALUInst
->m_Word1
.f
.dst_gpr
: pShader
->nRegs
;
245 pShader
->bLinksDirty
= GL_TRUE
;
246 pShader
->bNeedsAssembly
= GL_TRUE
;
248 pALUInst
->useCount
++;
251 void ResolveLinks(R700_Shader
*pShader
)
254 R700ShaderInstruction
*pInst
;
255 R700ALUInstruction
*pALUinst
;
256 R700TextureInstruction
*pTEXinst
;
257 R700VertexInstruction
*pVTXinst
;
261 GLuint cfOffset
= 0x0;
263 GLuint aluOffset
= cfOffset
+ pShader
->lstCFInstructions
.uNumOfNode
* GetInstructionSize(SIT_CF
);
265 GLuint texOffset
= aluOffset
; // + m_lstALUInstructions.size() * R700ALUInstruction::SIZE,
267 pInst
= pShader
->lstALUInstructions
.pHead
;
270 texOffset
+= GetInstructionSize(pInst
->m_ShaderInstType
);
272 pInst
= pInst
->pNextInst
;
275 vtxOffset
= texOffset
+ pShader
->lstTEXInstructions
.uNumOfNode
* GetInstructionSize(SIT_TEX
);
277 if ( ((pShader
->lstTEXInstructions
.uNumOfNode
> 0) && (texOffset
% 4 != 0)) ||
278 ((pShader
->lstVTXInstructions
.uNumOfNode
> 0) && (vtxOffset
% 4 != 0)) )
280 pALUinst
= (R700ALUInstruction
*) CALLOC_STRUCT(R700ALUInstruction
);
281 Init_R700ALUInstruction(pALUinst
);
282 AddALUInstruction(pShader
, pALUinst
);
283 texOffset
+= GetInstructionSize(SIT_ALU
);
284 vtxOffset
+= GetInstructionSize(SIT_ALU
);
287 pInst
= pShader
->lstALUInstructions
.pHead
;
291 pALUinst
= (R700ALUInstruction
*)pInst
;
293 if(pALUinst
->m_pLinkedALUClause
!= NULL
)
295 // This address is quad-word aligned
296 pALUinst
->m_pLinkedALUClause
->m_Word0
.f
.addr
= (aluOffset
+ uiSize
) >> 1;
299 uiSize
+= GetInstructionSize(pALUinst
->m_ShaderInstType
);
301 pInst
= pInst
->pNextInst
;
304 pInst
= pShader
->lstTEXInstructions
.pHead
;
308 pTEXinst
= (R700TextureInstruction
*)pInst
;
310 if (pTEXinst
->m_pLinkedGenericClause
!= NULL
)
312 pTEXinst
->m_pLinkedGenericClause
->m_Word0
.f
.addr
= (texOffset
+ uiSize
) >> 1;
315 uiSize
+= GetInstructionSize(pTEXinst
->m_ShaderInstType
);
317 pInst
= pInst
->pNextInst
;
320 pInst
= pShader
->lstVTXInstructions
.pHead
;
324 pVTXinst
= (R700VertexInstruction
*)pInst
;
326 if (pVTXinst
->m_pLinkedGenericClause
!= NULL
)
328 pVTXinst
->m_pLinkedGenericClause
->m_Word0
.f
.addr
= (vtxOffset
+ uiSize
) >> 1;
331 uiSize
+= GetInstructionSize(pVTXinst
->m_ShaderInstType
);
333 pInst
= pInst
->pNextInst
;
336 pShader
->bLinksDirty
= GL_FALSE
;
339 void Assemble(R700_Shader
*pShader
)
342 GLuint
*pShaderBinary
;
343 GLuint size_of_program
;
346 GLuint end_of_cf_instructions
;
347 GLuint number_of_alu_dwords
;
349 R700ShaderInstruction
*pInst
;
351 if(GL_TRUE
== pShader
->bBinaryShader
)
356 if(pShader
->bLinksDirty
== GL_TRUE
)
358 ResolveLinks(pShader
);
361 size_of_program
= pShader
->uShaderBinaryDWORDSize
;
363 pShaderBinary
= (GLuint
*) MALLOC(sizeof(GLuint
)*size_of_program
);
365 pCurrPos
= pShaderBinary
;
367 for (i
= 0; i
< size_of_program
; i
++)
369 pShaderBinary
[i
] = 0;
372 pInst
= pShader
->lstCFInstructions
.pHead
;
375 switch (pInst
->m_ShaderInstType
)
379 R700ControlFlowGenericClause
* pCFgeneric
= (R700ControlFlowGenericClause
*)pInst
;
380 *pCurrPos
++ = pCFgeneric
->m_Word0
.val
;
381 *pCurrPos
++ = pCFgeneric
->m_Word1
.val
;
386 R700ControlFlowALUClause
* pCFalu
= (R700ControlFlowALUClause
*)pInst
;
387 *pCurrPos
++ = pCFalu
->m_Word0
.val
;
388 *pCurrPos
++ = pCFalu
->m_Word1
.val
;
391 case SIT_CF_ALL_EXP_SX
:
393 R700ControlFlowSXClause
* pCFsx
= (R700ControlFlowSXClause
*)pInst
;
394 *pCurrPos
++ = pCFsx
->m_Word0
.val
;
395 *pCurrPos
++ = (pCFsx
->m_Word1
.val
| pCFsx
->m_Word1_SWIZ
.val
);
398 case SIT_CF_ALL_EXP_SMX
:
400 R700ControlFlowSMXClause
* pCFsmx
= (R700ControlFlowSMXClause
*)pInst
;
401 *pCurrPos
++ = pCFsmx
->m_Word0
.val
;
402 *pCurrPos
++ = (pCFsmx
->m_Word1
.val
| pCFsmx
->m_Word1_BUF
.val
);
409 pInst
= pInst
->pNextInst
;
412 number_of_alu_dwords
= 0;
413 pInst
= pShader
->lstALUInstructions
.pHead
;
416 switch (pInst
->m_ShaderInstType
)
420 R700ALUInstruction
* pALU
= (R700ALUInstruction
*)pInst
;
422 *pCurrPos
++ = pALU
->m_Word0
.val
;
423 *pCurrPos
++ = (pALU
->m_Word1
.val
| pALU
->m_Word1_OP2
.val
| pALU
->m_Word1_OP3
.val
);
425 number_of_alu_dwords
+= 2;
428 case SIT_ALU_HALF_LIT
:
430 R700ALUInstructionHalfLiteral
* pALUhalf
= (R700ALUInstructionHalfLiteral
*)pInst
;
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
));
437 number_of_alu_dwords
+= 4;
440 case SIT_ALU_FALL_LIT
:
442 R700ALUInstructionFullLiteral
* pALUfull
= (R700ALUInstructionFullLiteral
*)pInst
;
444 *pCurrPos
++ = pALUfull
->m_Word0
.val
;
445 *pCurrPos
++ = (pALUfull
->m_Word1
.val
| pALUfull
->m_Word1_OP2
.val
| pALUfull
->m_Word1_OP3
.val
);
447 *pCurrPos
++ = *((GLuint
*)&(pALUfull
->m_fLiteralX
));
448 *pCurrPos
++ = *((GLuint
*)&(pALUfull
->m_fLiteralY
));
449 *pCurrPos
++ = *((GLuint
*)&(pALUfull
->m_fLiteralZ
));
450 *pCurrPos
++ = *((GLuint
*)&(pALUfull
->m_fLiteralW
));
452 number_of_alu_dwords
+= 6;
459 pInst
= pInst
->pNextInst
;
462 pInst
= pShader
->lstTEXInstructions
.pHead
;
465 R700TextureInstruction
* pTEX
= (R700TextureInstruction
*)pInst
;
467 *pCurrPos
++ = pTEX
->m_Word0
.val
;
468 *pCurrPos
++ = pTEX
->m_Word1
.val
;
469 *pCurrPos
++ = pTEX
->m_Word2
.val
;
470 *pCurrPos
++ = 0x0beadeaf;
472 pInst
= pInst
->pNextInst
;
475 pInst
= pShader
->lstVTXInstructions
.pHead
;
478 switch (pInst
->m_ShaderInstType
)
482 R700VertexSemanticFetch
* pVTXsem
= (R700VertexSemanticFetch
*)pInst
;
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;
490 case SIT_VTX_GENERIC
: //
492 R700VertexGenericFetch
* pVTXgeneric
= (R700VertexGenericFetch
*)pInst
;
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;
504 pInst
= pInst
->pNextInst
;
507 if(NULL
!= pShader
->pProgram
)
509 FREE(pShader
->pProgram
);
511 pShader
->pProgram
= (GLubyte
*)pShaderBinary
;
513 end_of_cf_instructions
= pShader
->uCFOffset
+ pShader
->lstCFInstructions
.uNumOfNode
* GetInstructionSize(SIT_CF
);
515 pShader
->uEndOfCF
= end_of_cf_instructions
>> 1;
517 pShader
->uEndOfALU
= (end_of_cf_instructions
+ number_of_alu_dwords
) >> 1;
519 pShader
->uEndOfFetch
= (pShader
->uCFOffset
+ pShader
->uShaderBinaryDWORDSize
) >> 1;
521 pShader
->bNeedsAssembly
= GL_FALSE
;
524 void LoadProgram(R700_Shader
*pShader
) //context
528 void UpdateShaderRegisters(R700_Shader
*pShader
) //context
532 void DeleteInstructions(R700_Shader
*pShader
)
536 void DebugPrint(void)
540 void cleanup_vfetch_shaderinst(R700_Shader
*pShader
)
542 R700ShaderInstruction
*pInst
;
543 R700ShaderInstruction
*pInstToFree
;
544 R700VertexInstruction
*pVTXInst
;
545 R700ControlFlowInstruction
*pCFInst
;
547 pInst
= pShader
->lstVTXInstructions
.pHead
;
550 pVTXInst
= (R700VertexInstruction
*)pInst
;
551 pShader
->uShaderBinaryDWORDSize
-= GetInstructionSize(pVTXInst
->m_ShaderInstType
);
553 if(NULL
!= pVTXInst
->m_pLinkedGenericClause
)
555 pCFInst
= (R700ControlFlowInstruction
*)(pVTXInst
->m_pLinkedGenericClause
);
557 TakeInstOutFromList(&(pShader
->lstCFInstructions
),
558 (R700ShaderInstruction
*)pCFInst
);
560 pShader
->uShaderBinaryDWORDSize
-= GetInstructionSize(pCFInst
->m_ShaderInstType
);
563 pInst
= pInst
->pNextInst
;
566 //destroy each item in pShader->lstVTXInstructions;
567 pInst
= pShader
->lstVTXInstructions
.pHead
;
571 pInst
= pInst
->pNextInst
;
575 //set NULL pShader->lstVTXInstructions
576 pShader
->lstVTXInstructions
.pHead
=NULL
;
577 pShader
->lstVTXInstructions
.pTail
=NULL
;
578 pShader
->lstVTXInstructions
.uNumOfNode
=0;
581 void Clean_Up_Shader(R700_Shader
*pShader
)
583 FREE(pShader
->pProgram
);
585 R700ShaderInstruction
*pInst
;
586 R700ShaderInstruction
*pInstToFree
;
588 pInst
= pShader
->lstCFInstructions
.pHead
;
592 pInst
= pInst
->pNextInst
;
595 pInst
= pShader
->lstALUInstructions
.pHead
;
599 pInst
= pInst
->pNextInst
;
602 pInst
= pShader
->lstTEXInstructions
.pHead
;
606 pInst
= pInst
->pNextInst
;
609 pInst
= pShader
->lstVTXInstructions
.pHead
;
613 pInst
= pInst
->pNextInst
;