llvmpipe: Debug helper function to name llvm intermediate values.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_state_fs.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include "pipe/p_defines.h"
30 #include "util/u_memory.h"
31 #include "pipe/internal/p_winsys_screen.h"
32 #include "pipe/p_shader_tokens.h"
33 #include "draw/draw_context.h"
34 #include "tgsi/tgsi_dump.h"
35 #include "tgsi/tgsi_scan.h"
36 #include "tgsi/tgsi_parse.h"
37 #include "lp_bld_type.h"
38 #include "lp_bld_tgsi.h"
39 #include "lp_bld_debug.h"
40 #include "lp_screen.h"
41 #include "lp_context.h"
42 #include "lp_state.h"
43 #include "lp_quad.h"
44
45
46 static void
47 shader_generate(struct llvmpipe_screen *screen,
48 struct lp_fragment_shader *shader)
49 {
50 const struct tgsi_token *tokens = shader->base.tokens;
51 union lp_type type;
52 LLVMTypeRef elem_type;
53 LLVMTypeRef vec_type;
54 LLVMTypeRef int_vec_type;
55 LLVMTypeRef arg_types[8];
56 LLVMTypeRef func_type;
57 LLVMValueRef pos_ptr;
58 LLVMValueRef a0_ptr;
59 LLVMValueRef dadx_ptr;
60 LLVMValueRef dady_ptr;
61 LLVMValueRef consts_ptr;
62 LLVMValueRef outputs_ptr;
63 LLVMValueRef mask_ptr;
64 LLVMValueRef samplers_ptr;
65 LLVMBasicBlockRef block;
66 LLVMBuilderRef builder;
67 LLVMValueRef pos[NUM_CHANNELS];
68 LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
69 LLVMValueRef mask;
70 unsigned i, j;
71
72 type.value = 0;
73 type.floating = TRUE;
74 type.sign = TRUE;
75 type.norm = FALSE;
76 type.width = 32;
77 type.length = 4;
78
79 elem_type = lp_build_elem_type(type);
80 vec_type = lp_build_vec_type(type);
81 int_vec_type = lp_build_int_vec_type(type);
82
83 arg_types[0] = LLVMPointerType(vec_type, 0); /* pos */
84 arg_types[1] = LLVMPointerType(elem_type, 0); /* a0 */
85 arg_types[2] = LLVMPointerType(elem_type, 0); /* dadx */
86 arg_types[3] = LLVMPointerType(elem_type, 0); /* dady */
87 arg_types[4] = LLVMPointerType(elem_type, 0); /* consts */
88 arg_types[5] = LLVMPointerType(vec_type, 0); /* outputs */
89 arg_types[6] = LLVMPointerType(int_vec_type, 0); /* mask */
90 arg_types[7] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */
91
92 func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
93
94 shader->function = LLVMAddFunction(screen->module, "shader", func_type);
95 LLVMSetFunctionCallConv(shader->function, LLVMCCallConv);
96 for(i = 0; i < Elements(arg_types); ++i)
97 LLVMAddAttribute(LLVMGetParam(shader->function, i), LLVMNoAliasAttribute);
98
99 pos_ptr = LLVMGetParam(shader->function, 0);
100 a0_ptr = LLVMGetParam(shader->function, 1);
101 dadx_ptr = LLVMGetParam(shader->function, 2);
102 dady_ptr = LLVMGetParam(shader->function, 3);
103 consts_ptr = LLVMGetParam(shader->function, 4);
104 outputs_ptr = LLVMGetParam(shader->function, 5);
105 mask_ptr = LLVMGetParam(shader->function, 6);
106 samplers_ptr = LLVMGetParam(shader->function, 7);
107
108 lp_build_name(pos_ptr, "pos");
109 lp_build_name(a0_ptr, "a0");
110 lp_build_name(dadx_ptr, "dadx");
111 lp_build_name(dady_ptr, "dady");
112 lp_build_name(consts_ptr, "consts");
113 lp_build_name(outputs_ptr, "outputs");
114 lp_build_name(mask_ptr, "mask");
115 lp_build_name(samplers_ptr, "samplers");
116
117 block = LLVMAppendBasicBlock(shader->function, "entry");
118 builder = LLVMCreateBuilder();
119 LLVMPositionBuilderAtEnd(builder, block);
120
121 for(j = 0; j < NUM_CHANNELS; ++j) {
122 LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), j, 0);
123 pos[j] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, pos_ptr, &index, 1, ""), "");
124 lp_build_name(pos[j], "pos.%c", "xyzw"[j]);
125 }
126
127 memset(outputs, 0, sizeof outputs);
128
129 mask = lp_build_tgsi_soa(builder, tokens, type,
130 pos, a0_ptr, dadx_ptr, dady_ptr,
131 consts_ptr, outputs, samplers_ptr);
132
133 for(i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i) {
134 for(j = 0; j < NUM_CHANNELS; ++j) {
135 if(outputs[i][j]) {
136 LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i*NUM_CHANNELS + j, 0);
137 LLVMBuildStore(builder, outputs[i][j], LLVMBuildGEP(builder, outputs_ptr, &index, 1, ""));
138 lp_build_name(pos[j], "output%u.%c", i, "xyzw"[j]);
139 }
140 }
141 }
142
143 if(mask)
144 LLVMBuildStore(builder, mask, mask_ptr);
145
146 LLVMBuildRetVoid(builder);;
147
148 LLVMDisposeBuilder(builder);
149 }
150
151
152 void *
153 llvmpipe_create_fs_state(struct pipe_context *pipe,
154 const struct pipe_shader_state *templ)
155 {
156 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
157 struct lp_fragment_shader *shader;
158 LLVMValueRef fetch_texel;
159
160 shader = CALLOC_STRUCT(lp_fragment_shader);
161 if (!shader)
162 return NULL;
163
164 /* get/save the summary info for this shader */
165 tgsi_scan_shader(templ->tokens, &shader->info);
166
167 /* we need to keep a local copy of the tokens */
168 shader->base.tokens = tgsi_dup_tokens(templ->tokens);
169
170 shader->screen = screen;
171
172 #ifdef DEBUG
173 tgsi_dump(templ->tokens, 0);
174 #endif
175
176 shader_generate(screen, shader);
177
178 LLVMRunFunctionPassManager(screen->pass, shader->function);
179
180 #ifdef DEBUG
181 LLVMDumpValue(shader->function);
182 debug_printf("\n");
183 #endif
184
185 if(LLVMVerifyFunction(shader->function, LLVMPrintMessageAction)) {
186 LLVMDumpValue(shader->function);
187 abort();
188 }
189
190 fetch_texel = LLVMGetNamedFunction(screen->module, "fetch_texel");
191 if(fetch_texel) {
192 static boolean first_time = TRUE;
193 if(first_time) {
194 LLVMAddGlobalMapping(screen->engine, fetch_texel, lp_build_tgsi_fetch_texel_soa);
195 first_time = FALSE;
196 }
197 }
198
199 shader->jit_function = (lp_shader_fs_func)LLVMGetPointerToGlobal(screen->engine, shader->function);
200
201 #ifdef DEBUG
202 lp_disassemble(shader->jit_function);
203 #endif
204
205 return shader;
206 }
207
208
209 void
210 llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
211 {
212 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
213
214 llvmpipe->fs = (struct lp_fragment_shader *) fs;
215
216 llvmpipe->dirty |= LP_NEW_FS;
217 }
218
219
220 void
221 llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
222 {
223 struct lp_fragment_shader *shader = fs;
224 struct llvmpipe_screen *screen = shader->screen;
225
226 assert(fs != llvmpipe_context(pipe)->fs);
227
228 if(shader->function) {
229 if(shader->jit_function)
230 LLVMFreeMachineCodeForFunction(screen->engine, shader->function);
231 LLVMDeleteFunction(shader->function);
232 }
233
234 FREE((void *) shader->base.tokens);
235 FREE(shader);
236 }
237
238
239 void *
240 llvmpipe_create_vs_state(struct pipe_context *pipe,
241 const struct pipe_shader_state *templ)
242 {
243 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
244 struct lp_vertex_shader *state;
245
246 state = CALLOC_STRUCT(lp_vertex_shader);
247 if (state == NULL )
248 goto fail;
249
250 /* copy shader tokens, the ones passed in will go away.
251 */
252 state->shader.tokens = tgsi_dup_tokens(templ->tokens);
253 if (state->shader.tokens == NULL)
254 goto fail;
255
256 state->draw_data = draw_create_vertex_shader(llvmpipe->draw, templ);
257 if (state->draw_data == NULL)
258 goto fail;
259
260 return state;
261
262 fail:
263 if (state) {
264 FREE( (void *)state->shader.tokens );
265 FREE( state->draw_data );
266 FREE( state );
267 }
268 return NULL;
269 }
270
271
272 void
273 llvmpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
274 {
275 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
276
277 llvmpipe->vs = (const struct lp_vertex_shader *)vs;
278
279 draw_bind_vertex_shader(llvmpipe->draw,
280 (llvmpipe->vs ? llvmpipe->vs->draw_data : NULL));
281
282 llvmpipe->dirty |= LP_NEW_VS;
283 }
284
285
286 void
287 llvmpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
288 {
289 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
290
291 struct lp_vertex_shader *state =
292 (struct lp_vertex_shader *)vs;
293
294 draw_delete_vertex_shader(llvmpipe->draw, state->draw_data);
295 FREE( state );
296 }
297
298
299
300 void
301 llvmpipe_set_constant_buffer(struct pipe_context *pipe,
302 uint shader, uint index,
303 const struct pipe_constant_buffer *buf)
304 {
305 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
306
307 assert(shader < PIPE_SHADER_TYPES);
308 assert(index == 0);
309
310 /* note: reference counting */
311 pipe_buffer_reference(&llvmpipe->constants[shader].buffer,
312 buf ? buf->buffer : NULL);
313
314 llvmpipe->dirty |= LP_NEW_CONSTANTS;
315 }