Merge commit 'nha/r300-compiler-gallium'
[mesa.git] / src / mesa / drivers / dri / r600 / r700_vertprog.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
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #include "main/imports.h"
35 #include "main/mtypes.h"
36
37 #include "tnl/t_context.h"
38 #include "shader/prog_parameter.h"
39 #include "shader/prog_statevars.h"
40
41 #include "r600_context.h"
42 #include "r600_cmdbuf.h"
43
44 #include "r700_debug.h"
45 #include "r700_vertprog.h"
46
47 unsigned int Map_Vertex_Output(r700_AssemblerBase *pAsm,
48 struct gl_vertex_program *mesa_vp,
49 unsigned int unStart)
50 {
51 unsigned int i;
52 unsigned int unBit;
53 unsigned int unTotal = unStart;
54
55 //!!!!!!! THE ORDER MATCH FS INPUT
56
57 unBit = 1 << VERT_RESULT_HPOS;
58 if(mesa_vp->Base.OutputsWritten & unBit)
59 {
60 pAsm->ucVP_OutputMap[VERT_RESULT_HPOS] = unTotal++;
61 }
62
63 unBit = 1 << VERT_RESULT_COL0;
64 if(mesa_vp->Base.OutputsWritten & unBit)
65 {
66 pAsm->ucVP_OutputMap[VERT_RESULT_COL0] = unTotal++;
67 }
68
69 unBit = 1 << VERT_RESULT_COL1;
70 if(mesa_vp->Base.OutputsWritten & unBit)
71 {
72 pAsm->ucVP_OutputMap[VERT_RESULT_COL1] = unTotal++;
73 }
74
75 //TODO : dealing back face.
76 unBit = 1 << VERT_RESULT_BFC0;
77 if(mesa_vp->Base.OutputsWritten & unBit)
78 {
79 pAsm->ucVP_OutputMap[VERT_RESULT_BFC0] = unTotal++;
80 }
81
82 unBit = 1 << VERT_RESULT_BFC1;
83 if(mesa_vp->Base.OutputsWritten & unBit)
84 {
85 pAsm->ucVP_OutputMap[VERT_RESULT_BFC1] = unTotal++;
86 }
87
88 //TODO : dealing fog.
89 unBit = 1 << VERT_RESULT_FOGC;
90 if(mesa_vp->Base.OutputsWritten & unBit)
91 {
92 pAsm->ucVP_OutputMap[VERT_RESULT_FOGC] = unTotal++;
93 }
94
95 //TODO : dealing point size.
96 unBit = 1 << VERT_RESULT_PSIZ;
97 if(mesa_vp->Base.OutputsWritten & unBit)
98 {
99 pAsm->ucVP_OutputMap[VERT_RESULT_PSIZ] = unTotal++;
100 }
101
102 for(i=0; i<8; i++)
103 {
104 unBit = 1 << (VERT_RESULT_TEX0 + i);
105 if(mesa_vp->Base.OutputsWritten & unBit)
106 {
107 pAsm->ucVP_OutputMap[VERT_RESULT_TEX0 + i] = unTotal++;
108 }
109 }
110
111 return (unTotal - unStart);
112 }
113
114 unsigned int Map_Vertex_Input(r700_AssemblerBase *pAsm,
115 struct gl_vertex_program *mesa_vp,
116 unsigned int unStart)
117 {
118 int i;
119 unsigned int unBit;
120 unsigned int unTotal = unStart;
121 for(i=0; i<VERT_ATTRIB_MAX; i++)
122 {
123 unBit = 1 << i;
124 if(mesa_vp->Base.InputsRead & unBit)
125 {
126 pAsm->ucVP_AttributeMap[i] = unTotal++;
127 }
128 }
129 return (unTotal - unStart);
130 }
131
132 GLboolean Process_Vertex_Program_Vfetch_Instructions(
133 struct r700_vertex_program *vp,
134 struct gl_vertex_program *mesa_vp)
135 {
136 int i;
137 unsigned int unBit;
138 VTX_FETCH_METHOD vtxFetchMethod;
139 vtxFetchMethod.bEnableMini = GL_FALSE;
140 vtxFetchMethod.mega_fetch_remainder = 0;
141
142 for(i=0; i<VERT_ATTRIB_MAX; i++)
143 {
144 unBit = 1 << i;
145 if(mesa_vp->Base.InputsRead & unBit)
146 {
147 assemble_vfetch_instruction(&vp->r700AsmCode,
148 i,
149 vp->r700AsmCode.ucVP_AttributeMap[i],
150 vp->aos_desc[i].size,
151 vp->aos_desc[i].type,
152 &vtxFetchMethod);
153 }
154 }
155
156 return GL_TRUE;
157 }
158
159 void Map_Vertex_Program(struct r700_vertex_program *vp,
160 struct gl_vertex_program *mesa_vp)
161 {
162 GLuint ui;
163 r700_AssemblerBase *pAsm = &(vp->r700AsmCode);
164 unsigned int num_inputs;
165
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;
169
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;
173
174 // Create VFETCH instructions for inputs
175 if (GL_TRUE != Process_Vertex_Program_Vfetch_Instructions(vp, mesa_vp) )
176 {
177 r700_error(ERROR_ASM_VTX_CLAUSE, "Calling Process_Vertex_Program_Vfetch_Instructions return error. \n");
178 return; //error
179 }
180
181 // Map Outputs
182 pAsm->number_of_exports = Map_Vertex_Output(pAsm, mesa_vp, pAsm->number_used_registers);
183
184 pAsm->starting_export_register_number = pAsm->number_used_registers;
185
186 pAsm->number_used_registers += pAsm->number_of_exports;
187
188 pAsm->pucOutMask = (unsigned char*) MALLOC(pAsm->number_of_exports);
189
190 for(ui=0; ui<pAsm->number_of_exports; ui++)
191 {
192 pAsm->pucOutMask[ui] = 0x0;
193 }
194
195 /* Map temporary registers (GPRs) */
196 pAsm->starting_temp_register_number = pAsm->number_used_registers;
197
198 if(mesa_vp->Base.NumNativeTemporaries >= mesa_vp->Base.NumTemporaries)
199 { /* arb uses NumNativeTemporaries */
200 pAsm->number_used_registers += mesa_vp->Base.NumNativeTemporaries;
201 }
202 else
203 { /* fix func t_vp uses NumTemporaries */
204 pAsm->number_used_registers += mesa_vp->Base.NumTemporaries;
205 }
206
207 pAsm->uFirstHelpReg = pAsm->number_used_registers;
208 }
209
210 GLboolean Find_Instruction_Dependencies_vp(struct r700_vertex_program *vp,
211 struct gl_vertex_program *mesa_vp)
212 {
213 GLuint i, j;
214 GLint * puiTEMPwrites;
215 struct prog_instruction *pILInst;
216 InstDeps *pInstDeps;
217
218 puiTEMPwrites = (GLint*) MALLOC(sizeof(GLuint)*mesa_vp->Base.NumTemporaries);
219 for(i=0; i<mesa_vp->Base.NumTemporaries; i++)
220 {
221 puiTEMPwrites[i] = -1;
222 }
223
224 pInstDeps = (InstDeps*)MALLOC(sizeof(InstDeps)*mesa_vp->Base.NumInstructions);
225
226 for(i=0; i<mesa_vp->Base.NumInstructions; i++)
227 {
228 pInstDeps[i].nDstDep = -1;
229 pILInst = &(mesa_vp->Base.Instructions[i]);
230
231 //Dst
232 if(pILInst->DstReg.File == PROGRAM_TEMPORARY)
233 {
234 //Set lastwrite for the temp
235 puiTEMPwrites[pILInst->DstReg.Index] = i;
236 }
237
238 //Src
239 for(j=0; j<3; j++)
240 {
241 if(pILInst->SrcReg[j].File == PROGRAM_TEMPORARY)
242 {
243 //Set dep.
244 pInstDeps[i].nSrcDeps[j] = puiTEMPwrites[pILInst->SrcReg[j].Index];
245 }
246 else
247 {
248 pInstDeps[i].nSrcDeps[j] = -1;
249 }
250 }
251 }
252
253 vp->r700AsmCode.pInstDeps = pInstDeps;
254
255 FREE(puiTEMPwrites);
256
257 return GL_TRUE;
258 }
259
260 GLboolean r700TranslateVertexShader(struct r700_vertex_program *vp,
261 struct gl_vertex_program *mesa_vp)
262 {
263 //Init_Program
264 Init_r700_AssemblerBase(SPT_VP, &(vp->r700AsmCode), &(vp->r700Shader) );
265 Map_Vertex_Program( vp, mesa_vp );
266
267 if(GL_FALSE == Find_Instruction_Dependencies_vp(vp, mesa_vp))
268 {
269 return GL_FALSE;
270 }
271
272 if(GL_FALSE == AssembleInstr(mesa_vp->Base.NumInstructions,
273 &(mesa_vp->Base.Instructions[0]),
274 &(vp->r700AsmCode)) )
275 {
276 return GL_FALSE;
277 }
278
279 if(GL_FALSE == Process_Vertex_Exports(&(vp->r700AsmCode), mesa_vp->Base.OutputsWritten) )
280 {
281 return GL_FALSE;
282 }
283
284 vp->r700Shader.nRegs = (vp->r700AsmCode.number_used_registers == 0) ? 0
285 : (vp->r700AsmCode.number_used_registers - 1);
286
287 vp->r700Shader.nParamExports = vp->r700AsmCode.number_of_exports;
288
289 vp->translated = GL_TRUE;
290
291 return GL_TRUE;
292 }
293
294 void r700SelectVertexShader(GLcontext *ctx)
295 {
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)
300 {
301 vpc->r700AsmCode.bR6xx = 1;
302 }
303
304 TNLcontext *tnl = TNL_CONTEXT(ctx);
305 struct vertex_buffer *vb = &tnl->vb;
306
307 unsigned int unBit;
308 unsigned int i;
309 for(i=0; i<VERT_ATTRIB_MAX; i++)
310 {
311 unBit = 1 << i;
312 if(vpc->mesa_program.Base.InputsRead & unBit) /* ctx->Array.ArrayObj->xxxxxxx */
313 {
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;
317 }
318 }
319
320 if(GL_FALSE == vpc->translated)
321 {
322 r700TranslateVertexShader(vpc,
323 &(vpc->mesa_program) );
324 }
325 }
326
327 void * r700GetActiveVpShaderBo(GLcontext * ctx)
328 {
329 struct r700_vertex_program *vp
330 = (struct r700_vertex_program *)ctx->VertexProgram._Current;
331
332 return vp->shaderbo;
333 }
334
335 GLboolean r700SetupVertexProgram(GLcontext * ctx)
336 {
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;
342
343 struct gl_program_parameter_list *paramList;
344 unsigned int unNumParamData;
345 unsigned int ui;
346
347 if(GL_FALSE == vp->loaded)
348 {
349 if(vp->r700Shader.bNeedsAssembly == GL_TRUE)
350 {
351 Assemble( &(vp->r700Shader) );
352 }
353
354 /* Load vp to gpu */
355 r600EmitShader(ctx,
356 &(vp->shaderbo),
357 (GLvoid *)(vp->r700Shader.pProgram),
358 vp->r700Shader.uShaderBinaryDWORDSize,
359 "VS");
360
361 vp->loaded = GL_TRUE;
362 }
363
364 DumpHwBinary(DUMP_VERTEX_SHADER, (GLvoid *)(vp->r700Shader.pProgram),
365 vp->r700Shader.uShaderBinaryDWORDSize);
366
367 /* TODO : enable this after MemUse fixed *=
368 (context->chipobj.MemUse)(context, vp->shadercode.buf->id);
369 */
370
371 r700->vs.SQ_PGM_START_VS.u32All = 0; /* set from buffer object. */
372
373 SETfield(r700->vs.SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.nRegs + 1,
374 NUM_GPRS_shift, NUM_GPRS_mask);
375
376 if(vp->r700Shader.uStackSize) /* we don't use branch for now, it should be zero. */
377 {
378 SETfield(r700->vs.SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.uStackSize,
379 STACK_SIZE_shift, STACK_SIZE_mask);
380 }
381
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);
386
387 /*
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);
390 */
391
392 /* sent out shader constants. */
393 paramList = vp->mesa_program.Base.Parameters;
394
395 if(NULL != paramList)
396 {
397 _mesa_load_state_parameters(ctx, paramList);
398
399 unNumParamData = paramList->NumParameters * 4;
400
401 BEGIN_BATCH_NO_AUTOSTATE(unNumParamData + 2);
402
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);
406
407 unNumParamData = paramList->NumParameters;
408
409 for(ui=0; ui<unNumParamData; ui++)
410 {
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])));
415 }
416 END_BATCH();
417 COMMIT_BATCH();
418 }
419
420 return GL_TRUE;
421 }
422
423
424
425