2 * Copyright (C) 2006 Ben Skeggs.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 * Ben Skeggs <darktama@iinet.net.au>
39 #include "nouveau_context.h"
40 #include "nouveau_shader.h"
41 #include "nouveau_msg.h"
44 /* Map nvsRegister temp ID onto hw temp ID */
45 unsigned int temps
[NVS_MAX_TEMPS
];
46 /* Track free hw registers */
47 unsigned int hw_temps
[NVS_MAX_TEMPS
];
51 pass2_alloc_hw_temp(nvsPtr nvs
)
53 struct pass2_rec
*rec
= nvs
->pass_rec
;
56 for (i
=0; i
<nvs
->func
->MaxTemp
; i
++) {
57 /* This is a *horrible* hack.. R0 is both temp0 and result.color
58 * in NV30/40 fragprogs, we can use R0 as a temp before result
59 * is written however..
61 if (nvs
->mesa
.vp
.Base
.Target
== GL_FRAGMENT_PROGRAM_ARB
&& i
==0)
63 if (rec
->hw_temps
[i
] == 0) {
73 pass2_mangle_reg(nvsPtr nvs
, nvsInstruction
*inst
, nvsRegister reg
)
75 struct pass2_rec
*rec
= nvs
->pass_rec
;
77 if (reg
.file
== NVS_FILE_TEMP
) {
78 if (rec
->temps
[reg
.index
] == -1)
79 rec
->temps
[reg
.index
] = pass2_alloc_hw_temp(nvs
);
80 reg
.index
= rec
->temps
[reg
.index
];
87 pass2_add_instruction(nvsPtr nvs
, nvsInstruction
*inst
,
88 struct _op_xlat
*op
, int slot
)
90 nvsSwzComp default_swz
[4] = { NVS_SWZ_X
, NVS_SWZ_Y
,
91 NVS_SWZ_Z
, NVS_SWZ_W
};
92 nvsFunc
*shader
= nvs
->func
;
96 shader
->SetOpcode(shader
, op
->NV
, slot
);
97 if (inst
->saturate
) shader
->SetSaturate(shader
);
98 if (inst
->cond_update
) shader
->SetCCUpdate(shader
);
99 if (inst
->cond_test
) shader
->SetCondition(shader
, 1, inst
->cond
,
102 else shader
->SetCondition(shader
, 0, NVS_COND_TR
,
111 shader
->SetTexImageUnit(shader
, inst
->tex_unit
);
117 for (i
= 0; i
< 3; i
++) {
118 if (op
->srcpos
[i
] != -1) {
119 reg
= pass2_mangle_reg(nvs
, inst
, inst
->src
[i
]);
121 shader
->SetSource(shader
, ®
, op
->srcpos
[i
]);
123 if (reg
.file
== NVS_FILE_CONST
&&
124 shader
->GetSourceConstVal
) {
126 nvs
->params
[reg
.index
].hw_index_cnt
++;
127 nvs
->params
[reg
.index
].hw_index
= realloc(
128 nvs
->params
[reg
.index
].hw_index
,
129 sizeof(int) * idx_slot
+1);
130 nvs
->params
[reg
.index
].hw_index
[idx_slot
] =
131 nvs
->program_current
+ 4;
136 reg
= pass2_mangle_reg(nvs
, inst
, inst
->dest
);
137 shader
->SetResult(shader
, ®
, inst
->mask
, slot
);
139 if (inst
->dest_scale
!= NVS_SCALE_1X
) {
140 shader
->SetResultScale(shader
, inst
->dest_scale
);
145 pass2_assemble_instruction(nvsPtr nvs
, nvsInstruction
*inst
, int last
)
147 nvsFunc
*shader
= nvs
->func
;
149 unsigned int hw_inst
[8];
154 shader
->inst
= hw_inst
;
156 /* Assemble this instruction */
157 if (!(op
= shader
->GetOPTXFromSOP(inst
->op
, &slot
)))
159 shader
->InitInstruction(shader
);
160 pass2_add_instruction(nvs
, inst
, op
, slot
);
162 shader
->SetLastInst(shader
);
164 instsz
= shader
->GetOffsetNext(nvs
->func
);
165 if (nvs
->program_size
+ instsz
>= nvs
->program_alloc_size
) {
166 nvs
->program_alloc_size
*= 2;
167 nvs
->program
= realloc(nvs
->program
,
168 nvs
->program_alloc_size
*
172 for (i
=0; i
<instsz
; i
++)
173 nvs
->program
[nvs
->program_current
++] = hw_inst
[i
];
174 nvs
->program_size
= nvs
->program_current
;
179 pass2_translate(nvsPtr nvs
, nvsFragmentHeader
*f
)
181 nvsFunc
*shader
= nvs
->func
;
185 last
= (f
== ((nvsSubroutine
*)nvs
->program_tree
)->insn_tail
);
188 case NVS_INSTRUCTION
:
189 if (!pass2_assemble_instruction(nvs
,
195 WARN_ONCE("Unimplemented fragment type\n");
205 /* Translate program into hardware format */
207 nouveau_shader_pass2(nvsPtr nvs
)
209 struct pass2_rec
*rec
;
212 rec
= calloc(1, sizeof(struct pass2_rec
));
213 for (i
=0; i
<NVS_MAX_TEMPS
; i
++)
217 /* Start off with allocating 4 uint32_t's for each inst, will be grown
220 nvs
->program_alloc_size
= nvs
->mesa
.vp
.Base
.NumInstructions
* 4;
221 nvs
->program
= calloc(nvs
->program_alloc_size
, sizeof(uint32_t));
222 nvs
->program_size
= 0;
223 nvs
->program_current
= 0;
225 if (!pass2_translate(nvs
,
226 ((nvsSubroutine
*)nvs
->program_tree
)->insn_head
)) {
232 /* Shrink allocated memory to only what we need */
233 nvs
->program
= realloc(nvs
->program
,
234 nvs
->program_size
* sizeof(uint32_t));
235 nvs
->program_alloc_size
= nvs
->program_size
;
238 nvs
->on_hardware
= 0;
240 if (NOUVEAU_DEBUG
& DEBUG_SHADERS
) {
241 fflush(stdout
); fflush(stderr
);
242 fprintf(stderr
, "-----------MESA PROGRAM target=%s, id=0x%x\n",
243 _mesa_lookup_enum_by_nr(
244 nvs
->mesa
.vp
.Base
.Target
),
245 nvs
->mesa
.vp
.Base
.Id
);
246 fflush(stdout
); fflush(stderr
);
247 _mesa_print_program(&nvs
->mesa
.vp
.Base
);
248 fflush(stdout
); fflush(stderr
);
249 fprintf(stderr
, "^^^^^^^^^^^^^^^^MESA PROGRAM\n");
250 fflush(stdout
); fflush(stderr
);
251 fprintf(stderr
, "----------------NV PROGRAM\n");
252 fflush(stdout
); fflush(stderr
);
253 nvsDisasmHWShader(nvs
);
254 fflush(stdout
); fflush(stderr
);
255 fprintf(stderr
, "^^^^^^^^^^^^^^^^NV PROGRAM\n");
256 fflush(stdout
); fflush(stderr
);