1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
4 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
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.
27 **************************************************************************/
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"
46 shader_generate(struct llvmpipe_screen
*screen
,
47 struct lp_fragment_shader
*shader
)
49 const struct tgsi_token
*tokens
= shader
->base
.tokens
;
51 LLVMTypeRef elem_type
;
53 LLVMTypeRef arg_types
[7];
54 LLVMTypeRef func_type
;
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
];
76 elem_type
= lp_build_elem_type(type
);
77 vec_type
= lp_build_vec_type(type
);
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 */
87 func_type
= LLVMFunctionType(LLVMVoidType(), arg_types
, Elements(arg_types
), 0);
89 shader
->function
= LLVMAddFunction(screen
->module
, "shader", func_type
);
90 LLVMSetFunctionCallConv(shader
->function
, LLVMCCallConv
);
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);
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");
108 block
= LLVMAppendBasicBlock(shader
->function
, "entry");
109 builder
= LLVMCreateBuilder();
110 LLVMPositionBuilderAtEnd(builder
, block
);
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
);
118 memset(outputs
, 0, sizeof outputs
);
120 lp_build_tgsi_soa(builder
, tokens
, type
,
121 pos
, a0_ptr
, dadx_ptr
, dady_ptr
,
122 consts_ptr
, outputs
, samplers_ptr
);
124 for(i
= 0; i
< PIPE_MAX_SHADER_OUTPUTS
; ++i
) {
125 for(j
= 0; j
< NUM_CHANNELS
; ++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
));
134 LLVMBuildRetVoid(builder
);;
136 LLVMDisposeBuilder(builder
);
141 llvmpipe_create_fs_state(struct pipe_context
*pipe
,
142 const struct pipe_shader_state
*templ
)
144 struct llvmpipe_screen
*screen
= llvmpipe_screen(pipe
->screen
);
145 struct lp_fragment_shader
*shader
;
146 LLVMValueRef fetch_texel
;
148 shader
= CALLOC_STRUCT(lp_fragment_shader
);
152 /* get/save the summary info for this shader */
153 tgsi_scan_shader(templ
->tokens
, &shader
->info
);
155 /* we need to keep a local copy of the tokens */
156 shader
->base
.tokens
= tgsi_dup_tokens(templ
->tokens
);
158 shader
->screen
= screen
;
161 tgsi_dump(templ
->tokens
, 0);
164 shader_generate(screen
, shader
);
166 LLVMRunFunctionPassManager(screen
->pass
, shader
->function
);
169 LLVMDumpValue(shader
->function
);
173 if(LLVMVerifyFunction(shader
->function
, LLVMPrintMessageAction
)) {
174 LLVMDumpValue(shader
->function
);
178 fetch_texel
= LLVMGetNamedFunction(screen
->module
, "fetch_texel");
180 static boolean first_time
= TRUE
;
182 LLVMAddGlobalMapping(screen
->engine
, fetch_texel
, lp_build_tgsi_fetch_texel_soa
);
187 shader
->jit_function
= (lp_shader_fs_func
)LLVMGetPointerToGlobal(screen
->engine
, shader
->function
);
194 llvmpipe_bind_fs_state(struct pipe_context
*pipe
, void *fs
)
196 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
198 llvmpipe
->fs
= (struct lp_fragment_shader
*) fs
;
200 llvmpipe
->dirty
|= LP_NEW_FS
;
205 llvmpipe_delete_fs_state(struct pipe_context
*pipe
, void *fs
)
207 struct lp_fragment_shader
*shader
= fs
;
208 struct llvmpipe_screen
*screen
= shader
->screen
;
210 assert(fs
!= llvmpipe_context(pipe
)->fs
);
212 if(shader
->function
) {
213 if(shader
->jit_function
)
214 LLVMFreeMachineCodeForFunction(screen
->engine
, shader
->function
);
215 LLVMDeleteFunction(shader
->function
);
218 FREE((void *) shader
->base
.tokens
);
224 llvmpipe_create_vs_state(struct pipe_context
*pipe
,
225 const struct pipe_shader_state
*templ
)
227 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
228 struct lp_vertex_shader
*state
;
230 state
= CALLOC_STRUCT(lp_vertex_shader
);
234 /* copy shader tokens, the ones passed in will go away.
236 state
->shader
.tokens
= tgsi_dup_tokens(templ
->tokens
);
237 if (state
->shader
.tokens
== NULL
)
240 state
->draw_data
= draw_create_vertex_shader(llvmpipe
->draw
, templ
);
241 if (state
->draw_data
== NULL
)
248 FREE( (void *)state
->shader
.tokens
);
249 FREE( state
->draw_data
);
257 llvmpipe_bind_vs_state(struct pipe_context
*pipe
, void *vs
)
259 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
261 llvmpipe
->vs
= (const struct lp_vertex_shader
*)vs
;
263 draw_bind_vertex_shader(llvmpipe
->draw
,
264 (llvmpipe
->vs
? llvmpipe
->vs
->draw_data
: NULL
));
266 llvmpipe
->dirty
|= LP_NEW_VS
;
271 llvmpipe_delete_vs_state(struct pipe_context
*pipe
, void *vs
)
273 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
275 struct lp_vertex_shader
*state
=
276 (struct lp_vertex_shader
*)vs
;
278 draw_delete_vertex_shader(llvmpipe
->draw
, state
->draw_data
);
285 llvmpipe_set_constant_buffer(struct pipe_context
*pipe
,
286 uint shader
, uint index
,
287 const struct pipe_constant_buffer
*buf
)
289 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(pipe
);
291 assert(shader
< PIPE_SHADER_TYPES
);
294 /* note: reference counting */
295 pipe_buffer_reference(&llvmpipe
->constants
[shader
].buffer
,
296 buf
? buf
->buffer
: NULL
);
298 llvmpipe
->dirty
|= LP_NEW_CONSTANTS
;