llvmpipe: Eliminate non-LLVM fs execution paths.
[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_screen.h"
40 #include "lp_context.h"
41 #include "lp_state.h"
42 #include "lp_quad.h"
43
44
45 static void
46 shader_generate(struct llvmpipe_screen *screen,
47 struct lp_fragment_shader *shader)
48 {
49 const struct tgsi_token *tokens = shader->base.tokens;
50 union lp_type type;
51 LLVMTypeRef elem_type;
52 LLVMTypeRef vec_type;
53 LLVMTypeRef arg_types[7];
54 LLVMTypeRef func_type;
55 LLVMValueRef pos_ptr;
56 LLVMValueRef a0_ptr;
57 LLVMValueRef dadx_ptr;
58 LLVMValueRef dady_ptr;
59 LLVMValueRef consts_ptr;
60 LLVMValueRef outputs_ptr;
61 LLVMValueRef samplers_ptr;
62 LLVMBasicBlockRef block;
63 LLVMBuilderRef builder;
64 LLVMValueRef pos[NUM_CHANNELS];
65 LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
66 char name[32];
67 unsigned i, j;
68
69 type.value = 0;
70 type.floating = TRUE;
71 type.sign = TRUE;
72 type.norm = FALSE;
73 type.width = 32;
74 type.length = 4;
75
76 elem_type = lp_build_elem_type(type);
77 vec_type = lp_build_vec_type(type);
78
79 arg_types[0] = LLVMPointerType(vec_type, 0); /* pos */
80 arg_types[1] = LLVMPointerType(vec_type, 0); /* a0 */
81 arg_types[2] = LLVMPointerType(vec_type, 0); /* dadx */
82 arg_types[3] = LLVMPointerType(vec_type, 0); /* dady */
83 arg_types[4] = LLVMPointerType(elem_type, 0); /* consts */
84 arg_types[5] = LLVMPointerType(vec_type, 0); /* outputs */
85 arg_types[6] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */
86
87 func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
88
89 shader->function = LLVMAddFunction(screen->module, "shader", func_type);
90 LLVMSetFunctionCallConv(shader->function, LLVMCCallConv);
91
92 pos_ptr = LLVMGetParam(shader->function, 0);
93 a0_ptr = LLVMGetParam(shader->function, 1);
94 dadx_ptr = LLVMGetParam(shader->function, 2);
95 dady_ptr = LLVMGetParam(shader->function, 3);
96 consts_ptr = LLVMGetParam(shader->function, 4);
97 outputs_ptr = LLVMGetParam(shader->function, 5);
98 samplers_ptr = LLVMGetParam(shader->function, 6);
99
100 LLVMSetValueName(pos_ptr, "pos");
101 LLVMSetValueName(a0_ptr, "a0");
102 LLVMSetValueName(dadx_ptr, "dadx");
103 LLVMSetValueName(dady_ptr, "dady");
104 LLVMSetValueName(consts_ptr, "consts");
105 LLVMSetValueName(outputs_ptr, "outputs");
106 LLVMSetValueName(samplers_ptr, "samplers");
107
108 block = LLVMAppendBasicBlock(shader->function, "entry");
109 builder = LLVMCreateBuilder();
110 LLVMPositionBuilderAtEnd(builder, block);
111
112 for(j = 0; j < NUM_CHANNELS; ++j) {
113 LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), j, 0);
114 util_snprintf(name, sizeof name, "pos.%c", "xyzw"[j]);
115 pos[j] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, pos_ptr, &index, 1, ""), name);
116 }
117
118 memset(outputs, 0, sizeof outputs);
119
120 lp_build_tgsi_soa(builder, tokens, type,
121 pos, a0_ptr, dadx_ptr, dady_ptr,
122 consts_ptr, outputs, samplers_ptr);
123
124 for(i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i) {
125 for(j = 0; j < NUM_CHANNELS; ++j) {
126 if(outputs[i][j]) {
127 LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i*NUM_CHANNELS + j, 0);
128 util_snprintf(name, sizeof name, "output%u.%c", i, "xyzw"[j]);
129 LLVMBuildStore(builder, outputs[i][j], LLVMBuildGEP(builder, outputs_ptr, &index, 1, name));
130 }
131 }
132 }
133
134 LLVMBuildRetVoid(builder);;
135
136 LLVMDisposeBuilder(builder);
137 }
138
139
140 void *
141 llvmpipe_create_fs_state(struct pipe_context *pipe,
142 const struct pipe_shader_state *templ)
143 {
144 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
145 struct lp_fragment_shader *shader;
146 LLVMValueRef fetch_texel;
147
148 shader = CALLOC_STRUCT(lp_fragment_shader);
149 if (!shader)
150 return NULL;
151
152 /* get/save the summary info for this shader */
153 tgsi_scan_shader(templ->tokens, &shader->info);
154
155 /* we need to keep a local copy of the tokens */
156 shader->base.tokens = tgsi_dup_tokens(templ->tokens);
157
158 shader->screen = screen;
159
160 #ifdef DEBUG
161 tgsi_dump(templ->tokens, 0);
162 #endif
163
164 shader_generate(screen, shader);
165
166 LLVMRunFunctionPassManager(screen->pass, shader->function);
167
168 #ifdef DEBUG
169 LLVMDumpValue(shader->function);
170 debug_printf("\n");
171 #endif
172
173 if(LLVMVerifyFunction(shader->function, LLVMPrintMessageAction)) {
174 LLVMDumpValue(shader->function);
175 abort();
176 }
177
178 fetch_texel = LLVMGetNamedFunction(screen->module, "fetch_texel");
179 if(fetch_texel) {
180 static boolean first_time = TRUE;
181 if(first_time) {
182 LLVMAddGlobalMapping(screen->engine, fetch_texel, lp_build_tgsi_fetch_texel_soa);
183 first_time = FALSE;
184 }
185 }
186
187 shader->jit_function = (lp_shader_fs_func)LLVMGetPointerToGlobal(screen->engine, shader->function);
188
189 return shader;
190 }
191
192
193 void
194 llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
195 {
196 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
197
198 llvmpipe->fs = (struct lp_fragment_shader *) fs;
199
200 llvmpipe->dirty |= LP_NEW_FS;
201 }
202
203
204 void
205 llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
206 {
207 struct lp_fragment_shader *shader = fs;
208 struct llvmpipe_screen *screen = shader->screen;
209
210 assert(fs != llvmpipe_context(pipe)->fs);
211
212 if(shader->function) {
213 if(shader->jit_function)
214 LLVMFreeMachineCodeForFunction(screen->engine, shader->function);
215 LLVMDeleteFunction(shader->function);
216 }
217
218 FREE((void *) shader->base.tokens);
219 FREE(shader);
220 }
221
222
223 void *
224 llvmpipe_create_vs_state(struct pipe_context *pipe,
225 const struct pipe_shader_state *templ)
226 {
227 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
228 struct lp_vertex_shader *state;
229
230 state = CALLOC_STRUCT(lp_vertex_shader);
231 if (state == NULL )
232 goto fail;
233
234 /* copy shader tokens, the ones passed in will go away.
235 */
236 state->shader.tokens = tgsi_dup_tokens(templ->tokens);
237 if (state->shader.tokens == NULL)
238 goto fail;
239
240 state->draw_data = draw_create_vertex_shader(llvmpipe->draw, templ);
241 if (state->draw_data == NULL)
242 goto fail;
243
244 return state;
245
246 fail:
247 if (state) {
248 FREE( (void *)state->shader.tokens );
249 FREE( state->draw_data );
250 FREE( state );
251 }
252 return NULL;
253 }
254
255
256 void
257 llvmpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
258 {
259 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
260
261 llvmpipe->vs = (const struct lp_vertex_shader *)vs;
262
263 draw_bind_vertex_shader(llvmpipe->draw,
264 (llvmpipe->vs ? llvmpipe->vs->draw_data : NULL));
265
266 llvmpipe->dirty |= LP_NEW_VS;
267 }
268
269
270 void
271 llvmpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
272 {
273 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
274
275 struct lp_vertex_shader *state =
276 (struct lp_vertex_shader *)vs;
277
278 draw_delete_vertex_shader(llvmpipe->draw, state->draw_data);
279 FREE( state );
280 }
281
282
283
284 void
285 llvmpipe_set_constant_buffer(struct pipe_context *pipe,
286 uint shader, uint index,
287 const struct pipe_constant_buffer *buf)
288 {
289 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
290
291 assert(shader < PIPE_SHADER_TYPES);
292 assert(index == 0);
293
294 /* note: reference counting */
295 pipe_buffer_reference(&llvmpipe->constants[shader].buffer,
296 buf ? buf->buffer : NULL);
297
298 llvmpipe->dirty |= LP_NEW_CONSTANTS;
299 }