gallivm/sample: pass indirect offset into texture/image units
[mesa.git] / src / gallium / auxiliary / draw / draw_llvm_sample.c
1 /**************************************************************************
2 *
3 * Copyright 2010 VMware, Inc.
4 * All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * Texture sampling code generation
30 * @author Jose Fonseca <jfonseca@vmware.com>
31 */
32
33 #include "pipe/p_defines.h"
34 #include "pipe/p_shader_tokens.h"
35 #include "gallivm/lp_bld_const.h"
36 #include "gallivm/lp_bld_debug.h"
37 #include "gallivm/lp_bld_type.h"
38 #include "gallivm/lp_bld_sample.h"
39 #include "gallivm/lp_bld_tgsi.h"
40
41
42 #include "util/u_debug.h"
43 #include "util/u_memory.h"
44 #include "util/u_pointer.h"
45 #include "util/u_string.h"
46
47 #include "draw_llvm.h"
48
49
50 /**
51 * This provides the bridge between the sampler state store in
52 * lp_jit_context and lp_jit_texture and the sampler code
53 * generator. It provides the texture layout information required by
54 * the texture sampler code generator in terms of the state stored in
55 * lp_jit_context and lp_jit_texture in runtime.
56 */
57 struct draw_llvm_sampler_dynamic_state
58 {
59 struct lp_sampler_dynamic_state base;
60
61 const struct draw_sampler_static_state *static_state;
62 };
63
64
65 /**
66 * This is the bridge between our sampler and the TGSI translator.
67 */
68 struct draw_llvm_sampler_soa
69 {
70 struct lp_build_sampler_soa base;
71
72 struct draw_llvm_sampler_dynamic_state dynamic_state;
73
74 unsigned nr_samplers;
75 };
76
77 struct draw_llvm_image_dynamic_state
78 {
79 struct lp_sampler_dynamic_state base;
80
81 const struct draw_image_static_state *static_state;
82 };
83
84 struct draw_llvm_image_soa
85 {
86 struct lp_build_image_soa base;
87
88 struct draw_llvm_image_dynamic_state dynamic_state;
89 };
90
91 /**
92 * Fetch the specified member of the lp_jit_texture structure.
93 * \param emit_load if TRUE, emit the LLVM load instruction to actually
94 * fetch the field's value. Otherwise, just emit the
95 * GEP code to address the field.
96 *
97 * @sa http://llvm.org/docs/GetElementPtr.html
98 */
99 static LLVMValueRef
100 draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base,
101 struct gallivm_state *gallivm,
102 LLVMValueRef context_ptr,
103 unsigned texture_unit,
104 LLVMValueRef texture_unit_offset,
105 unsigned member_index,
106 const char *member_name,
107 boolean emit_load)
108 {
109 LLVMBuilderRef builder = gallivm->builder;
110 LLVMValueRef indices[4];
111 LLVMValueRef ptr;
112 LLVMValueRef res;
113
114 debug_assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
115
116 /* context[0] */
117 indices[0] = lp_build_const_int32(gallivm, 0);
118 /* context[0].textures */
119 indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_TEXTURES);
120 /* context[0].textures[unit] */
121 indices[2] = lp_build_const_int32(gallivm, texture_unit);
122 /* context[0].textures[unit].member */
123 indices[3] = lp_build_const_int32(gallivm, member_index);
124
125 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
126
127 if (emit_load)
128 res = LLVMBuildLoad(builder, ptr, "");
129 else
130 res = ptr;
131
132 lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);
133
134 return res;
135 }
136
137
138 /**
139 * Fetch the specified member of the lp_jit_sampler structure.
140 * \param emit_load if TRUE, emit the LLVM load instruction to actually
141 * fetch the field's value. Otherwise, just emit the
142 * GEP code to address the field.
143 *
144 * @sa http://llvm.org/docs/GetElementPtr.html
145 */
146 static LLVMValueRef
147 draw_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
148 struct gallivm_state *gallivm,
149 LLVMValueRef context_ptr,
150 unsigned sampler_unit,
151 unsigned member_index,
152 const char *member_name,
153 boolean emit_load)
154 {
155 LLVMBuilderRef builder = gallivm->builder;
156 LLVMValueRef indices[4];
157 LLVMValueRef ptr;
158 LLVMValueRef res;
159
160 debug_assert(sampler_unit < PIPE_MAX_SAMPLERS);
161
162 /* context[0] */
163 indices[0] = lp_build_const_int32(gallivm, 0);
164 /* context[0].samplers */
165 indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_SAMPLERS);
166 /* context[0].samplers[unit] */
167 indices[2] = lp_build_const_int32(gallivm, sampler_unit);
168 /* context[0].samplers[unit].member */
169 indices[3] = lp_build_const_int32(gallivm, member_index);
170
171 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
172
173 if (emit_load)
174 res = LLVMBuildLoad(builder, ptr, "");
175 else
176 res = ptr;
177
178 lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);
179
180 return res;
181 }
182
183 /**
184 * Fetch the specified member of the lp_jit_texture structure.
185 * \param emit_load if TRUE, emit the LLVM load instruction to actually
186 * fetch the field's value. Otherwise, just emit the
187 * GEP code to address the field.
188 *
189 * @sa http://llvm.org/docs/GetElementPtr.html
190 */
191 static LLVMValueRef
192 draw_llvm_image_member(const struct lp_sampler_dynamic_state *base,
193 struct gallivm_state *gallivm,
194 LLVMValueRef context_ptr,
195 unsigned image_unit,
196 LLVMValueRef image_unit_offset,
197 unsigned member_index,
198 const char *member_name,
199 boolean emit_load)
200 {
201 LLVMBuilderRef builder = gallivm->builder;
202 LLVMValueRef indices[4];
203 LLVMValueRef ptr;
204 LLVMValueRef res;
205
206 debug_assert(image_unit < PIPE_MAX_SHADER_IMAGES);
207
208 /* context[0] */
209 indices[0] = lp_build_const_int32(gallivm, 0);
210 /* context[0].textures */
211 indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_IMAGES);
212 /* context[0].textures[unit] */
213 indices[2] = lp_build_const_int32(gallivm, image_unit);
214 /* context[0].textures[unit].member */
215 indices[3] = lp_build_const_int32(gallivm, member_index);
216
217 ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
218
219 if (emit_load)
220 res = LLVMBuildLoad(builder, ptr, "");
221 else
222 res = ptr;
223
224 lp_build_name(res, "context.image%u.%s", image_unit, member_name);
225
226 return res;
227 }
228
229 /**
230 * Helper macro to instantiate the functions that generate the code to
231 * fetch the members of lp_jit_texture to fulfill the sampler code
232 * generator requests.
233 *
234 * This complexity is the price we have to pay to keep the texture
235 * sampler code generator a reusable module without dependencies to
236 * llvmpipe internals.
237 */
238 #define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \
239 static LLVMValueRef \
240 draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \
241 struct gallivm_state *gallivm, \
242 LLVMValueRef context_ptr, \
243 unsigned texture_unit, \
244 LLVMValueRef texture_unit_offset) \
245 { \
246 return draw_llvm_texture_member(base, gallivm, context_ptr, \
247 texture_unit, texture_unit_offset, \
248 _index, #_name, _emit_load ); \
249 }
250
251
252 DRAW_LLVM_TEXTURE_MEMBER(width, DRAW_JIT_TEXTURE_WIDTH, TRUE)
253 DRAW_LLVM_TEXTURE_MEMBER(height, DRAW_JIT_TEXTURE_HEIGHT, TRUE)
254 DRAW_LLVM_TEXTURE_MEMBER(depth, DRAW_JIT_TEXTURE_DEPTH, TRUE)
255 DRAW_LLVM_TEXTURE_MEMBER(first_level,DRAW_JIT_TEXTURE_FIRST_LEVEL, TRUE)
256 DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE)
257 DRAW_LLVM_TEXTURE_MEMBER(base_ptr, DRAW_JIT_TEXTURE_BASE, TRUE)
258 DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE)
259 DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE)
260 DRAW_LLVM_TEXTURE_MEMBER(mip_offsets, DRAW_JIT_TEXTURE_MIP_OFFSETS, FALSE)
261 DRAW_LLVM_TEXTURE_MEMBER(num_samples, DRAW_JIT_TEXTURE_NUM_SAMPLES, TRUE)
262 DRAW_LLVM_TEXTURE_MEMBER(sample_stride, DRAW_JIT_TEXTURE_SAMPLE_STRIDE, TRUE)
263
264 #define DRAW_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load) \
265 static LLVMValueRef \
266 draw_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \
267 struct gallivm_state *gallivm, \
268 LLVMValueRef context_ptr, \
269 unsigned sampler_unit) \
270 { \
271 return draw_llvm_sampler_member(base, gallivm, context_ptr, \
272 sampler_unit, _index, #_name, _emit_load ); \
273 }
274
275
276 DRAW_LLVM_SAMPLER_MEMBER(min_lod, DRAW_JIT_SAMPLER_MIN_LOD, TRUE)
277 DRAW_LLVM_SAMPLER_MEMBER(max_lod, DRAW_JIT_SAMPLER_MAX_LOD, TRUE)
278 DRAW_LLVM_SAMPLER_MEMBER(lod_bias, DRAW_JIT_SAMPLER_LOD_BIAS, TRUE)
279 DRAW_LLVM_SAMPLER_MEMBER(border_color, DRAW_JIT_SAMPLER_BORDER_COLOR, FALSE)
280
281 #define DRAW_LLVM_IMAGE_MEMBER(_name, _index, _emit_load) \
282 static LLVMValueRef \
283 draw_llvm_image_##_name( const struct lp_sampler_dynamic_state *base, \
284 struct gallivm_state *gallivm, \
285 LLVMValueRef context_ptr, \
286 unsigned image_unit, LLVMValueRef image_unit_offset) \
287 { \
288 return draw_llvm_image_member(base, gallivm, context_ptr, \
289 image_unit, image_unit_offset, \
290 _index, #_name, _emit_load ); \
291 }
292
293
294 DRAW_LLVM_IMAGE_MEMBER(width, DRAW_JIT_IMAGE_WIDTH, TRUE)
295 DRAW_LLVM_IMAGE_MEMBER(height, DRAW_JIT_IMAGE_HEIGHT, TRUE)
296 DRAW_LLVM_IMAGE_MEMBER(depth, DRAW_JIT_IMAGE_DEPTH, TRUE)
297 DRAW_LLVM_IMAGE_MEMBER(base_ptr, DRAW_JIT_IMAGE_BASE, TRUE)
298 DRAW_LLVM_IMAGE_MEMBER(row_stride, DRAW_JIT_IMAGE_ROW_STRIDE, TRUE)
299 DRAW_LLVM_IMAGE_MEMBER(img_stride, DRAW_JIT_IMAGE_IMG_STRIDE, TRUE)
300 DRAW_LLVM_IMAGE_MEMBER(num_samples, DRAW_JIT_IMAGE_NUM_SAMPLES, TRUE)
301 DRAW_LLVM_IMAGE_MEMBER(sample_stride, DRAW_JIT_IMAGE_SAMPLE_STRIDE, TRUE)
302
303 static void
304 draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
305 {
306 FREE(sampler);
307 }
308
309
310 /**
311 * Fetch filtered values from texture.
312 * The 'texel' parameter returns four vectors corresponding to R, G, B, A.
313 */
314 static void
315 draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
316 struct gallivm_state *gallivm,
317 const struct lp_sampler_params *params)
318 {
319 struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
320 unsigned texture_index = params->texture_index;
321 unsigned sampler_index = params->sampler_index;
322
323 assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
324 assert(sampler_index < PIPE_MAX_SAMPLERS);
325
326 if (params->texture_index_offset) {
327 struct lp_build_sample_array_switch switch_info;
328 memset(&switch_info, 0, sizeof(switch_info));
329 LLVMValueRef unit = LLVMBuildAdd(gallivm->builder, params->texture_index_offset,
330 lp_build_const_int32(gallivm, texture_index), "");
331 lp_build_sample_array_init_soa(&switch_info, gallivm, params, unit,
332 0, sampler->nr_samplers);
333
334 for (unsigned i = 0; i < sampler->nr_samplers; i++) {
335 lp_build_sample_array_case_soa(&switch_info, i,
336 &sampler->dynamic_state.static_state[i].texture_state,
337 &sampler->dynamic_state.static_state[i].sampler_state,
338 &sampler->dynamic_state.base);
339 }
340 lp_build_sample_array_fini_soa(&switch_info);
341 } else {
342 lp_build_sample_soa(&sampler->dynamic_state.static_state[texture_index].texture_state,
343 &sampler->dynamic_state.static_state[sampler_index].sampler_state,
344 &sampler->dynamic_state.base,
345 gallivm, params);
346 }
347 }
348
349
350 /**
351 * Fetch the texture size.
352 */
353 static void
354 draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
355 struct gallivm_state *gallivm,
356 const struct lp_sampler_size_query_params *params)
357 {
358 struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
359
360 assert(params->texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
361
362 lp_build_size_query_soa(gallivm,
363 &sampler->dynamic_state.static_state[params->texture_unit].texture_state,
364 &sampler->dynamic_state.base,
365 params);
366 }
367
368 struct lp_build_sampler_soa *
369 draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state,
370 unsigned nr_samplers)
371 {
372 struct draw_llvm_sampler_soa *sampler;
373
374 sampler = CALLOC_STRUCT(draw_llvm_sampler_soa);
375 if (!sampler)
376 return NULL;
377
378 sampler->base.destroy = draw_llvm_sampler_soa_destroy;
379 sampler->base.emit_tex_sample = draw_llvm_sampler_soa_emit_fetch_texel;
380 sampler->base.emit_size_query = draw_llvm_sampler_soa_emit_size_query;
381 sampler->dynamic_state.base.width = draw_llvm_texture_width;
382 sampler->dynamic_state.base.height = draw_llvm_texture_height;
383 sampler->dynamic_state.base.depth = draw_llvm_texture_depth;
384 sampler->dynamic_state.base.first_level = draw_llvm_texture_first_level;
385 sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level;
386 sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride;
387 sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride;
388 sampler->dynamic_state.base.base_ptr = draw_llvm_texture_base_ptr;
389 sampler->dynamic_state.base.mip_offsets = draw_llvm_texture_mip_offsets;
390 sampler->dynamic_state.base.num_samples = draw_llvm_texture_num_samples;
391 sampler->dynamic_state.base.sample_stride = draw_llvm_texture_sample_stride;
392 sampler->dynamic_state.base.min_lod = draw_llvm_sampler_min_lod;
393 sampler->dynamic_state.base.max_lod = draw_llvm_sampler_max_lod;
394 sampler->dynamic_state.base.lod_bias = draw_llvm_sampler_lod_bias;
395 sampler->dynamic_state.base.border_color = draw_llvm_sampler_border_color;
396 sampler->dynamic_state.static_state = static_state;
397
398 sampler->nr_samplers = nr_samplers;
399 return &sampler->base;
400 }
401
402 static void
403 draw_llvm_image_soa_emit_op(const struct lp_build_image_soa *base,
404 struct gallivm_state *gallivm,
405 const struct lp_img_params *params)
406 {
407 struct draw_llvm_image_soa *image = (struct draw_llvm_image_soa *)base;
408 unsigned image_index = params->image_index;
409 assert(image_index < PIPE_MAX_SHADER_IMAGES);
410
411 lp_build_img_op_soa(&image->dynamic_state.static_state[image_index].image_state,
412 &image->dynamic_state.base,
413 gallivm, params);
414 }
415 /**
416 * Fetch the texture size.
417 */
418 static void
419 draw_llvm_image_soa_emit_size_query(const struct lp_build_image_soa *base,
420 struct gallivm_state *gallivm,
421 const struct lp_sampler_size_query_params *params)
422 {
423 struct draw_llvm_image_soa *image = (struct draw_llvm_image_soa *)base;
424
425 assert(params->texture_unit < PIPE_MAX_SHADER_IMAGES);
426
427 lp_build_size_query_soa(gallivm,
428 &image->dynamic_state.static_state[params->texture_unit].image_state,
429 &image->dynamic_state.base,
430 params);
431 }
432 static void
433 draw_llvm_image_soa_destroy(struct lp_build_image_soa *image)
434 {
435 FREE(image);
436 }
437
438 struct lp_build_image_soa *
439 draw_llvm_image_soa_create(const struct draw_image_static_state *static_state)
440 {
441 struct draw_llvm_image_soa *image;
442
443 image = CALLOC_STRUCT(draw_llvm_image_soa);
444 if (!image)
445 return NULL;
446
447 image->base.destroy = draw_llvm_image_soa_destroy;
448 image->base.emit_op = draw_llvm_image_soa_emit_op;
449 image->base.emit_size_query = draw_llvm_image_soa_emit_size_query;
450
451 image->dynamic_state.base.width = draw_llvm_image_width;
452 image->dynamic_state.base.height = draw_llvm_image_height;
453
454 image->dynamic_state.base.depth = draw_llvm_image_depth;
455 image->dynamic_state.base.base_ptr = draw_llvm_image_base_ptr;
456 image->dynamic_state.base.row_stride = draw_llvm_image_row_stride;
457 image->dynamic_state.base.img_stride = draw_llvm_image_img_stride;
458 image->dynamic_state.base.num_samples = draw_llvm_image_num_samples;
459 image->dynamic_state.base.sample_stride = draw_llvm_image_sample_stride;
460
461 image->dynamic_state.static_state = static_state;
462
463 return &image->base;
464 }