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 SetActiveCFlist(R700_Shader
*pShader
, TypedShaderList
* plstCF
)
164 pShader
->plstCFInstructions_active
= plstCF
;
167 void AddCFInstruction(R700_Shader
*pShader
, R700ControlFlowInstruction
*pCFInst
)
169 R700ControlFlowSXClause
* pSXClause
;
170 R700ControlFlowSMXClause
* pSMXClause
;
172 pCFInst
->m_uIndex
= pShader
->plstCFInstructions_active
->uNumOfNode
;
173 AddInstToList(pShader
->plstCFInstructions_active
,
174 (R700ShaderInstruction
*)pCFInst
);
175 pShader
->uShaderBinaryDWORDSize
+= GetInstructionSize(pCFInst
->m_ShaderInstType
);
179 switch (pCFInst
->m_ShaderInstType
)
181 case SIT_CF_ALL_EXP_SX
:
182 pSXClause
= (R700ControlFlowSXClause
*)pCFInst
;
184 case SIT_CF_ALL_EXP_SMX
:
185 pSMXClause
= (R700ControlFlowSMXClause
*)pCFInst
;
191 if((pSXClause
!= NULL
) && (pSXClause
->m_Word0
.f
.type
== SQ_EXPORT_PARAM
))
193 pShader
->nParamExports
+= pSXClause
->m_Word1
.f
.burst_count
+ 1;
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
))
198 pShader
->nMemExports
+= pSMXClause
->m_Word1
.f
.burst_count
+ 1;
201 pShader
->bLinksDirty
= GL_TRUE
;
202 pShader
->bNeedsAssembly
= GL_TRUE
;
207 void AddVTXInstruction(R700_Shader
*pShader
, R700VertexInstruction
*pVTXInst
)
209 pVTXInst
->m_uIndex
= pShader
->lstVTXInstructions
.uNumOfNode
;
210 AddInstToList(&(pShader
->lstVTXInstructions
),
211 (R700ShaderInstruction
*)pVTXInst
);
212 pShader
->uShaderBinaryDWORDSize
+= GetInstructionSize(pVTXInst
->m_ShaderInstType
);
214 if(pVTXInst
->m_ShaderInstType
== SIT_VTX_GENERIC
)
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
;
220 pShader
->bLinksDirty
= GL_TRUE
;
221 pShader
->bNeedsAssembly
= GL_TRUE
;
223 pVTXInst
->useCount
++;
226 void AddTEXInstruction(R700_Shader
*pShader
, R700TextureInstruction
*pTEXInst
)
228 pTEXInst
->m_uIndex
= pShader
->lstTEXInstructions
.uNumOfNode
;
229 AddInstToList(&(pShader
->lstTEXInstructions
),
230 (R700ShaderInstruction
*)pTEXInst
);
231 pShader
->uShaderBinaryDWORDSize
+= GetInstructionSize(pTEXInst
->m_ShaderInstType
);
233 pShader
->nRegs
= (pShader
->nRegs
< pTEXInst
->m_Word1
.f
.dst_gpr
) ? pTEXInst
->m_Word1
.f
.dst_gpr
: pShader
->nRegs
;
235 pShader
->bLinksDirty
= GL_TRUE
;
236 pShader
->bNeedsAssembly
= GL_TRUE
;
238 pTEXInst
->useCount
++;
241 void AddALUInstruction(R700_Shader
*pShader
, R700ALUInstruction
*pALUInst
)
243 pALUInst
->m_uIndex
= pShader
->lstALUInstructions
.uNumOfNode
;
244 AddInstToList(&(pShader
->lstALUInstructions
),
245 (R700ShaderInstruction
*)pALUInst
);
246 pShader
->uShaderBinaryDWORDSize
+= GetInstructionSize(pALUInst
->m_ShaderInstType
);
248 pShader
->nRegs
= (pShader
->nRegs
< pALUInst
->m_Word1
.f
.dst_gpr
) ? pALUInst
->m_Word1
.f
.dst_gpr
: pShader
->nRegs
;
250 pShader
->bLinksDirty
= GL_TRUE
;
251 pShader
->bNeedsAssembly
= GL_TRUE
;
253 pALUInst
->useCount
++;
256 void ResolveLinks(R700_Shader
*pShader
)
259 R700ShaderInstruction
*pInst
;
260 R700ALUInstruction
*pALUinst
;
261 R700TextureInstruction
*pTEXinst
;
262 R700VertexInstruction
*pVTXinst
;
266 GLuint cfOffset
= 0x0;
268 GLuint aluOffset
= cfOffset
+ pShader
->lstCFInstructions
.uNumOfNode
* GetInstructionSize(SIT_CF
);
270 GLuint texOffset
= aluOffset
; // + m_lstALUInstructions.size() * R700ALUInstruction::SIZE,
272 pInst
= pShader
->lstALUInstructions
.pHead
;
275 texOffset
+= GetInstructionSize(pInst
->m_ShaderInstType
);
277 pInst
= pInst
->pNextInst
;
280 vtxOffset
= texOffset
+ pShader
->lstTEXInstructions
.uNumOfNode
* GetInstructionSize(SIT_TEX
);
282 if ( ((pShader
->lstTEXInstructions
.uNumOfNode
> 0) && (texOffset
% 4 != 0)) ||
283 ((pShader
->lstVTXInstructions
.uNumOfNode
> 0) && (vtxOffset
% 4 != 0)) )
285 pALUinst
= (R700ALUInstruction
*) CALLOC_STRUCT(R700ALUInstruction
);
286 Init_R700ALUInstruction(pALUinst
);
287 AddALUInstruction(pShader
, pALUinst
);
288 texOffset
+= GetInstructionSize(SIT_ALU
);
289 vtxOffset
+= GetInstructionSize(SIT_ALU
);
292 pInst
= pShader
->lstALUInstructions
.pHead
;
296 pALUinst
= (R700ALUInstruction
*)pInst
;
298 if(pALUinst
->m_pLinkedALUClause
!= NULL
)
300 // This address is quad-word aligned
301 pALUinst
->m_pLinkedALUClause
->m_Word0
.f
.addr
= (aluOffset
+ uiSize
) >> 1;
304 uiSize
+= GetInstructionSize(pALUinst
->m_ShaderInstType
);
306 pInst
= pInst
->pNextInst
;
309 pInst
= pShader
->lstTEXInstructions
.pHead
;
313 pTEXinst
= (R700TextureInstruction
*)pInst
;
315 if (pTEXinst
->m_pLinkedGenericClause
!= NULL
)
317 pTEXinst
->m_pLinkedGenericClause
->m_Word0
.f
.addr
= (texOffset
+ uiSize
) >> 1;
320 uiSize
+= GetInstructionSize(pTEXinst
->m_ShaderInstType
);
322 pInst
= pInst
->pNextInst
;
325 pInst
= pShader
->lstVTXInstructions
.pHead
;
329 pVTXinst
= (R700VertexInstruction
*)pInst
;
331 if (pVTXinst
->m_pLinkedGenericClause
!= NULL
)
333 pVTXinst
->m_pLinkedGenericClause
->m_Word0
.f
.addr
= (vtxOffset
+ uiSize
) >> 1;
336 uiSize
+= GetInstructionSize(pVTXinst
->m_ShaderInstType
);
338 pInst
= pInst
->pNextInst
;
341 pShader
->bLinksDirty
= GL_FALSE
;
344 void Assemble(R700_Shader
*pShader
)
347 GLuint
*pShaderBinary
;
348 GLuint size_of_program
;
351 GLuint end_of_cf_instructions
;
352 GLuint number_of_alu_dwords
;
354 R700ShaderInstruction
*pInst
;
356 if(GL_TRUE
== pShader
->bBinaryShader
)
361 if(pShader
->bLinksDirty
== GL_TRUE
)
363 ResolveLinks(pShader
);
366 size_of_program
= pShader
->uShaderBinaryDWORDSize
;
368 pShaderBinary
= (GLuint
*) MALLOC(sizeof(GLuint
)*size_of_program
);
370 pCurrPos
= pShaderBinary
;
372 for (i
= 0; i
< size_of_program
; i
++)
374 pShaderBinary
[i
] = 0;
377 pInst
= pShader
->lstCFInstructions
.pHead
;
380 switch (pInst
->m_ShaderInstType
)
384 R700ControlFlowGenericClause
* pCFgeneric
= (R700ControlFlowGenericClause
*)pInst
;
385 *pCurrPos
++ = pCFgeneric
->m_Word0
.val
;
386 *pCurrPos
++ = pCFgeneric
->m_Word1
.val
;
391 R700ControlFlowALUClause
* pCFalu
= (R700ControlFlowALUClause
*)pInst
;
392 *pCurrPos
++ = pCFalu
->m_Word0
.val
;
393 *pCurrPos
++ = pCFalu
->m_Word1
.val
;
396 case SIT_CF_ALL_EXP_SX
:
398 R700ControlFlowSXClause
* pCFsx
= (R700ControlFlowSXClause
*)pInst
;
399 *pCurrPos
++ = pCFsx
->m_Word0
.val
;
400 *pCurrPos
++ = (pCFsx
->m_Word1
.val
| pCFsx
->m_Word1_SWIZ
.val
);
403 case SIT_CF_ALL_EXP_SMX
:
405 R700ControlFlowSMXClause
* pCFsmx
= (R700ControlFlowSMXClause
*)pInst
;
406 *pCurrPos
++ = pCFsmx
->m_Word0
.val
;
407 *pCurrPos
++ = (pCFsmx
->m_Word1
.val
| pCFsmx
->m_Word1_BUF
.val
);
414 pInst
= pInst
->pNextInst
;
417 number_of_alu_dwords
= 0;
418 pInst
= pShader
->lstALUInstructions
.pHead
;
421 switch (pInst
->m_ShaderInstType
)
425 R700ALUInstruction
* pALU
= (R700ALUInstruction
*)pInst
;
427 *pCurrPos
++ = pALU
->m_Word0
.val
;
428 *pCurrPos
++ = (pALU
->m_Word1
.val
| pALU
->m_Word1_OP2
.val
| pALU
->m_Word1_OP3
.val
);
430 number_of_alu_dwords
+= 2;
433 case SIT_ALU_HALF_LIT
:
435 R700ALUInstructionHalfLiteral
* pALUhalf
= (R700ALUInstructionHalfLiteral
*)pInst
;
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
));
442 number_of_alu_dwords
+= 4;
445 case SIT_ALU_FALL_LIT
:
447 R700ALUInstructionFullLiteral
* pALUfull
= (R700ALUInstructionFullLiteral
*)pInst
;
449 *pCurrPos
++ = pALUfull
->m_Word0
.val
;
450 *pCurrPos
++ = (pALUfull
->m_Word1
.val
| pALUfull
->m_Word1_OP2
.val
| pALUfull
->m_Word1_OP3
.val
);
452 *pCurrPos
++ = *((GLuint
*)&(pALUfull
->m_fLiteralX
));
453 *pCurrPos
++ = *((GLuint
*)&(pALUfull
->m_fLiteralY
));
454 *pCurrPos
++ = *((GLuint
*)&(pALUfull
->m_fLiteralZ
));
455 *pCurrPos
++ = *((GLuint
*)&(pALUfull
->m_fLiteralW
));
457 number_of_alu_dwords
+= 6;
464 pInst
= pInst
->pNextInst
;
467 pInst
= pShader
->lstTEXInstructions
.pHead
;
470 R700TextureInstruction
* pTEX
= (R700TextureInstruction
*)pInst
;
472 *pCurrPos
++ = pTEX
->m_Word0
.val
;
473 *pCurrPos
++ = pTEX
->m_Word1
.val
;
474 *pCurrPos
++ = pTEX
->m_Word2
.val
;
475 *pCurrPos
++ = 0x0beadeaf;
477 pInst
= pInst
->pNextInst
;
480 pInst
= pShader
->lstVTXInstructions
.pHead
;
483 switch (pInst
->m_ShaderInstType
)
487 R700VertexSemanticFetch
* pVTXsem
= (R700VertexSemanticFetch
*)pInst
;
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;
495 case SIT_VTX_GENERIC
: //
497 R700VertexGenericFetch
* pVTXgeneric
= (R700VertexGenericFetch
*)pInst
;
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;
509 pInst
= pInst
->pNextInst
;
512 if(NULL
!= pShader
->pProgram
)
514 FREE(pShader
->pProgram
);
516 pShader
->pProgram
= (GLubyte
*)pShaderBinary
;
518 end_of_cf_instructions
= pShader
->uCFOffset
+ pShader
->lstCFInstructions
.uNumOfNode
* GetInstructionSize(SIT_CF
);
520 pShader
->uEndOfCF
= end_of_cf_instructions
>> 1;
522 pShader
->uEndOfALU
= (end_of_cf_instructions
+ number_of_alu_dwords
) >> 1;
524 pShader
->uEndOfFetch
= (pShader
->uCFOffset
+ pShader
->uShaderBinaryDWORDSize
) >> 1;
526 pShader
->bNeedsAssembly
= GL_FALSE
;
529 void LoadProgram(R700_Shader
*pShader
) //context
533 void UpdateShaderRegisters(R700_Shader
*pShader
) //context
537 void DeleteInstructions(R700_Shader
*pShader
)
541 void DebugPrint(void)
545 void cleanup_vfetch_shaderinst(R700_Shader
*pShader
)
547 R700ShaderInstruction
*pInst
;
548 R700ShaderInstruction
*pInstToFree
;
549 R700VertexInstruction
*pVTXInst
;
550 R700ControlFlowInstruction
*pCFInst
;
552 pInst
= pShader
->lstVTXInstructions
.pHead
;
555 pVTXInst
= (R700VertexInstruction
*)pInst
;
556 pShader
->uShaderBinaryDWORDSize
-= GetInstructionSize(pVTXInst
->m_ShaderInstType
);
558 if(NULL
!= pVTXInst
->m_pLinkedGenericClause
)
560 pCFInst
= (R700ControlFlowInstruction
*)(pVTXInst
->m_pLinkedGenericClause
);
562 TakeInstOutFromList(&(pShader
->lstCFInstructions
),
563 (R700ShaderInstruction
*)pCFInst
);
565 pShader
->uShaderBinaryDWORDSize
-= GetInstructionSize(pCFInst
->m_ShaderInstType
);
568 pInst
= pInst
->pNextInst
;
571 //destroy each item in pShader->lstVTXInstructions;
572 pInst
= pShader
->lstVTXInstructions
.pHead
;
576 pInst
= pInst
->pNextInst
;
580 //set NULL pShader->lstVTXInstructions
581 pShader
->lstVTXInstructions
.pHead
=NULL
;
582 pShader
->lstVTXInstructions
.pTail
=NULL
;
583 pShader
->lstVTXInstructions
.uNumOfNode
=0;
586 void Clean_Up_Shader(R700_Shader
*pShader
)
588 FREE(pShader
->pProgram
);
590 R700ShaderInstruction
*pInst
;
591 R700ShaderInstruction
*pInstToFree
;
593 pInst
= pShader
->lstCFInstructions
.pHead
;
597 pInst
= pInst
->pNextInst
;
600 pInst
= pShader
->lstALUInstructions
.pHead
;
604 pInst
= pInst
->pNextInst
;
607 pInst
= pShader
->lstTEXInstructions
.pHead
;
611 pInst
= pInst
->pNextInst
;
614 pInst
= pShader
->lstVTXInstructions
.pHead
;
618 pInst
= pInst
->pNextInst
;