1 /**************************************************************************
2 *
3 * Copyright 2009 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 * @file
30 * C - JIT interfaces
31 *
32 * @author Jose Fonseca <[email protected]>
33 */
34
35 #include <llvm/Config/llvm-config.h>
36
37 #include "util/u_memory.h"
38 #include "gallivm/lp_bld_init.h"
39 #include "gallivm/lp_bld_debug.h"
40 #include "gallivm/lp_bld_format.h"
41 #include "lp_context.h"
42 #include "lp_debug.h"
43 #include "lp_memory.h"
44 #include "lp_screen.h"
45 #include "lp_jit.h"
46
47 static void
lp_jit_create_types(struct lp_fragment_shader_variant * lp)48 lp_jit_create_types(struct lp_fragment_shader_variant *lp)
49 {
50 struct gallivm_state *gallivm = lp->gallivm;
51 LLVMContextRef lc = gallivm->context;
52 LLVMTypeRef viewport_type;
53 LLVMTypeRef linear_elem_type;
54
55 /* struct lp_jit_viewport */
56 {
57 LLVMTypeRef elem_types[LP_JIT_VIEWPORT_NUM_FIELDS];
58
59 elem_types[LP_JIT_VIEWPORT_MIN_DEPTH] =
60 elem_types[LP_JIT_VIEWPORT_MAX_DEPTH] = LLVMFloatTypeInContext(lc);
61
62 viewport_type = LLVMStructTypeInContext(lc, elem_types,
63 ARRAY_SIZE(elem_types), 0);
64
65 LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, min_depth,
66 gallivm->target, viewport_type,
67 LP_JIT_VIEWPORT_MIN_DEPTH);
68 LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, max_depth,
69 gallivm->target, viewport_type,
70 LP_JIT_VIEWPORT_MAX_DEPTH);
71 LP_CHECK_STRUCT_SIZE(struct lp_jit_viewport,
72 gallivm->target, viewport_type);
73 }
74
75
76 /* struct lp_jit_context */
77 {
78 LLVMTypeRef elem_types[LP_JIT_CTX_COUNT];
79 LLVMTypeRef context_type;
80
81 elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatTypeInContext(lc);
82 elem_types[LP_JIT_CTX_SAMPLE_MASK] =
83 elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] =
84 elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32TypeInContext(lc);
85 elem_types[LP_JIT_CTX_U8_BLEND_COLOR] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
86 elem_types[LP_JIT_CTX_F_BLEND_COLOR] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0);
87 elem_types[LP_JIT_CTX_VIEWPORTS] = LLVMPointerType(viewport_type, 0);
88
89 context_type = LLVMStructTypeInContext(lc, elem_types,
90 ARRAY_SIZE(elem_types), 0);
91
92 LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
93 gallivm->target, context_type,
94 LP_JIT_CTX_ALPHA_REF);
95 LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_front,
96 gallivm->target, context_type,
97 LP_JIT_CTX_STENCIL_REF_FRONT);
98 LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_back,
99 gallivm->target, context_type,
100 LP_JIT_CTX_STENCIL_REF_BACK);
101 LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, u8_blend_color,
102 gallivm->target, context_type,
103 LP_JIT_CTX_U8_BLEND_COLOR);
104 LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, f_blend_color,
105 gallivm->target, context_type,
106 LP_JIT_CTX_F_BLEND_COLOR);
107 LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, viewports,
108 gallivm->target, context_type,
109 LP_JIT_CTX_VIEWPORTS);
110 LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, sample_mask,
111 gallivm->target, context_type,
112 LP_JIT_CTX_SAMPLE_MASK);
113 LP_CHECK_STRUCT_SIZE(struct lp_jit_context,
114 gallivm->target, context_type);
115
116 lp->jit_context_type = context_type;
117 lp->jit_context_ptr_type = LLVMPointerType(context_type, 0);
118 lp->jit_resources_type = lp_build_jit_resources_type(gallivm);
119 lp->jit_resources_ptr_type = LLVMPointerType(lp->jit_resources_type, 0);
120 }
121
122 /* struct lp_jit_thread_data */
123 {
124 LLVMTypeRef elem_types[LP_JIT_THREAD_DATA_COUNT];
125 LLVMTypeRef thread_data_type;
126
127 elem_types[LP_JIT_THREAD_DATA_CACHE] =
128 LLVMPointerType(lp_build_format_cache_type(gallivm), 0);
129 elem_types[LP_JIT_THREAD_DATA_VIS_COUNTER] = LLVMInt64TypeInContext(lc);
130 elem_types[LP_JIT_THREAD_DATA_PS_INVOCATIONS] = LLVMInt64TypeInContext(lc);
131 elem_types[LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX] =
132 elem_types[LP_JIT_THREAD_DATA_RASTER_STATE_VIEW_INDEX] =
133 LLVMInt32TypeInContext(lc);
134
135 thread_data_type = LLVMStructTypeInContext(lc, elem_types,
136 ARRAY_SIZE(elem_types), 0);
137
138 lp->jit_thread_data_type = thread_data_type;
139 lp->jit_thread_data_ptr_type = LLVMPointerType(thread_data_type, 0);
140 }
141
142 /*
143 * lp_linear_elem
144 *
145 * XXX: it can be instanced only once due to the use of opaque types, and
146 * the fact that screen->module is also a global.
147 */
148 {
149 LLVMTypeRef ret_type;
150 LLVMTypeRef arg_types[1];
151 LLVMTypeRef func_type;
152
153 ret_type = LLVMPointerType(LLVMVectorType(LLVMInt8TypeInContext(lc), 16), 0);
154
155 arg_types[0] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
156
157 /* lp_linear_func */
158 func_type = LLVMFunctionType(ret_type, arg_types, ARRAY_SIZE(arg_types), 0);
159
160 /*
161 * We actually define lp_linear_elem not as a structure but simply as a
162 * lp_linear_func pointer
163 */
164 lp->jit_linear_func_type = func_type;
165 linear_elem_type = LLVMPointerType(func_type, 0);
166 }
167
168 /* struct lp_jit_linear_context */
169 {
170 LLVMTypeRef linear_elem_ptr_type = LLVMPointerType(linear_elem_type, 0);
171 LLVMTypeRef elem_types[LP_JIT_LINEAR_CTX_COUNT];
172 LLVMTypeRef linear_context_type;
173
174
175 elem_types[LP_JIT_LINEAR_CTX_CONSTANTS] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
176 elem_types[LP_JIT_LINEAR_CTX_TEX] =
177 lp->jit_linear_textures_type =
178 LLVMArrayType(linear_elem_ptr_type, LP_MAX_LINEAR_TEXTURES);
179
180 elem_types[LP_JIT_LINEAR_CTX_INPUTS] =
181 lp->jit_linear_inputs_type =
182 LLVMArrayType(linear_elem_ptr_type, LP_MAX_LINEAR_INPUTS);
183 elem_types[LP_JIT_LINEAR_CTX_COLOR0] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
184 elem_types[LP_JIT_LINEAR_CTX_BLEND_COLOR] = LLVMInt32TypeInContext(lc);
185 elem_types[LP_JIT_LINEAR_CTX_ALPHA_REF] = LLVMInt8TypeInContext(lc);
186
187 linear_context_type = LLVMStructTypeInContext(lc, elem_types,
188 ARRAY_SIZE(elem_types), 0);
189
190 LP_CHECK_MEMBER_OFFSET(struct lp_jit_linear_context, constants,
191 gallivm->target, linear_context_type,
192 LP_JIT_LINEAR_CTX_CONSTANTS);
193 LP_CHECK_MEMBER_OFFSET(struct lp_jit_linear_context, tex,
194 gallivm->target, linear_context_type,
195 LP_JIT_LINEAR_CTX_TEX);
196 LP_CHECK_MEMBER_OFFSET(struct lp_jit_linear_context, inputs,
197 gallivm->target, linear_context_type,
198 LP_JIT_LINEAR_CTX_INPUTS);
199 LP_CHECK_MEMBER_OFFSET(struct lp_jit_linear_context, color0,
200 gallivm->target, linear_context_type,
201 LP_JIT_LINEAR_CTX_COLOR0);
202 LP_CHECK_MEMBER_OFFSET(struct lp_jit_linear_context, blend_color,
203 gallivm->target, linear_context_type,
204 LP_JIT_LINEAR_CTX_BLEND_COLOR);
205 LP_CHECK_MEMBER_OFFSET(struct lp_jit_linear_context, alpha_ref_value,
206 gallivm->target, linear_context_type,
207 LP_JIT_LINEAR_CTX_ALPHA_REF);
208 LP_CHECK_STRUCT_SIZE(struct lp_jit_linear_context,
209 gallivm->target, linear_context_type);
210
211 lp->jit_linear_context_type = linear_context_type;
212 lp->jit_linear_context_ptr_type = LLVMPointerType(linear_context_type, 0);
213 }
214
215 if (gallivm_debug & GALLIVM_DEBUG_IR) {
216 char *str = LLVMPrintModuleToString(gallivm->module);
217 fprintf(stderr, "%s", str);
218 LLVMDisposeMessage(str);
219 }
220 }
221
222
223 void
lp_jit_screen_cleanup(struct llvmpipe_screen * screen)224 lp_jit_screen_cleanup(struct llvmpipe_screen *screen)
225 {
226 /* nothing */
227 }
228
229
230 bool
lp_jit_screen_init(struct llvmpipe_screen * screen)231 lp_jit_screen_init(struct llvmpipe_screen *screen)
232 {
233 return lp_build_init();
234 }
235
236
237 void
lp_jit_init_types(struct lp_fragment_shader_variant * lp)238 lp_jit_init_types(struct lp_fragment_shader_variant *lp)
239 {
240 if (!lp->jit_context_ptr_type)
241 lp_jit_create_types(lp);
242 }
243
244 static void
lp_jit_create_cs_types(struct lp_compute_shader_variant * lp)245 lp_jit_create_cs_types(struct lp_compute_shader_variant *lp)
246 {
247 struct gallivm_state *gallivm = lp->gallivm;
248 LLVMContextRef lc = gallivm->context;
249
250 /* struct lp_jit_cs_thread_data */
251 {
252 LLVMTypeRef elem_types[LP_JIT_CS_THREAD_DATA_COUNT];
253 LLVMTypeRef thread_data_type;
254
255 elem_types[LP_JIT_CS_THREAD_DATA_CACHE] =
256 LLVMPointerType(lp_build_format_cache_type(gallivm), 0);
257
258 elem_types[LP_JIT_CS_THREAD_DATA_SHARED] = LLVMPointerType(LLVMInt32TypeInContext(lc), 0);
259
260 elem_types[LP_JIT_CS_THREAD_DATA_PAYLOAD] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
261 thread_data_type = LLVMStructTypeInContext(lc, elem_types,
262 ARRAY_SIZE(elem_types), 0);
263
264 lp->jit_cs_thread_data_type = thread_data_type;
265 lp->jit_cs_thread_data_ptr_type = LLVMPointerType(thread_data_type, 0);
266 }
267
268 /* struct lp_jit_cs_context */
269 {
270 LLVMTypeRef elem_types[LP_JIT_CS_CTX_COUNT];
271 LLVMTypeRef cs_context_type;
272
273 elem_types[LP_JIT_CS_CTX_KERNEL_ARGS] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
274 elem_types[LP_JIT_CS_CTX_SHARED_SIZE] = LLVMInt32TypeInContext(lc);
275
276 cs_context_type = LLVMStructTypeInContext(lc, elem_types,
277 ARRAY_SIZE(elem_types), 0);
278
279 LP_CHECK_MEMBER_OFFSET(struct lp_jit_cs_context, kernel_args,
280 gallivm->target, cs_context_type,
281 LP_JIT_CS_CTX_KERNEL_ARGS);
282 LP_CHECK_MEMBER_OFFSET(struct lp_jit_cs_context, shared_size,
283 gallivm->target, cs_context_type,
284 LP_JIT_CS_CTX_SHARED_SIZE);
285 LP_CHECK_STRUCT_SIZE(struct lp_jit_cs_context,
286 gallivm->target, cs_context_type);
287
288 lp->jit_cs_context_type = cs_context_type;
289 lp->jit_cs_context_ptr_type = LLVMPointerType(cs_context_type, 0);
290 lp->jit_resources_type = lp_build_jit_resources_type(gallivm);
291 lp->jit_resources_ptr_type = LLVMPointerType(lp->jit_resources_type, 0);
292 }
293
294 if (gallivm_debug & GALLIVM_DEBUG_IR) {
295 char *str = LLVMPrintModuleToString(gallivm->module);
296 fprintf(stderr, "%s", str);
297 LLVMDisposeMessage(str);
298 }
299 }
300
301 void
lp_jit_init_cs_types(struct lp_compute_shader_variant * lp)302 lp_jit_init_cs_types(struct lp_compute_shader_variant *lp)
303 {
304 if (!lp->jit_cs_context_ptr_type)
305 lp_jit_create_cs_types(lp);
306 }
307
308 void
lp_jit_buffer_from_pipe(struct lp_jit_buffer * jit,const struct pipe_shader_buffer * buffer)309 lp_jit_buffer_from_pipe(struct lp_jit_buffer *jit, const struct pipe_shader_buffer *buffer)
310 {
311 const uint8_t *current_data = NULL;
312
313 /* resource buffer */
314 if (buffer->buffer)
315 current_data = (uint8_t *)llvmpipe_resource_data(buffer->buffer);
316
317 if (current_data) {
318 current_data += buffer->buffer_offset;
319 jit->u = (const uint32_t *)current_data;
320 jit->num_elements = buffer->buffer_size;
321 } else {
322 jit->u = NULL;
323 jit->num_elements = 0;
324 }
325 }
326
327 void
lp_jit_buffer_from_bda(struct lp_jit_buffer * jit,void * mem,size_t size)328 lp_jit_buffer_from_bda(struct lp_jit_buffer *jit, void *mem, size_t size)
329 {
330 const uint8_t *current_data = mem;
331
332 if (current_data) {
333 jit->u = (const uint32_t *)current_data;
334 jit->num_elements = size;
335 } else {
336 jit->u = NULL;
337 jit->num_elements = 0;
338 }
339 }
340
341 void
lp_jit_buffer_from_pipe_const(struct lp_jit_buffer * jit,const struct pipe_constant_buffer * buffer,struct pipe_screen * screen)342 lp_jit_buffer_from_pipe_const(struct lp_jit_buffer *jit, const struct pipe_constant_buffer *buffer, struct pipe_screen *screen)
343 {
344 uint64_t current_size = buffer->buffer_size;
345
346 const uint8_t *current_data = NULL;
347 if (buffer->buffer) {
348 /* resource buffer */
349 current_data = (uint8_t *)llvmpipe_resource_data(buffer->buffer);
350 } else if (buffer->user_buffer) {
351 /* user-space buffer */
352 current_data = (uint8_t *)buffer->user_buffer;
353 }
354
355 if (current_data && current_size >= sizeof(float)) {
356 current_data += buffer->buffer_offset;
357 jit->f = (const float *)current_data;
358 jit->num_elements = DIV_ROUND_UP(current_size, lp_get_constant_buffer_stride(screen));
359 } else {
360 static const float fake_const_buf[4];
361 jit->f = fake_const_buf;
362 jit->num_elements = 0;
363 }
364 }
365
366 void
lp_jit_texture_from_pipe(struct lp_jit_texture * jit,const struct pipe_sampler_view * view)367 lp_jit_texture_from_pipe(struct lp_jit_texture *jit, const struct pipe_sampler_view *view)
368 {
369 struct pipe_resource *res = view->texture;
370 struct llvmpipe_resource *lp_tex = llvmpipe_resource(res);
371
372 if (!lp_tex->dt) {
373 /* regular texture - setup array of mipmap level offsets */
374 unsigned first_level = 0;
375 unsigned last_level = 0;
376
377 if (llvmpipe_resource_is_texture(res)) {
378 first_level = view->u.tex.first_level;
379 last_level = view->u.tex.last_level;
380 assert(first_level <= last_level);
381 assert(last_level <= res->last_level);
382 jit->base = lp_tex->tex_data;
383 } else {
384 jit->base = lp_tex->data;
385 }
386
387 if (LP_PERF & PERF_TEX_MEM) {
388 /* use dummy tile memory */
389 jit->base = lp_dummy_tile;
390 jit->width = TILE_SIZE/8;
391 jit->height = TILE_SIZE/8;
392 jit->depth = 1;
393 jit->first_level = 0;
394 jit->last_level = 0;
395 jit->mip_offsets[0] = 0;
396 jit->mip_offsets[LP_JIT_TEXTURE_SAMPLE_STRIDE] = 0;
397 jit->row_stride[0] = 0;
398 jit->img_stride[0] = 0;
399 } else {
400 jit->width = res->width0;
401 jit->height = res->height0;
402 jit->depth = res->depth0;
403 jit->first_level = first_level;
404 jit->last_level = last_level;
405 jit->mip_offsets[0] = 0;
406
407 if (llvmpipe_resource_is_texture(res)) {
408 if (res->nr_samples > 1) {
409 jit->last_level = res->nr_samples;
410 jit->mip_offsets[LP_JIT_TEXTURE_SAMPLE_STRIDE] = lp_tex->sample_stride;
411 jit->row_stride[0] = lp_tex->row_stride[0];
412 jit->img_stride[0] = lp_tex->img_stride[0];
413 } else {
414 for (unsigned j = first_level; j <= last_level; j++) {
415 jit->mip_offsets[j] = lp_tex->mip_offsets[j];
416 jit->row_stride[j] = lp_tex->row_stride[j];
417 jit->img_stride[j] = lp_tex->img_stride[j];
418 }
419 }
420
421 bool is_2d_view_of_3d = res->target == PIPE_TEXTURE_3D && view->target == PIPE_TEXTURE_2D;
422
423 if (res->target == PIPE_TEXTURE_1D_ARRAY ||
424 res->target == PIPE_TEXTURE_2D_ARRAY ||
425 res->target == PIPE_TEXTURE_CUBE ||
426 res->target == PIPE_TEXTURE_CUBE_ARRAY ||
427 is_2d_view_of_3d) {
428 /*
429 * For array textures, we don't have first_layer, instead
430 * adjust last_layer (stored as depth) plus the mip level
431 * offsets (as we have mip-first layout can't just adjust
432 * base ptr). XXX For mip levels, could do something
433 * similar.
434 */
435 jit->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1;
436 for (unsigned j = first_level; j <= last_level; j++) {
437 if (is_2d_view_of_3d && (res->flags & PIPE_RESOURCE_FLAG_SPARSE)) {
438 jit->mip_offsets[j] = llvmpipe_get_texel_offset(
439 view->texture, j, 0, 0, view->u.tex.first_layer);
440 } else {
441 jit->mip_offsets[j] += view->u.tex.first_layer *
442 lp_tex->img_stride[j];
443 }
444 }
445 if (view->target == PIPE_TEXTURE_CUBE ||
446 view->target == PIPE_TEXTURE_CUBE_ARRAY) {
447 assert(jit->depth % 6 == 0);
448 }
449 assert(view->u.tex.first_layer <= view->u.tex.last_layer);
450 if (res->target == PIPE_TEXTURE_3D)
451 assert(view->u.tex.last_layer < res->depth0);
452 else
453 assert(view->u.tex.last_layer < res->array_size);
454 }
455
456 if (res->flags & PIPE_RESOURCE_FLAG_SPARSE)
457 jit->residency = lp_tex->residency;
458 } else {
459 /*
460 * For tex2d_from_buf, adjust width and height with application
461 * values. If is_tex2d_from_buf is false (1D images),
462 * adjust using size value (stored as width).
463 */
464 unsigned view_blocksize = util_format_get_blocksize(view->format);
465
466 jit->mip_offsets[0] = 0;
467 jit->img_stride[0] = 0;
468
469 /* If it's not a 2D texture view of a buffer, adjust using size. */
470 if (!view->is_tex2d_from_buf) {
471 /* everything specified in number of elements here. */
472 jit->width = view->u.buf.size / view_blocksize;
473 jit->row_stride[0] = 0;
474
475 /* Adjust base pointer with offset. */
476 jit->base = (uint8_t *)jit->base + view->u.buf.offset;
477
478 /* XXX Unsure if we need to sanitize parameters? */
479 assert(view->u.buf.offset + view->u.buf.size <= res->width0);
480 } else {
481 jit->width = view->u.tex2d_from_buf.width;
482 jit->height = view->u.tex2d_from_buf.height;
483 jit->row_stride[0] = view->u.tex2d_from_buf.row_stride * view_blocksize;
484
485 jit->base = (uint8_t *)jit->base +
486 view->u.tex2d_from_buf.offset * view_blocksize;
487 }
488 }
489 }
490 } else {
491 /* display target texture/surface */
492 jit->base = llvmpipe_resource_map(res, 0, 0, LP_TEX_USAGE_READ);
493 jit->row_stride[0] = lp_tex->row_stride[0];
494 jit->img_stride[0] = lp_tex->img_stride[0];
495 jit->mip_offsets[0] = 0;
496 jit->width = res->width0;
497 jit->height = res->height0;
498 jit->depth = res->depth0;
499 jit->first_level = jit->last_level = 0;
500 if (res->nr_samples > 1)
501 jit->last_level = res->nr_samples;
502 assert(jit->base);
503 }
504 }
505
506 void
lp_jit_texture_buffer_from_bda(struct lp_jit_texture * jit,void * mem,size_t size,enum pipe_format format)507 lp_jit_texture_buffer_from_bda(struct lp_jit_texture *jit, void *mem, size_t size, enum pipe_format format)
508 {
509 jit->base = mem;
510
511 if (LP_PERF & PERF_TEX_MEM) {
512 /* use dummy tile memory */
513 jit->base = lp_dummy_tile;
514 jit->width = TILE_SIZE/8;
515 jit->height = TILE_SIZE/8;
516 jit->depth = 1;
517 jit->first_level = 0;
518 jit->last_level = 0;
519 jit->mip_offsets[0] = 0;
520 jit->row_stride[0] = 0;
521 jit->img_stride[0] = 0;
522 } else {
523 jit->height = 1;
524 jit->depth = 1;
525 jit->first_level = 0;
526 jit->last_level = 0;
527
528 /*
529 * For buffers, we don't have "offset", instead adjust
530 * the size (stored as width) plus the base pointer.
531 */
532 const unsigned view_blocksize = util_format_get_blocksize(format);
533 /* probably don't really need to fill that out */
534 jit->mip_offsets[0] = 0;
535 jit->row_stride[0] = 0;
536 jit->img_stride[0] = 0;
537
538 /* everything specified in number of elements here. */
539 jit->width = size / view_blocksize;
540 }
541 }
542
543 void
lp_jit_sampler_from_pipe(struct lp_jit_sampler * jit,const struct pipe_sampler_state * sampler)544 lp_jit_sampler_from_pipe(struct lp_jit_sampler *jit, const struct pipe_sampler_state *sampler)
545 {
546 jit->min_lod = sampler->min_lod;
547 jit->max_lod = sampler->max_lod;
548 jit->lod_bias = sampler->lod_bias;
549 jit->max_aniso = sampler->max_anisotropy;
550 COPY_4V(jit->border_color, sampler->border_color.f);
551 }
552
553 void
lp_jit_image_from_pipe(struct lp_jit_image * jit,const struct pipe_image_view * view)554 lp_jit_image_from_pipe(struct lp_jit_image *jit, const struct pipe_image_view *view)
555 {
556 struct pipe_resource *res = view->resource;
557 struct llvmpipe_resource *lp_res = llvmpipe_resource(res);
558
559 if (!lp_res->dt) {
560 /* regular texture - setup array of mipmap level offsets */
561 if (llvmpipe_resource_is_texture(res)) {
562 jit->base = lp_res->tex_data;
563 } else {
564 jit->base = lp_res->data;
565 }
566
567 jit->width = res->width0;
568 jit->height = res->height0;
569 jit->depth = res->depth0;
570 jit->num_samples = res->nr_samples;
571
572 if (llvmpipe_resource_is_texture(res)) {
573 uint32_t mip_offset = lp_res->mip_offsets[view->u.tex.level];
574
575 jit->width = u_minify(jit->width, view->u.tex.level);
576 jit->height = u_minify(jit->height, view->u.tex.level);
577
578 if (res->target == PIPE_TEXTURE_1D_ARRAY ||
579 res->target == PIPE_TEXTURE_2D_ARRAY ||
580 res->target == PIPE_TEXTURE_3D ||
581 res->target == PIPE_TEXTURE_CUBE ||
582 res->target == PIPE_TEXTURE_CUBE_ARRAY) {
583 /*
584 * For array textures, we don't have first_layer, instead
585 * adjust last_layer (stored as depth) plus the mip level offsets
586 * (as we have mip-first layout can't just adjust base ptr).
587 * XXX For mip levels, could do something similar.
588 */
589 jit->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1;
590
591 if (res->target == PIPE_TEXTURE_3D && view->u.tex.first_layer != 0 &&
592 (res->flags & PIPE_RESOURCE_FLAG_SPARSE)) {
593 mip_offset = llvmpipe_get_texel_offset(
594 res, view->u.tex.level, 0, 0, view->u.tex.first_layer);
595 } else {
596 mip_offset += view->u.tex.first_layer * lp_res->img_stride[view->u.tex.level];
597 }
598 } else
599 jit->depth = u_minify(jit->depth, view->u.tex.level);
600
601 jit->row_stride = lp_res->row_stride[view->u.tex.level];
602 jit->img_stride = lp_res->img_stride[view->u.tex.level];
603 jit->sample_stride = lp_res->sample_stride;
604 jit->base = (uint8_t *)jit->base + mip_offset;
605 } else {
606 unsigned image_blocksize = util_format_get_blocksize(view->format);
607
608 jit->img_stride = 0;
609
610 /* If it's not a 2D image view of a buffer, adjust using size. */
611 if (!(view->access & PIPE_IMAGE_ACCESS_TEX2D_FROM_BUFFER)) {
612 /* everything specified in number of elements here. */
613 jit->width = view->u.buf.size / image_blocksize;
614 jit->row_stride = 0;
615
616 /* Adjust base pointer with offset. */
617 jit->base = (uint8_t *)jit->base + view->u.buf.offset;
618
619 /* XXX Unsure if we need to sanitize parameters? */
620 assert(view->u.buf.offset + view->u.buf.size <= res->width0);
621 } else {
622 jit->width = view->u.tex2d_from_buf.width;
623 jit->height = view->u.tex2d_from_buf.height;
624 jit->row_stride = view->u.tex2d_from_buf.row_stride * image_blocksize;
625
626 jit->base = (uint8_t *)jit->base +
627 view->u.tex2d_from_buf.offset * image_blocksize;
628 }
629 }
630
631 if (res->flags & PIPE_RESOURCE_FLAG_SPARSE) {
632 jit->residency = lp_res->residency;
633 jit->base_offset = (uint32_t)((uintptr_t)jit->base - (uintptr_t)lp_res->tex_data);
634 }
635 }
636 }
637
638 void
lp_jit_image_buffer_from_bda(struct lp_jit_image * jit,void * mem,size_t size,enum pipe_format format)639 lp_jit_image_buffer_from_bda(struct lp_jit_image *jit, void *mem, size_t size, enum pipe_format format)
640 {
641 jit->base = mem;
642
643 jit->height = 1;
644 jit->depth = 1;
645 jit->num_samples = 1;
646
647 unsigned view_blocksize = util_format_get_blocksize(format);
648 jit->width = size / view_blocksize;
649 }
650