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>
34 #include "main/imports.h"
35 #include "main/mtypes.h"
37 #include "tnl/t_context.h"
38 #include "shader/program.h"
39 #include "shader/prog_parameter.h"
40 #include "shader/prog_statevars.h"
42 #include "radeon_debug.h"
43 #include "r600_context.h"
44 #include "r600_cmdbuf.h"
45 #include "shader/programopt.c"
47 #include "r700_debug.h"
48 #include "r700_vertprog.h"
50 unsigned int Map_Vertex_Output(r700_AssemblerBase
*pAsm
,
51 struct gl_vertex_program
*mesa_vp
,
56 unsigned int unTotal
= unStart
;
58 //!!!!!!! THE ORDER MATCH FS INPUT
60 unBit
= 1 << VERT_RESULT_HPOS
;
61 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
63 pAsm
->ucVP_OutputMap
[VERT_RESULT_HPOS
] = unTotal
++;
66 unBit
= 1 << VERT_RESULT_COL0
;
67 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
69 pAsm
->ucVP_OutputMap
[VERT_RESULT_COL0
] = unTotal
++;
72 unBit
= 1 << VERT_RESULT_COL1
;
73 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
75 pAsm
->ucVP_OutputMap
[VERT_RESULT_COL1
] = unTotal
++;
78 //TODO : dealing back face.
79 unBit
= 1 << VERT_RESULT_BFC0
;
80 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
82 pAsm
->ucVP_OutputMap
[VERT_RESULT_BFC0
] = unTotal
++;
85 unBit
= 1 << VERT_RESULT_BFC1
;
86 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
88 pAsm
->ucVP_OutputMap
[VERT_RESULT_BFC1
] = unTotal
++;
92 unBit
= 1 << VERT_RESULT_FOGC
;
93 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
95 pAsm
->ucVP_OutputMap
[VERT_RESULT_FOGC
] = unTotal
++;
98 //TODO : dealing point size.
99 unBit
= 1 << VERT_RESULT_PSIZ
;
100 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
102 pAsm
->ucVP_OutputMap
[VERT_RESULT_PSIZ
] = unTotal
++;
107 unBit
= 1 << (VERT_RESULT_TEX0
+ i
);
108 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
110 pAsm
->ucVP_OutputMap
[VERT_RESULT_TEX0
+ i
] = unTotal
++;
114 return (unTotal
- unStart
);
117 unsigned int Map_Vertex_Input(r700_AssemblerBase
*pAsm
,
118 struct gl_vertex_program
*mesa_vp
,
119 unsigned int unStart
)
123 unsigned int unTotal
= unStart
;
124 for(i
=0; i
<VERT_ATTRIB_MAX
; i
++)
127 if(mesa_vp
->Base
.InputsRead
& unBit
)
129 pAsm
->ucVP_AttributeMap
[i
] = unTotal
++;
132 return (unTotal
- unStart
);
135 GLboolean
Process_Vertex_Program_Vfetch_Instructions(
136 struct r700_vertex_program
*vp
,
137 struct gl_vertex_program
*mesa_vp
)
141 VTX_FETCH_METHOD vtxFetchMethod
;
142 vtxFetchMethod
.bEnableMini
= GL_FALSE
;
143 vtxFetchMethod
.mega_fetch_remainder
= 0;
145 for(i
=0; i
<VERT_ATTRIB_MAX
; i
++)
148 if(mesa_vp
->Base
.InputsRead
& unBit
)
150 assemble_vfetch_instruction(&vp
->r700AsmCode
,
152 vp
->r700AsmCode
.ucVP_AttributeMap
[i
],
153 vp
->aos_desc
[i
].size
,
154 vp
->aos_desc
[i
].type
,
162 GLboolean
Process_Vertex_Program_Vfetch_Instructions2(
164 struct r700_vertex_program
*vp
,
165 struct gl_vertex_program
*mesa_vp
)
168 context_t
*context
= R700_CONTEXT(ctx
);
170 VTX_FETCH_METHOD vtxFetchMethod
;
171 vtxFetchMethod
.bEnableMini
= GL_FALSE
;
172 vtxFetchMethod
.mega_fetch_remainder
= 0;
174 for(i
=0; i
<context
->nNumActiveAos
; i
++)
176 assemble_vfetch_instruction2(&vp
->r700AsmCode
,
177 vp
->r700AsmCode
.ucVP_AttributeMap
[context
->stream_desc
[i
].element
],
178 context
->stream_desc
[i
].type
,
179 context
->stream_desc
[i
].size
,
180 context
->stream_desc
[i
].element
,
181 context
->stream_desc
[i
]._signed
,
182 context
->stream_desc
[i
].normalize
,
189 void Map_Vertex_Program(GLcontext
*ctx
,
190 struct r700_vertex_program
*vp
,
191 struct gl_vertex_program
*mesa_vp
)
194 r700_AssemblerBase
*pAsm
= &(vp
->r700AsmCode
);
195 unsigned int num_inputs
;
197 // R0 will always be used for index into vertex buffer
198 pAsm
->number_used_registers
= 1;
199 pAsm
->starting_vfetch_register_number
= pAsm
->number_used_registers
;
201 // Map Inputs: Add 1 to mapping since R0 is used for index
202 num_inputs
= Map_Vertex_Input(pAsm
, mesa_vp
, pAsm
->number_used_registers
);
203 pAsm
->number_used_registers
+= num_inputs
;
205 // Create VFETCH instructions for inputs
206 if(1 == vp
->uiVersion
)
208 if (GL_TRUE
!= Process_Vertex_Program_Vfetch_Instructions(vp
, mesa_vp
) )
210 radeon_error("Calling Process_Vertex_Program_Vfetch_Instructions return error. \n");
216 if (GL_TRUE
!= Process_Vertex_Program_Vfetch_Instructions2(ctx
, vp
, mesa_vp
) )
218 radeon_error("Calling Process_Vertex_Program_Vfetch_Instructions2 return error. \n");
224 pAsm
->number_of_exports
= Map_Vertex_Output(pAsm
, mesa_vp
, pAsm
->number_used_registers
);
226 pAsm
->starting_export_register_number
= pAsm
->number_used_registers
;
228 pAsm
->number_used_registers
+= pAsm
->number_of_exports
;
230 pAsm
->pucOutMask
= (unsigned char*) MALLOC(pAsm
->number_of_exports
);
232 for(ui
=0; ui
<pAsm
->number_of_exports
; ui
++)
234 pAsm
->pucOutMask
[ui
] = 0x0;
237 /* Map temporary registers (GPRs) */
238 pAsm
->starting_temp_register_number
= pAsm
->number_used_registers
;
240 if(mesa_vp
->Base
.NumNativeTemporaries
>= mesa_vp
->Base
.NumTemporaries
)
241 { /* arb uses NumNativeTemporaries */
242 pAsm
->number_used_registers
+= mesa_vp
->Base
.NumNativeTemporaries
;
245 { /* fix func t_vp uses NumTemporaries */
246 pAsm
->number_used_registers
+= mesa_vp
->Base
.NumTemporaries
;
249 pAsm
->uFirstHelpReg
= pAsm
->number_used_registers
;
252 GLboolean
Find_Instruction_Dependencies_vp(struct r700_vertex_program
*vp
,
253 struct gl_vertex_program
*mesa_vp
)
256 GLint
* puiTEMPwrites
;
257 struct prog_instruction
*pILInst
;
260 puiTEMPwrites
= (GLint
*) MALLOC(sizeof(GLuint
)*mesa_vp
->Base
.NumTemporaries
);
261 for(i
=0; i
<mesa_vp
->Base
.NumTemporaries
; i
++)
263 puiTEMPwrites
[i
] = -1;
266 pInstDeps
= (InstDeps
*)MALLOC(sizeof(InstDeps
)*mesa_vp
->Base
.NumInstructions
);
268 for(i
=0; i
<mesa_vp
->Base
.NumInstructions
; i
++)
270 pInstDeps
[i
].nDstDep
= -1;
271 pILInst
= &(mesa_vp
->Base
.Instructions
[i
]);
274 if(pILInst
->DstReg
.File
== PROGRAM_TEMPORARY
)
276 //Set lastwrite for the temp
277 puiTEMPwrites
[pILInst
->DstReg
.Index
] = i
;
283 if(pILInst
->SrcReg
[j
].File
== PROGRAM_TEMPORARY
)
286 pInstDeps
[i
].nSrcDeps
[j
] = puiTEMPwrites
[pILInst
->SrcReg
[j
].Index
];
290 pInstDeps
[i
].nSrcDeps
[j
] = -1;
295 vp
->r700AsmCode
.pInstDeps
= pInstDeps
;
302 struct r700_vertex_program
* r700TranslateVertexShader(GLcontext
*ctx
,
303 struct gl_vertex_program
*mesa_vp
,
306 context_t
*context
= R700_CONTEXT(ctx
);
307 struct r700_vertex_program
*vp
;
308 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
309 struct vertex_buffer
*vb
= &tnl
->vb
;
313 vp
= _mesa_calloc(sizeof(*vp
));
314 vp
->uiVersion
= nVer
;
315 vp
->mesa_program
= (struct gl_vertex_program
*)_mesa_clone_program(ctx
, &mesa_vp
->Base
);
317 if (mesa_vp
->IsPositionInvariant
)
319 _mesa_insert_mvp_code(ctx
, vp
->mesa_program
);
324 for(i
=0; i
<VERT_ATTRIB_MAX
; i
++)
327 if(vp
->mesa_program
->Base
.InputsRead
& unBit
) /* ctx->Array.ArrayObj->xxxxxxx */
329 vp
->aos_desc
[i
].size
= vb
->AttribPtr
[i
]->size
;
330 vp
->aos_desc
[i
].stride
= vb
->AttribPtr
[i
]->size
* sizeof(GL_FLOAT
);/* when emit array, data is packed. vb->AttribPtr[i]->stride;*/
331 vp
->aos_desc
[i
].type
= GL_FLOAT
;
337 for(i
=0; i
<context
->nNumActiveAos
; i
++)
339 vp
->aos_desc
[i
].size
= context
->stream_desc
[i
].size
;
340 vp
->aos_desc
[i
].stride
= context
->stream_desc
[i
].stride
;
341 vp
->aos_desc
[i
].type
= context
->stream_desc
[i
].type
;
345 if (context
->radeon
.radeonScreen
->chip_family
< CHIP_FAMILY_RV770
)
347 vp
->r700AsmCode
.bR6xx
= 1;
351 Init_r700_AssemblerBase(SPT_VP
, &(vp
->r700AsmCode
), &(vp
->r700Shader
) );
352 Map_Vertex_Program(ctx
, vp
, vp
->mesa_program
);
354 if(GL_FALSE
== Find_Instruction_Dependencies_vp(vp
, vp
->mesa_program
))
359 if(GL_FALSE
== AssembleInstr(vp
->mesa_program
->Base
.NumInstructions
,
360 &(vp
->mesa_program
->Base
.Instructions
[0]),
361 &(vp
->r700AsmCode
)) )
366 if(GL_FALSE
== Process_Vertex_Exports(&(vp
->r700AsmCode
), vp
->mesa_program
->Base
.OutputsWritten
) )
371 vp
->r700Shader
.nRegs
= (vp
->r700AsmCode
.number_used_registers
== 0) ? 0
372 : (vp
->r700AsmCode
.number_used_registers
- 1);
374 vp
->r700Shader
.nParamExports
= vp
->r700AsmCode
.number_of_exports
;
376 vp
->translated
= GL_TRUE
;
381 void r700SelectVertexShader(GLcontext
*ctx
, GLint nVersion
)
383 context_t
*context
= R700_CONTEXT(ctx
);
384 struct r700_vertex_program_cont
*vpc
;
385 struct r700_vertex_program
*vp
;
386 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
387 struct vertex_buffer
*vb
= &tnl
->vb
;
391 GLbitfield InputsRead
;
393 vpc
= (struct r700_vertex_program_cont
*)ctx
->VertexProgram
._Current
;
395 InputsRead
= vpc
->mesa_program
.Base
.InputsRead
;
396 if (vpc
->mesa_program
.IsPositionInvariant
)
398 InputsRead
|= VERT_BIT_POS
;
401 for (vp
= vpc
->progs
; vp
; vp
= vp
->next
)
403 if (vp
->uiVersion
!= nVersion
)
408 for(i
=0; i
<VERT_ATTRIB_MAX
; i
++)
411 if(InputsRead
& unBit
)
413 if (vp
->aos_desc
[i
].size
!= vb
->AttribPtr
[i
]->size
)
423 for(i
=0; i
<context
->nNumActiveAos
; i
++)
425 if (vp
->aos_desc
[i
].size
!= context
->stream_desc
[i
].size
)
434 context
->selected_vp
= vp
;
439 vp
= r700TranslateVertexShader(ctx
, &(vpc
->mesa_program
), nVersion
);
442 radeon_error("Failed to translate vertex shader. \n");
445 vp
->next
= vpc
->progs
;
447 context
->selected_vp
= vp
;
451 int getTypeSize(GLenum type
)
456 return sizeof(GLdouble
);
458 return sizeof(GLfloat
);
460 return sizeof(GLint
);
461 case GL_UNSIGNED_INT
:
462 return sizeof(GLuint
);
464 return sizeof(GLshort
);
465 case GL_UNSIGNED_SHORT
:
466 return sizeof(GLushort
);
468 return sizeof(GLbyte
);
469 case GL_UNSIGNED_BYTE
:
470 return sizeof(GLubyte
);
477 static void r700TranslateAttrib(GLcontext
*ctx
, GLuint unLoc
, int count
, const struct gl_client_array
*input
)
479 context_t
*context
= R700_CONTEXT(ctx
);
481 StreamDesc
* pStreamDesc
= &(context
->stream_desc
[context
->nNumActiveAos
]);
485 stride
= (input
->StrideB
== 0) ? getTypeSize(input
->Type
) * input
->Size
488 if (input
->Type
== GL_DOUBLE
|| input
->Type
== GL_UNSIGNED_INT
|| input
->Type
== GL_INT
||
490 getTypeSize(input
->Type
) != 4 ||
494 pStreamDesc
->type
= GL_FLOAT
;
496 if (input
->StrideB
== 0)
498 pStreamDesc
->stride
= 0;
502 pStreamDesc
->stride
= sizeof(GLfloat
) * input
->Size
;
504 pStreamDesc
->dwords
= input
->Size
;
505 pStreamDesc
->is_named_bo
= GL_FALSE
;
509 pStreamDesc
->type
= input
->Type
;
510 pStreamDesc
->dwords
= (getTypeSize(input
->Type
) * input
->Size
+ 3)/ 4;
511 if (!input
->BufferObj
->Name
)
513 if (input
->StrideB
== 0)
515 pStreamDesc
->stride
= 0;
519 pStreamDesc
->stride
= (getTypeSize(pStreamDesc
->type
) * input
->Size
+ 3) & ~3;
522 pStreamDesc
->is_named_bo
= GL_FALSE
;
526 pStreamDesc
->size
= input
->Size
;
527 pStreamDesc
->dst_loc
= context
->nNumActiveAos
;
528 pStreamDesc
->element
= unLoc
;
530 switch (pStreamDesc
->type
)
533 pStreamDesc
->_signed
= 0;
534 pStreamDesc
->normalize
= GL_FALSE
;
537 pStreamDesc
->_signed
= 1;
538 pStreamDesc
->normalize
= input
->Normalized
;
541 pStreamDesc
->_signed
= 1;
542 pStreamDesc
->normalize
= input
->Normalized
;
544 case GL_UNSIGNED_SHORT
:
545 pStreamDesc
->_signed
= 0;
546 pStreamDesc
->normalize
= input
->Normalized
;
548 case GL_UNSIGNED_BYTE
:
549 pStreamDesc
->_signed
= 0;
550 pStreamDesc
->normalize
= input
->Normalized
;
554 case GL_UNSIGNED_INT
:
559 context
->nNumActiveAos
++;
562 void r700SetVertexFormat(GLcontext
*ctx
, const struct gl_client_array
*arrays
[], int count
)
564 context_t
*context
= R700_CONTEXT(ctx
);
565 struct r700_vertex_program
*vpc
566 = (struct r700_vertex_program
*)ctx
->VertexProgram
._Current
;
568 struct gl_vertex_program
* mesa_vp
= (struct gl_vertex_program
*)&(vpc
->mesa_program
);
569 unsigned int unLoc
= 0;
570 unsigned int unBit
= mesa_vp
->Base
.InputsRead
;
571 context
->nNumActiveAos
= 0;
577 r700TranslateAttrib(ctx
, unLoc
, count
, arrays
[unLoc
]);
583 context
->radeon
.tcl
.aos_count
= context
->nNumActiveAos
;
586 void * r700GetActiveVpShaderBo(GLcontext
* ctx
)
588 context_t
*context
= R700_CONTEXT(ctx
);
589 struct r700_vertex_program
*vp
= context
->selected_vp
;;
597 GLboolean
r700SetupVertexProgram(GLcontext
* ctx
)
599 context_t
*context
= R700_CONTEXT(ctx
);
600 R700_CHIP_CONTEXT
*r700
= (R700_CHIP_CONTEXT
*)(&context
->hw
);
601 struct r700_vertex_program
*vp
= context
->selected_vp
;
603 struct gl_program_parameter_list
*paramList
;
604 unsigned int unNumParamData
;
607 if(GL_FALSE
== vp
->loaded
)
609 if(vp
->r700Shader
.bNeedsAssembly
== GL_TRUE
)
611 Assemble( &(vp
->r700Shader
) );
617 (GLvoid
*)(vp
->r700Shader
.pProgram
),
618 vp
->r700Shader
.uShaderBinaryDWORDSize
,
621 vp
->loaded
= GL_TRUE
;
624 DumpHwBinary(DUMP_VERTEX_SHADER
, (GLvoid
*)(vp
->r700Shader
.pProgram
),
625 vp
->r700Shader
.uShaderBinaryDWORDSize
);
627 /* TODO : enable this after MemUse fixed *=
628 (context->chipobj.MemUse)(context, vp->shadercode.buf->id);
631 R600_STATECHANGE(context
, vs
);
632 R600_STATECHANGE(context
, fs
); /* hack */
634 r700
->vs
.SQ_PGM_RESOURCES_VS
.u32All
= 0;
635 SETbit(r700
->vs
.SQ_PGM_RESOURCES_VS
.u32All
, PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit
);
637 r700
->vs
.SQ_PGM_START_VS
.u32All
= 0; /* set from buffer object. */
639 SETfield(r700
->vs
.SQ_PGM_RESOURCES_VS
.u32All
, vp
->r700Shader
.nRegs
+ 1,
640 NUM_GPRS_shift
, NUM_GPRS_mask
);
642 if(vp
->r700Shader
.uStackSize
) /* we don't use branch for now, it should be zero. */
644 SETfield(r700
->vs
.SQ_PGM_RESOURCES_VS
.u32All
, vp
->r700Shader
.uStackSize
,
645 STACK_SIZE_shift
, STACK_SIZE_mask
);
648 R600_STATECHANGE(context
, spi
);
650 SETfield(r700
->SPI_VS_OUT_CONFIG
.u32All
,
651 vp
->r700Shader
.nParamExports
? (vp
->r700Shader
.nParamExports
- 1) : 0,
652 VS_EXPORT_COUNT_shift
, VS_EXPORT_COUNT_mask
);
653 SETfield(r700
->SPI_PS_IN_CONTROL_0
.u32All
, vp
->r700Shader
.nParamExports
,
654 NUM_INTERP_shift
, NUM_INTERP_mask
);
657 SETbit(r700->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
658 CLEARbit(r700->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
661 /* sent out shader constants. */
662 paramList
= vp
->mesa_program
->Base
.Parameters
;
664 if(NULL
!= paramList
) {
665 _mesa_load_state_parameters(ctx
, paramList
);
667 if (paramList
->NumParameters
> R700_MAX_DX9_CONSTS
)
670 R600_STATECHANGE(context
, vs_consts
);
672 r700
->vs
.num_consts
= paramList
->NumParameters
;
674 unNumParamData
= paramList
->NumParameters
;
676 for(ui
=0; ui
<unNumParamData
; ui
++) {
677 r700
->vs
.consts
[ui
][0].f32All
= paramList
->ParameterValues
[ui
][0];
678 r700
->vs
.consts
[ui
][1].f32All
= paramList
->ParameterValues
[ui
][1];
679 r700
->vs
.consts
[ui
][2].f32All
= paramList
->ParameterValues
[ui
][2];
680 r700
->vs
.consts
[ui
][3].f32All
= paramList
->ParameterValues
[ui
][3];
683 r700
->vs
.num_consts
= 0;