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/prog_parameter.h"
39 #include "shader/prog_statevars.h"
41 #include "r600_context.h"
42 #include "r600_cmdbuf.h"
44 #include "r700_debug.h"
45 #include "r700_vertprog.h"
47 unsigned int Map_Vertex_Output(r700_AssemblerBase
*pAsm
,
48 struct gl_vertex_program
*mesa_vp
,
53 unsigned int unTotal
= unStart
;
55 //!!!!!!! THE ORDER MATCH FS INPUT
57 unBit
= 1 << VERT_RESULT_HPOS
;
58 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
60 pAsm
->ucVP_OutputMap
[VERT_RESULT_HPOS
] = unTotal
++;
63 unBit
= 1 << VERT_RESULT_COL0
;
64 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
66 pAsm
->ucVP_OutputMap
[VERT_RESULT_COL0
] = unTotal
++;
69 unBit
= 1 << VERT_RESULT_COL1
;
70 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
72 pAsm
->ucVP_OutputMap
[VERT_RESULT_COL1
] = unTotal
++;
75 //TODO : dealing back face.
76 unBit
= 1 << VERT_RESULT_BFC0
;
77 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
79 pAsm
->ucVP_OutputMap
[VERT_RESULT_BFC0
] = unTotal
++;
82 unBit
= 1 << VERT_RESULT_BFC1
;
83 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
85 pAsm
->ucVP_OutputMap
[VERT_RESULT_BFC1
] = unTotal
++;
89 unBit
= 1 << VERT_RESULT_FOGC
;
90 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
92 pAsm
->ucVP_OutputMap
[VERT_RESULT_FOGC
] = unTotal
++;
95 //TODO : dealing point size.
96 unBit
= 1 << VERT_RESULT_PSIZ
;
97 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
99 pAsm
->ucVP_OutputMap
[VERT_RESULT_PSIZ
] = unTotal
++;
104 unBit
= 1 << (VERT_RESULT_TEX0
+ i
);
105 if(mesa_vp
->Base
.OutputsWritten
& unBit
)
107 pAsm
->ucVP_OutputMap
[VERT_RESULT_TEX0
+ i
] = unTotal
++;
111 return (unTotal
- unStart
);
114 unsigned int Map_Vertex_Input(r700_AssemblerBase
*pAsm
,
115 struct gl_vertex_program
*mesa_vp
,
116 unsigned int unStart
)
120 unsigned int unTotal
= unStart
;
121 for(i
=0; i
<VERT_ATTRIB_MAX
; i
++)
124 if(mesa_vp
->Base
.InputsRead
& unBit
)
126 pAsm
->ucVP_AttributeMap
[i
] = unTotal
++;
129 return (unTotal
- unStart
);
132 GLboolean
Process_Vertex_Program_Vfetch_Instructions(
133 struct r700_vertex_program
*vp
,
134 struct gl_vertex_program
*mesa_vp
)
138 VTX_FETCH_METHOD vtxFetchMethod
;
139 vtxFetchMethod
.bEnableMini
= GL_FALSE
;
140 vtxFetchMethod
.mega_fetch_remainder
= 0;
142 for(i
=0; i
<VERT_ATTRIB_MAX
; i
++)
145 if(mesa_vp
->Base
.InputsRead
& unBit
)
147 assemble_vfetch_instruction(&vp
->r700AsmCode
,
149 vp
->r700AsmCode
.ucVP_AttributeMap
[i
],
150 vp
->aos_desc
[i
].size
,
151 vp
->aos_desc
[i
].type
,
159 void Map_Vertex_Program(struct r700_vertex_program
*vp
,
160 struct gl_vertex_program
*mesa_vp
)
163 r700_AssemblerBase
*pAsm
= &(vp
->r700AsmCode
);
164 unsigned int num_inputs
;
166 // R0 will always be used for index into vertex buffer
167 pAsm
->number_used_registers
= 1;
168 pAsm
->starting_vfetch_register_number
= pAsm
->number_used_registers
;
170 // Map Inputs: Add 1 to mapping since R0 is used for index
171 num_inputs
= Map_Vertex_Input(pAsm
, mesa_vp
, pAsm
->number_used_registers
);
172 pAsm
->number_used_registers
+= num_inputs
;
174 // Create VFETCH instructions for inputs
175 if (GL_TRUE
!= Process_Vertex_Program_Vfetch_Instructions(vp
, mesa_vp
) )
177 r700_error(ERROR_ASM_VTX_CLAUSE
, "Calling Process_Vertex_Program_Vfetch_Instructions return error. \n");
182 pAsm
->number_of_exports
= Map_Vertex_Output(pAsm
, mesa_vp
, pAsm
->number_used_registers
);
184 pAsm
->starting_export_register_number
= pAsm
->number_used_registers
;
186 pAsm
->number_used_registers
+= pAsm
->number_of_exports
;
188 pAsm
->pucOutMask
= (unsigned char*) MALLOC(pAsm
->number_of_exports
);
190 for(ui
=0; ui
<pAsm
->number_of_exports
; ui
++)
192 pAsm
->pucOutMask
[ui
] = 0x0;
195 /* Map temporary registers (GPRs) */
196 pAsm
->starting_temp_register_number
= pAsm
->number_used_registers
;
198 if(mesa_vp
->Base
.NumNativeTemporaries
>= mesa_vp
->Base
.NumTemporaries
)
199 { /* arb uses NumNativeTemporaries */
200 pAsm
->number_used_registers
+= mesa_vp
->Base
.NumNativeTemporaries
;
203 { /* fix func t_vp uses NumTemporaries */
204 pAsm
->number_used_registers
+= mesa_vp
->Base
.NumTemporaries
;
207 pAsm
->uFirstHelpReg
= pAsm
->number_used_registers
;
210 GLboolean
Find_Instruction_Dependencies_vp(struct r700_vertex_program
*vp
,
211 struct gl_vertex_program
*mesa_vp
)
214 GLint
* puiTEMPwrites
;
215 struct prog_instruction
*pILInst
;
218 puiTEMPwrites
= (GLint
*) MALLOC(sizeof(GLuint
)*mesa_vp
->Base
.NumTemporaries
);
219 for(i
=0; i
<mesa_vp
->Base
.NumTemporaries
; i
++)
221 puiTEMPwrites
[i
] = -1;
224 pInstDeps
= (InstDeps
*)MALLOC(sizeof(InstDeps
)*mesa_vp
->Base
.NumInstructions
);
226 for(i
=0; i
<mesa_vp
->Base
.NumInstructions
; i
++)
228 pInstDeps
[i
].nDstDep
= -1;
229 pILInst
= &(mesa_vp
->Base
.Instructions
[i
]);
232 if(pILInst
->DstReg
.File
== PROGRAM_TEMPORARY
)
234 //Set lastwrite for the temp
235 puiTEMPwrites
[pILInst
->DstReg
.Index
] = i
;
241 if(pILInst
->SrcReg
[j
].File
== PROGRAM_TEMPORARY
)
244 pInstDeps
[i
].nSrcDeps
[j
] = puiTEMPwrites
[pILInst
->SrcReg
[j
].Index
];
248 pInstDeps
[i
].nSrcDeps
[j
] = -1;
253 vp
->r700AsmCode
.pInstDeps
= pInstDeps
;
260 GLboolean
r700TranslateVertexShader(struct r700_vertex_program
*vp
,
261 struct gl_vertex_program
*mesa_vp
)
264 Init_r700_AssemblerBase(SPT_VP
, &(vp
->r700AsmCode
), &(vp
->r700Shader
) );
265 Map_Vertex_Program( vp
, mesa_vp
);
267 if(GL_FALSE
== Find_Instruction_Dependencies_vp(vp
, mesa_vp
))
272 if(GL_FALSE
== AssembleInstr(mesa_vp
->Base
.NumInstructions
,
273 &(mesa_vp
->Base
.Instructions
[0]),
274 &(vp
->r700AsmCode
)) )
279 if(GL_FALSE
== Process_Vertex_Exports(&(vp
->r700AsmCode
), mesa_vp
->Base
.OutputsWritten
) )
284 vp
->r700Shader
.nRegs
= (vp
->r700AsmCode
.number_used_registers
== 0) ? 0
285 : (vp
->r700AsmCode
.number_used_registers
- 1);
287 vp
->r700Shader
.nParamExports
= vp
->r700AsmCode
.number_of_exports
;
289 vp
->translated
= GL_TRUE
;
294 void r700SelectVertexShader(GLcontext
*ctx
)
296 context_t
*context
= R700_CONTEXT(ctx
);
297 struct r700_vertex_program
*vpc
298 = (struct r700_vertex_program
*)ctx
->VertexProgram
._Current
;
299 if (context
->radeon
.radeonScreen
->chip_family
< CHIP_FAMILY_RV770
)
301 vpc
->r700AsmCode
.bR6xx
= 1;
304 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
305 struct vertex_buffer
*vb
= &tnl
->vb
;
309 for(i
=0; i
<VERT_ATTRIB_MAX
; i
++)
312 if(vpc
->mesa_program
.Base
.InputsRead
& unBit
) /* ctx->Array.ArrayObj->xxxxxxx */
314 vpc
->aos_desc
[i
].size
= vb
->AttribPtr
[i
]->size
;
315 vpc
->aos_desc
[i
].stride
= vb
->AttribPtr
[i
]->size
* sizeof(GL_FLOAT
);/* when emit array, data is packed. vb->AttribPtr[i]->stride;*/
316 vpc
->aos_desc
[i
].type
= GL_FLOAT
;
320 if(GL_FALSE
== vpc
->translated
)
322 r700TranslateVertexShader(vpc
,
323 &(vpc
->mesa_program
) );
327 void * r700GetActiveVpShaderBo(GLcontext
* ctx
)
329 struct r700_vertex_program
*vp
330 = (struct r700_vertex_program
*)ctx
->VertexProgram
._Current
;
335 GLboolean
r700SetupVertexProgram(GLcontext
* ctx
)
337 context_t
*context
= R700_CONTEXT(ctx
);
338 R700_CHIP_CONTEXT
*r700
= (R700_CHIP_CONTEXT
*)(&context
->hw
);
339 BATCH_LOCALS(&context
->radeon
);
340 struct r700_vertex_program
*vp
341 = (struct r700_vertex_program
*)ctx
->VertexProgram
._Current
;
343 struct gl_program_parameter_list
*paramList
;
344 unsigned int unNumParamData
;
347 if(GL_FALSE
== vp
->loaded
)
349 if(vp
->r700Shader
.bNeedsAssembly
== GL_TRUE
)
351 Assemble( &(vp
->r700Shader
) );
357 (GLvoid
*)(vp
->r700Shader
.pProgram
),
358 vp
->r700Shader
.uShaderBinaryDWORDSize
,
361 vp
->loaded
= GL_TRUE
;
364 DumpHwBinary(DUMP_VERTEX_SHADER
, (GLvoid
*)(vp
->r700Shader
.pProgram
),
365 vp
->r700Shader
.uShaderBinaryDWORDSize
);
367 /* TODO : enable this after MemUse fixed *=
368 (context->chipobj.MemUse)(context, vp->shadercode.buf->id);
371 r700
->vs
.SQ_PGM_START_VS
.u32All
= 0; /* set from buffer object. */
373 SETfield(r700
->vs
.SQ_PGM_RESOURCES_VS
.u32All
, vp
->r700Shader
.nRegs
+ 1,
374 NUM_GPRS_shift
, NUM_GPRS_mask
);
376 if(vp
->r700Shader
.uStackSize
) /* we don't use branch for now, it should be zero. */
378 SETfield(r700
->vs
.SQ_PGM_RESOURCES_VS
.u32All
, vp
->r700Shader
.uStackSize
,
379 STACK_SIZE_shift
, STACK_SIZE_mask
);
382 SETfield(r700
->SPI_VS_OUT_CONFIG
.u32All
, vp
->r700Shader
.nParamExports
? (vp
->r700Shader
.nParamExports
- 1) : 0,
383 VS_EXPORT_COUNT_shift
, VS_EXPORT_COUNT_mask
);
384 SETfield(r700
->SPI_PS_IN_CONTROL_0
.u32All
, vp
->r700Shader
.nParamExports
,
385 NUM_INTERP_shift
, NUM_INTERP_mask
);
388 SETbit(r700->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
389 CLEARbit(r700->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
392 /* sent out shader constants. */
393 paramList
= vp
->mesa_program
.Base
.Parameters
;
395 if(NULL
!= paramList
)
397 _mesa_load_state_parameters(ctx
, paramList
);
399 unNumParamData
= paramList
->NumParameters
* 4;
401 BEGIN_BATCH_NO_AUTOSTATE(unNumParamData
+ 2);
403 R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_ALU_CONST
, unNumParamData
));
404 /* assembler map const from very beginning. */
405 R600_OUT_BATCH(SQ_ALU_CONSTANT_VS_OFFSET
* 4);
407 unNumParamData
= paramList
->NumParameters
;
409 for(ui
=0; ui
<unNumParamData
; ui
++)
411 R600_OUT_BATCH(*((unsigned int*)&(paramList
->ParameterValues
[ui
][0])));
412 R600_OUT_BATCH(*((unsigned int*)&(paramList
->ParameterValues
[ui
][1])));
413 R600_OUT_BATCH(*((unsigned int*)&(paramList
->ParameterValues
[ui
][2])));
414 R600_OUT_BATCH(*((unsigned int*)&(paramList
->ParameterValues
[ui
][3])));