~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/gallium/drivers/llvmpipe/lp_texture_handle.c

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2023 Valve Corporation
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice (including the next
 
12
 * paragraph) shall be included in all copies or substantial portions of the
 
13
 * Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
21
 * IN THE SOFTWARE.
 
22
 */
 
23
 
 
24
#include "lp_context.h"
 
25
#include "lp_texture_handle.h"
 
26
#include "lp_screen.h"
 
27
 
 
28
#include "gallivm/lp_bld_const.h"
 
29
#include "gallivm/lp_bld_debug.h"
 
30
#include "gallivm/lp_bld_nir.h"
 
31
 
 
32
#include "nir.h"
 
33
#include "nir_builder.h"
 
34
 
 
35
#include "pipe/p_context.h"
 
36
#include "pipe/p_screen.h"
 
37
#include "util/mesa-sha1.h"
 
38
 
 
39
static const char *image_function_base_hash = "8ca89d7a4ab5830be6a1ba1140844081235b01164a8fce8316ca6a2f81f1a899";
 
40
static const char *sample_function_base_hash = "0789b032c4a1ddba086e07496fe2a992b1ee08f78c0884a2923564b1ed52b9cc";
 
41
static const char *size_function_base_hash = "6d249ab9c1106c68b87ec9fdb5ade28368171d27f221c687f32ae1544231d2fe";
 
42
 
 
43
static void
 
44
llvmpipe_register_texture(struct llvmpipe_context *ctx, struct lp_static_texture_state *state, bool sampled);
 
45
 
 
46
static void
 
47
llvmpipe_register_sampler(struct llvmpipe_context *ctx, struct lp_static_sampler_state *state);
 
48
 
 
49
static uint64_t
 
50
llvmpipe_create_texture_handle(struct pipe_context *pctx, struct pipe_sampler_view *view, const struct pipe_sampler_state *sampler)
 
51
{
 
52
   struct llvmpipe_context *ctx = llvmpipe_context(pctx);
 
53
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
54
 
 
55
   struct lp_texture_handle *handle = calloc(1, sizeof(struct lp_texture_handle));
 
56
 
 
57
   if (view) {
 
58
      struct lp_static_texture_state state;
 
59
      lp_sampler_static_texture_state(&state, view);
 
60
 
 
61
      /* Trade a bit of performance for potentially less sampler/texture combinations. */
 
62
      state.pot_width = false;
 
63
      state.pot_height = false;
 
64
      state.pot_depth = false;
 
65
 
 
66
      llvmpipe_register_texture(ctx, &state, true);
 
67
 
 
68
      bool found = false;
 
69
      for (uint32_t i = 0; i < matrix->texture_count; i++) {
 
70
         if (!memcmp(&matrix->textures[i]->state, &state, sizeof(struct lp_static_texture_state))) {
 
71
            handle->functions = matrix->textures[i];
 
72
            found = true;
 
73
            break;
 
74
         }
 
75
      }
 
76
      assert(found);
 
77
   }
 
78
 
 
79
   if (sampler) {
 
80
      struct lp_static_sampler_state state;
 
81
      lp_sampler_static_sampler_state(&state, sampler);
 
82
 
 
83
      llvmpipe_register_sampler(ctx, &state);
 
84
 
 
85
      bool found = false;
 
86
      for (uint32_t i = 0; i < matrix->sampler_count; i++) {
 
87
         if (!memcmp(matrix->samplers + i, &state, sizeof(struct lp_static_sampler_state))) {
 
88
            handle->sampler_index = i;
 
89
            found = true;
 
90
            break;
 
91
         }
 
92
      }
 
93
      assert(found);
 
94
   }
 
95
 
 
96
   return (uint64_t)(uintptr_t)handle;
 
97
}
 
98
 
 
99
static void
 
100
llvmpipe_delete_texture_handle(struct pipe_context *pctx, uint64_t _handle)
 
101
{
 
102
   if (!_handle)
 
103
      return;
 
104
 
 
105
   struct lp_texture_handle *handle = (void *)(uintptr_t)_handle;
 
106
 
 
107
   struct lp_texture_functions *functions = handle->functions;
 
108
   if (functions) {
 
109
      assert(functions->ref_count);
 
110
      functions->ref_count--;
 
111
   }
 
112
 
 
113
   free(handle);
 
114
}
 
115
 
 
116
static uint64_t
 
117
llvmpipe_create_image_handle(struct pipe_context *pctx, const struct pipe_image_view *view)
 
118
{
 
119
   struct llvmpipe_context *ctx = llvmpipe_context(pctx);
 
120
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
121
 
 
122
   struct lp_texture_handle *handle = calloc(1, sizeof(struct lp_texture_handle));
 
123
 
 
124
   struct lp_static_texture_state state;
 
125
   lp_sampler_static_texture_state_image(&state, view);
 
126
 
 
127
   /* Trade a bit of performance for potentially less sampler/texture combinations. */
 
128
   state.pot_width = false;
 
129
   state.pot_height = false;
 
130
   state.pot_depth = false;
 
131
 
 
132
   if (view->u.tex.first_layer == view->u.tex.last_layer) {
 
133
      if (state.target == PIPE_TEXTURE_1D_ARRAY)
 
134
         state.target = PIPE_TEXTURE_1D;
 
135
      else if (state.target == PIPE_TEXTURE_2D_ARRAY || state.target == PIPE_TEXTURE_3D)
 
136
         state.target = PIPE_TEXTURE_2D;
 
137
      else if (state.target == PIPE_TEXTURE_CUBE_ARRAY)
 
138
         state.target = PIPE_TEXTURE_CUBE;
 
139
   }
 
140
 
 
141
   llvmpipe_register_texture(ctx, &state, false);
 
142
 
 
143
   bool found = false;
 
144
   for (uint32_t i = 0; i < matrix->texture_count; i++) {
 
145
      if (!memcmp(&matrix->textures[i]->state, &state, sizeof(struct lp_static_texture_state))) {
 
146
         handle->functions = matrix->textures[i];
 
147
         found = true;
 
148
         break;
 
149
      }
 
150
   }
 
151
   assert(found);
 
152
 
 
153
   return (uint64_t)(uintptr_t)handle;
 
154
}
 
155
 
 
156
static void
 
157
llvmpipe_delete_image_handle(struct pipe_context *pctx, uint64_t handle)
 
158
{
 
159
   free((void *)(uintptr_t)handle);
 
160
}
 
161
 
 
162
void
 
163
llvmpipe_init_sampler_matrix(struct llvmpipe_context *ctx)
 
164
{
 
165
   ctx->pipe.create_texture_handle = llvmpipe_create_texture_handle;
 
166
   ctx->pipe.delete_texture_handle = llvmpipe_delete_texture_handle;
 
167
   ctx->pipe.create_image_handle = llvmpipe_create_image_handle;
 
168
   ctx->pipe.delete_image_handle = llvmpipe_delete_image_handle;
 
169
 
 
170
   util_dynarray_init(&ctx->sampler_matrix.gallivms, NULL);
 
171
}
 
172
 
 
173
void
 
174
llvmpipe_sampler_matrix_destroy(struct llvmpipe_context *ctx)
 
175
{
 
176
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
177
 
 
178
   free(matrix->samplers);
 
179
 
 
180
   for (uint32_t texture_index = 0; texture_index < matrix->texture_count; texture_index++) {
 
181
      struct lp_texture_functions *texture = matrix->textures[texture_index];
 
182
 
 
183
      uint32_t sampler_count = texture->sampler_count;
 
184
      if (texture->state.format == PIPE_FORMAT_NONE)
 
185
         sampler_count = MIN2(sampler_count, 1);
 
186
 
 
187
      for (uint32_t sampler_index = 0; sampler_index < sampler_count; sampler_index++)
 
188
         free(texture->sample_functions[sampler_index]);
 
189
 
 
190
      free(texture->sample_functions);
 
191
      free(texture->fetch_functions);
 
192
      free(texture->image_functions);
 
193
      free(texture);
 
194
   }
 
195
   free(matrix->textures);
 
196
 
 
197
   util_dynarray_foreach (&ctx->sampler_matrix.gallivms, struct gallivm_state *, gallivm)
 
198
      gallivm_destroy(*gallivm);
 
199
 
 
200
   util_dynarray_fini(&ctx->sampler_matrix.gallivms);
 
201
}
 
202
 
 
203
static void *
 
204
compile_function(struct llvmpipe_context *ctx, struct gallivm_state *gallivm, LLVMValueRef function,
 
205
                 uint8_t cache_key[SHA1_DIGEST_LENGTH])
 
206
{
 
207
   gallivm_verify_function(gallivm, function);
 
208
   gallivm_compile_module(gallivm);
 
209
 
 
210
   void *function_ptr = func_to_pointer(gallivm_jit_function(gallivm, function));
 
211
 
 
212
   if (!gallivm->cache->data_size)
 
213
      lp_disk_cache_insert_shader(llvmpipe_screen(ctx->pipe.screen), gallivm->cache, cache_key);
 
214
 
 
215
   gallivm_free_ir(gallivm);
 
216
 
 
217
   util_dynarray_append(&ctx->sampler_matrix.gallivms, struct gallivm_state *, gallivm);
 
218
 
 
219
   return function_ptr;
 
220
}
 
221
 
 
222
static void *
 
223
compile_image_function(struct llvmpipe_context *ctx, struct lp_static_texture_state *texture, uint32_t op)
 
224
{
 
225
   const struct util_format_description *desc = util_format_description(texture->format);
 
226
   if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS && !lp_storage_render_image_format_supported(texture->format))
 
227
      return NULL;
 
228
   
 
229
   bool ms = op >= LP_TOTAL_IMAGE_OP_COUNT / 2;
 
230
   if (ms)
 
231
      op -= LP_TOTAL_IMAGE_OP_COUNT / 2;
 
232
 
 
233
   struct lp_img_params params = { 0 };
 
234
 
 
235
   params.img_op = op;
 
236
   if (op >= LP_IMG_OP_COUNT - 1) {
 
237
      params.img_op = LP_IMG_ATOMIC;
 
238
      params.op = op - (LP_IMG_OP_COUNT - 1);
 
239
   } else if (op != LP_IMG_LOAD && op != LP_IMG_STORE) {
 
240
      params.img_op = LP_IMG_ATOMIC_CAS;
 
241
   }
 
242
 
 
243
   /* Loads need to support a wider range of formats for input attachments. */
 
244
   if (params.img_op != LP_IMG_LOAD)
 
245
      if (texture->format != PIPE_FORMAT_NONE && !lp_storage_image_format_supported(texture->format))
 
246
         return NULL;
 
247
 
 
248
   uint8_t cache_key[SHA1_DIGEST_LENGTH];
 
249
   struct mesa_sha1 hash_ctx;
 
250
   _mesa_sha1_init(&hash_ctx);
 
251
   _mesa_sha1_update(&hash_ctx, image_function_base_hash, strlen(image_function_base_hash));
 
252
   _mesa_sha1_update(&hash_ctx, texture, sizeof(*texture));
 
253
   _mesa_sha1_update(&hash_ctx, &op, sizeof(op));
 
254
   _mesa_sha1_final(&hash_ctx, cache_key);
 
255
 
 
256
   struct lp_cached_code cached = { 0 };
 
257
   lp_disk_cache_find_shader(llvmpipe_screen(ctx->pipe.screen), &cached, cache_key);
 
258
 
 
259
   struct gallivm_state *gallivm = gallivm_create("sample_function", ctx->context, &cached);
 
260
 
 
261
   struct lp_image_static_state state = {
 
262
      .image_state = *texture,
 
263
   };
 
264
   struct lp_build_image_soa *image_soa = lp_bld_llvm_image_soa_create(&state, 1);
 
265
 
 
266
   struct lp_type type;
 
267
   memset(&type, 0, sizeof type);
 
268
   type.floating = true;      /* floating point values */
 
269
   type.sign = true;          /* values are signed */
 
270
   type.norm = false;         /* values are not limited to [0,1] or [-1,1] */
 
271
   type.width = 32;           /* 32-bit float */
 
272
   type.length = MIN2(lp_native_vector_width / 32, 16); /* n*4 elements per vector */
 
273
 
 
274
   struct lp_compute_shader_variant cs = { .gallivm = gallivm };
 
275
   lp_jit_init_cs_types(&cs);
 
276
 
 
277
   params.type = type;
 
278
   params.target = texture->target;
 
279
   params.resources_type = cs.jit_resources_type;
 
280
   params.format = texture->format;
 
281
 
 
282
   LLVMTypeRef function_type = lp_build_image_function_type(gallivm, &params, ms);
 
283
   if (!function_type) {
 
284
      free(image_soa);
 
285
      gallivm_destroy(gallivm);
 
286
      return NULL;
 
287
   }
 
288
 
 
289
   LLVMValueRef function = LLVMAddFunction(gallivm->module, "image", function_type);
 
290
 
 
291
   uint32_t arg_index = 0;
 
292
 
 
293
   gallivm->texture_descriptor = LLVMGetParam(function, arg_index++);
 
294
 
 
295
   if (params.img_op != LP_IMG_LOAD)
 
296
      params.exec_mask = LLVMGetParam(function, arg_index++);
 
297
 
 
298
   LLVMValueRef coords[3];
 
299
   params.coords = coords;
 
300
   for (uint32_t i = 0; i < 3; i++)
 
301
      coords[i] = LLVMGetParam(function, arg_index++);
 
302
 
 
303
   if (ms)
 
304
      params.ms_index = LLVMGetParam(function, arg_index++);
 
305
 
 
306
   if (params.img_op != LP_IMG_LOAD)
 
307
      for (uint32_t i = 0; i < 4; i++)
 
308
         params.indata[i] = LLVMGetParam(function, arg_index++);
 
309
 
 
310
   if (params.img_op == LP_IMG_ATOMIC_CAS)
 
311
      for (uint32_t i = 0; i < 4; i++)
 
312
         params.indata2[i] = LLVMGetParam(function, arg_index++);
 
313
 
 
314
   LLVMBuilderRef old_builder = gallivm->builder;
 
315
   LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(gallivm->context, function, "entry");
 
316
   gallivm->builder = LLVMCreateBuilderInContext(gallivm->context);
 
317
   LLVMPositionBuilderAtEnd(gallivm->builder, block);
 
318
 
 
319
   LLVMValueRef outdata[4] = { 0 };
 
320
   lp_build_img_op_soa(texture, lp_build_image_soa_dynamic_state(image_soa), gallivm, &params, outdata);
 
321
 
 
322
   for (uint32_t i = 1; i < 4; i++)
 
323
      if (!outdata[i])
 
324
         outdata[i] = outdata[0];
 
325
 
 
326
   if (params.img_op != LP_IMG_STORE)
 
327
      LLVMBuildAggregateRet(gallivm->builder, outdata, 4);
 
328
   else
 
329
      LLVMBuildRetVoid(gallivm->builder);
 
330
 
 
331
   LLVMDisposeBuilder(gallivm->builder);
 
332
   gallivm->builder = old_builder;
 
333
 
 
334
   free(image_soa);
 
335
 
 
336
   return compile_function(ctx, gallivm, function, cache_key);
 
337
}
 
338
 
 
339
static void *
 
340
compile_sample_function(struct llvmpipe_context *ctx, struct lp_static_texture_state *texture,
 
341
                        struct lp_static_sampler_state *sampler, uint32_t sample_key)
 
342
{
 
343
   enum lp_sampler_lod_control lod_control = (sample_key & LP_SAMPLER_LOD_CONTROL_MASK) >> LP_SAMPLER_LOD_CONTROL_SHIFT;
 
344
 
 
345
   if (texture->format != PIPE_FORMAT_NONE) {
 
346
      enum lp_sampler_op_type op_type = (sample_key & LP_SAMPLER_OP_TYPE_MASK) >> LP_SAMPLER_OP_TYPE_SHIFT;
 
347
      if (op_type != LP_SAMPLER_OP_LODQ)
 
348
         if ((sampler->compare_mode == PIPE_TEX_COMPARE_NONE) == !!(sample_key & LP_SAMPLER_SHADOW))
 
349
            return NULL;
 
350
 
 
351
      /* Skip integer formats which would cause a type mismatch in the compare function. */
 
352
      const struct util_format_description *desc = util_format_description(texture->format);
 
353
      struct lp_type texel_type = {
 
354
         .floating = true,
 
355
         .width = 32,
 
356
         .length = 1,
 
357
      };
 
358
      texel_type = lp_build_texel_type(texel_type, desc);
 
359
      if ((sample_key & LP_SAMPLER_SHADOW) && !texel_type.floating)
 
360
         return NULL;
 
361
 
 
362
      if (texture_dims(texture->target) != 2 && op_type == LP_SAMPLER_OP_GATHER)
 
363
         return NULL;
 
364
 
 
365
      if (op_type != LP_SAMPLER_OP_FETCH) {
 
366
         if (!sampler->normalized_coords) {
 
367
            if (texture->target != PIPE_TEXTURE_1D && texture->target != PIPE_TEXTURE_2D)
 
368
               return NULL;
 
369
 
 
370
            if (!texture->level_zero_only)
 
371
               return NULL;
 
372
         }
 
373
      }
 
374
 
 
375
      if (util_format_is_pure_integer(texture->format) &&
 
376
          (sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR ||
 
377
           sampler->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR ||
 
378
           sampler->mag_img_filter == PIPE_TEX_FILTER_LINEAR))
 
379
         return NULL;
 
380
 
 
381
      if (sampler->aniso) {
 
382
         if (texture_dims(texture->target) != 2)
 
383
            return NULL;
 
384
 
 
385
         if (util_format_is_pure_integer(texture->format))
 
386
            return NULL;
 
387
      }
 
388
 
 
389
      uint32_t bind = op_type == LP_SAMPLER_OP_FETCH ? PIPE_BIND_CONSTANT_BUFFER : PIPE_BIND_SAMPLER_VIEW;
 
390
      if (!ctx->pipe.screen->is_format_supported(ctx->pipe.screen, texture->format, texture->target, 0, 0, bind))
 
391
         return NULL;
 
392
   }
 
393
 
 
394
   uint8_t cache_key[SHA1_DIGEST_LENGTH];
 
395
   struct mesa_sha1 hash_ctx;
 
396
   _mesa_sha1_init(&hash_ctx);
 
397
   _mesa_sha1_update(&hash_ctx, sample_function_base_hash, strlen(sample_function_base_hash));
 
398
   _mesa_sha1_update(&hash_ctx, texture, sizeof(*texture));
 
399
   _mesa_sha1_update(&hash_ctx, sampler, sizeof(*sampler));
 
400
   _mesa_sha1_update(&hash_ctx, &sample_key, sizeof(sample_key));
 
401
   _mesa_sha1_final(&hash_ctx, cache_key);
 
402
 
 
403
   struct lp_cached_code cached = { 0 };
 
404
   lp_disk_cache_find_shader(llvmpipe_screen(ctx->pipe.screen), &cached, cache_key);
 
405
 
 
406
   struct gallivm_state *gallivm = gallivm_create("sample_function", ctx->context, &cached);
 
407
 
 
408
   struct lp_sampler_static_state state = {
 
409
      .texture_state = *texture,
 
410
      .sampler_state = *sampler,
 
411
   };
 
412
   struct lp_build_sampler_soa *sampler_soa = lp_llvm_sampler_soa_create(&state, 1);
 
413
 
 
414
   struct lp_type type;
 
415
   memset(&type, 0, sizeof type);
 
416
   type.floating = true;      /* floating point values */
 
417
   type.sign = true;          /* values are signed */
 
418
   type.norm = false;         /* values are not limited to [0,1] or [-1,1] */
 
419
   type.width = 32;           /* 32-bit float */
 
420
   type.length = MIN2(lp_native_vector_width / 32, 16); /* n*4 elements per vector */
 
421
 
 
422
   struct lp_compute_shader_variant cs = { .gallivm = gallivm };
 
423
   lp_jit_init_cs_types(&cs);
 
424
 
 
425
   LLVMTypeRef function_type = lp_build_sample_function_type(gallivm, sample_key);
 
426
   LLVMValueRef function = LLVMAddFunction(gallivm->module, "sample", function_type);
 
427
 
 
428
   uint32_t arg_index = 0;
 
429
 
 
430
   gallivm->texture_descriptor = LLVMGetParam(function, arg_index++);
 
431
   gallivm->sampler_descriptor = LLVMGetParam(function, arg_index++);
 
432
 
 
433
   LLVMValueRef aniso_filter_table = LLVMGetParam(function, arg_index++);
 
434
 
 
435
   LLVMValueRef coords[5];
 
436
   for (unsigned i = 0; i < 4; i++)
 
437
      coords[i] = LLVMGetParam(function, arg_index++);
 
438
 
 
439
   if (sample_key & LP_SAMPLER_SHADOW)
 
440
      coords[4] = LLVMGetParam(function, arg_index++);
 
441
   else
 
442
      coords[4] = lp_build_undef(gallivm, type);
 
443
 
 
444
   LLVMValueRef ms_index = NULL;
 
445
   if (sample_key & LP_SAMPLER_FETCH_MS)
 
446
      ms_index = LLVMGetParam(function, arg_index++);
 
447
 
 
448
   LLVMValueRef offsets[3] = { 0 };
 
449
   if (sample_key & LP_SAMPLER_OFFSETS)
 
450
      for (unsigned i = 0; i < 3; i++)
 
451
         offsets[i] = LLVMGetParam(function, arg_index++);
 
452
 
 
453
   LLVMValueRef lod = NULL;
 
454
   if (lod_control == LP_SAMPLER_LOD_BIAS || lod_control == LP_SAMPLER_LOD_EXPLICIT)
 
455
      lod = LLVMGetParam(function, arg_index++);
 
456
 
 
457
   LLVMBuilderRef old_builder = gallivm->builder;
 
458
   LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(gallivm->context, function, "entry");
 
459
   gallivm->builder = LLVMCreateBuilderInContext(gallivm->context);
 
460
   LLVMPositionBuilderAtEnd(gallivm->builder, block);
 
461
 
 
462
   LLVMValueRef texel_out[4] = { 0 };
 
463
   lp_build_sample_soa_code(gallivm, texture, sampler, lp_build_sampler_soa_dynamic_state(sampler_soa),
 
464
                            type, sample_key, 0, 0, cs.jit_resources_type, NULL, cs.jit_cs_thread_data_type,
 
465
                            NULL, coords, offsets, NULL, lod, ms_index, aniso_filter_table, texel_out);
 
466
 
 
467
   LLVMBuildAggregateRet(gallivm->builder, texel_out, 4);
 
468
 
 
469
   LLVMDisposeBuilder(gallivm->builder);
 
470
   gallivm->builder = old_builder;
 
471
 
 
472
   free(sampler_soa);
 
473
 
 
474
   return compile_function(ctx, gallivm, function, cache_key);
 
475
}
 
476
 
 
477
static void *
 
478
compile_size_function(struct llvmpipe_context *ctx, struct lp_static_texture_state *texture, bool samples)
 
479
{
 
480
   uint8_t cache_key[SHA1_DIGEST_LENGTH];
 
481
   struct mesa_sha1 hash_ctx;
 
482
   _mesa_sha1_init(&hash_ctx);
 
483
   _mesa_sha1_update(&hash_ctx, size_function_base_hash, strlen(size_function_base_hash));
 
484
   _mesa_sha1_update(&hash_ctx, texture, sizeof(*texture));
 
485
   _mesa_sha1_update(&hash_ctx, &samples, sizeof(samples));
 
486
   _mesa_sha1_final(&hash_ctx, cache_key);
 
487
 
 
488
   struct lp_cached_code cached = { 0 };
 
489
   lp_disk_cache_find_shader(llvmpipe_screen(ctx->pipe.screen), &cached, cache_key);
 
490
 
 
491
   struct gallivm_state *gallivm = gallivm_create("sample_function", ctx->context, &cached);
 
492
 
 
493
   struct lp_sampler_static_state state = {
 
494
      .texture_state = *texture,
 
495
   };
 
496
   struct lp_build_sampler_soa *sampler_soa = lp_llvm_sampler_soa_create(&state, 1);
 
497
 
 
498
   struct lp_type type;
 
499
   memset(&type, 0, sizeof type);
 
500
   type.floating = true;      /* floating point values */
 
501
   type.sign = true;          /* values are signed */
 
502
   type.norm = false;         /* values are not limited to [0,1] or [-1,1] */
 
503
   type.width = 32;           /* 32-bit float */
 
504
   type.length = MIN2(lp_native_vector_width / 32, 16); /* n*4 elements per vector */
 
505
 
 
506
   struct lp_compute_shader_variant cs = { .gallivm = gallivm };
 
507
   lp_jit_init_cs_types(&cs);
 
508
 
 
509
   struct lp_sampler_size_query_params params = {
 
510
      .int_type = lp_int_type(type),
 
511
      .target = texture->target,
 
512
      .resources_type = cs.jit_resources_type,
 
513
      .is_sviewinfo = true,
 
514
      .samples_only = samples,
 
515
   };
 
516
 
 
517
   if (params.target == PIPE_TEXTURE_1D)
 
518
      params.target = PIPE_TEXTURE_1D_ARRAY;
 
519
   else if (params.target == PIPE_TEXTURE_2D)
 
520
      params.target = PIPE_TEXTURE_2D_ARRAY;
 
521
   else if (params.target == PIPE_TEXTURE_CUBE)
 
522
      params.target = PIPE_TEXTURE_CUBE_ARRAY;
 
523
 
 
524
   LLVMTypeRef function_type = lp_build_size_function_type(gallivm, &params);
 
525
   LLVMValueRef function = LLVMAddFunction(gallivm->module, "size", function_type);
 
526
 
 
527
   uint32_t arg_index = 0;
 
528
 
 
529
   gallivm->texture_descriptor = LLVMGetParam(function, arg_index++);
 
530
 
 
531
   if (!samples)
 
532
      params.explicit_lod = LLVMGetParam(function, arg_index++);
 
533
 
 
534
   LLVMBuilderRef old_builder = gallivm->builder;
 
535
   LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(gallivm->context, function, "entry");
 
536
   gallivm->builder = LLVMCreateBuilderInContext(gallivm->context);
 
537
   LLVMPositionBuilderAtEnd(gallivm->builder, block);
 
538
 
 
539
   LLVMValueRef out_sizes[4] = { 0 };
 
540
   params.sizes_out = out_sizes;
 
541
   lp_build_size_query_soa(gallivm, texture, lp_build_sampler_soa_dynamic_state(sampler_soa), &params);
 
542
 
 
543
   for (uint32_t i = 0; i < 4; i++)
 
544
      if (!out_sizes[i])
 
545
         out_sizes[i] = lp_build_const_int_vec(gallivm, params.int_type, 0);
 
546
 
 
547
   LLVMBuildAggregateRet(gallivm->builder, out_sizes, 4);
 
548
 
 
549
   LLVMDisposeBuilder(gallivm->builder);
 
550
   gallivm->builder = old_builder;
 
551
 
 
552
   free(sampler_soa);
 
553
 
 
554
   return compile_function(ctx, gallivm, function, cache_key);
 
555
}
 
556
 
 
557
static void
 
558
compile_sample_functions(struct llvmpipe_context *ctx, struct lp_static_texture_state *texture,
 
559
                        struct lp_static_sampler_state *sampler, void ***dst)
 
560
{
 
561
   void **functions;
 
562
   if (*dst) {
 
563
      functions = *dst;
 
564
   } else {
 
565
      functions = calloc(LP_SAMPLE_KEY_COUNT, sizeof(void *));
 
566
      *dst = functions;
 
567
   }
 
568
 
 
569
   bool has_sampler = !!sampler;
 
570
 
 
571
   struct lp_static_sampler_state dummy_sampler = { 0 };
 
572
   if (!sampler)
 
573
      sampler = &dummy_sampler;
 
574
 
 
575
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
576
   for (uint32_t sample_key = 0; sample_key < LP_SAMPLE_KEY_COUNT; sample_key++) {
 
577
      if (!matrix->sampler_keys[sample_key])
 
578
         continue;
 
579
 
 
580
      enum lp_sampler_op_type op_type = (sample_key & LP_SAMPLER_OP_TYPE_MASK) >> LP_SAMPLER_OP_TYPE_SHIFT;
 
581
      if (has_sampler && op_type == LP_SAMPLER_OP_FETCH)
 
582
         continue;
 
583
 
 
584
      if (!functions[sample_key])
 
585
         functions[sample_key] = compile_sample_function(ctx, texture, sampler, sample_key);
 
586
   }
 
587
}
 
588
 
 
589
static void
 
590
llvmpipe_register_texture(struct llvmpipe_context *ctx, struct lp_static_texture_state *state, bool sampled)
 
591
{
 
592
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
593
 
 
594
   bool packed = true;
 
595
   uint32_t dst_index = matrix->texture_count;
 
596
   for (uint32_t i = 0; i < matrix->texture_count; i++) {
 
597
      if (memcmp(&matrix->textures[i]->state, state, sizeof(struct lp_static_texture_state)))
 
598
         continue;
 
599
 
 
600
      bool has_functions = sampled ? matrix->textures[i]->sampled : matrix->textures[i]->storage;
 
601
 
 
602
      uint32_t prev_ref_count = matrix->textures[i]->ref_count++;
 
603
      if (has_functions && prev_ref_count)
 
604
         return;
 
605
 
 
606
      packed = false;
 
607
      dst_index = i;
 
608
      break;
 
609
   }
 
610
 
 
611
   struct lp_texture_functions *entry;
 
612
   if (packed) {
 
613
      matrix->texture_count++;
 
614
      matrix->textures = realloc(matrix->textures, matrix->texture_count * sizeof(struct lp_texture_functions *));
 
615
 
 
616
      entry = calloc(1, sizeof(struct lp_texture_functions));
 
617
      matrix->textures[dst_index] = entry;
 
618
 
 
619
      entry->ref_count = 1;
 
620
      entry->state = *state;
 
621
      entry->image_functions = calloc(LP_TOTAL_IMAGE_OP_COUNT, sizeof(void **));
 
622
   } else {
 
623
      entry = matrix->textures[dst_index];
 
624
   }
 
625
 
 
626
   if (sampled)
 
627
      entry->sampled = true;
 
628
   else
 
629
      entry->storage = true;
 
630
 
 
631
   if (entry->sampled) {
 
632
      if (entry->sample_functions) {
 
633
         entry->sample_functions = realloc(entry->sample_functions, matrix->sampler_count * sizeof(void **));
 
634
         memset(entry->sample_functions + entry->sampler_count, 0, (matrix->sampler_count - entry->sampler_count) * sizeof(void **));
 
635
      } else {
 
636
         entry->sample_functions = calloc(matrix->sampler_count, sizeof(void **));
 
637
      }
 
638
      entry->sampler_count = matrix->sampler_count;
 
639
 
 
640
      if (state->format == PIPE_FORMAT_NONE) {
 
641
         if (matrix->sampler_count)
 
642
            compile_sample_functions(ctx, state, NULL, entry->sample_functions);
 
643
         for (uint32_t i = 1; i < matrix->sampler_count; i++)
 
644
            entry->sample_functions[i] = entry->sample_functions[0];
 
645
      } else {
 
646
         for (uint32_t i = 0; i < matrix->sampler_count; i++)
 
647
            compile_sample_functions(ctx, state, matrix->samplers + i, entry->sample_functions + i);
 
648
      }
 
649
 
 
650
      compile_sample_functions(ctx, state, NULL, &entry->fetch_functions);
 
651
 
 
652
      if (!entry->size_function)
 
653
         entry->size_function = compile_size_function(ctx, state, false);
 
654
 
 
655
      if (!entry->samples_function)
 
656
         entry->samples_function = compile_size_function(ctx, state, true);
 
657
   }
 
658
 
 
659
   if (entry->storage) {
 
660
      uint32_t image_op;
 
661
      BITSET_FOREACH_SET (image_op, matrix->image_ops, LP_TOTAL_IMAGE_OP_COUNT)
 
662
         if (!entry->image_functions[image_op])
 
663
            entry->image_functions[image_op] = compile_image_function(ctx, state, image_op);
 
664
   }
 
665
}
 
666
 
 
667
static void
 
668
llvmpipe_register_sampler(struct llvmpipe_context *ctx, struct lp_static_sampler_state *state)
 
669
{
 
670
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
671
   for (uint32_t i = 0; i < matrix->sampler_count; i++)
 
672
      if (!memcmp(matrix->samplers + i, state, sizeof(struct lp_static_sampler_state)))
 
673
         return;
 
674
 
 
675
   matrix->sampler_count++;
 
676
   matrix->samplers = realloc(matrix->samplers, matrix->sampler_count * sizeof(struct lp_static_sampler_state));
 
677
 
 
678
   matrix->samplers[matrix->sampler_count - 1] = *state;
 
679
 
 
680
   for (uint32_t i = 0; i < matrix->texture_count; i++) {
 
681
      struct lp_texture_functions *texture = matrix->textures[i];
 
682
      if (!texture->ref_count || !texture->sampled)
 
683
         continue;
 
684
 
 
685
      texture->sampler_count = matrix->sampler_count;
 
686
      texture->sample_functions = realloc(texture->sample_functions, matrix->sampler_count * sizeof(void **));
 
687
 
 
688
      void ***dst = texture->sample_functions + (matrix->sampler_count - 1);
 
689
 
 
690
      if (texture->state.format == PIPE_FORMAT_NONE)  {
 
691
         if (matrix->sampler_count == 1) {
 
692
            *dst = NULL;
 
693
            compile_sample_functions(ctx, &texture->state, NULL, dst);
 
694
         } else {
 
695
            *dst = texture->sample_functions[0];
 
696
         }
 
697
 
 
698
         continue;
 
699
      }
 
700
 
 
701
      *dst = NULL;
 
702
      compile_sample_functions(ctx, &texture->state, state, dst);
 
703
   }
 
704
}
 
705
 
 
706
static void
 
707
register_sample_key(struct llvmpipe_context *ctx, uint32_t sample_key)
 
708
{
 
709
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
710
 
 
711
   uint32_t prev_ref_count = matrix->sampler_keys[sample_key]++;
 
712
   if (prev_ref_count)
 
713
      return;
 
714
 
 
715
   for (uint32_t texture_index = 0; texture_index < matrix->texture_count; texture_index++) {
 
716
      struct lp_texture_functions *texture = matrix->textures[texture_index];
 
717
      if (!texture->ref_count || !texture->sampled)
 
718
         continue;
 
719
 
 
720
      enum lp_sampler_op_type op_type = (sample_key & LP_SAMPLER_OP_TYPE_MASK) >> LP_SAMPLER_OP_TYPE_SHIFT;
 
721
      if (op_type == LP_SAMPLER_OP_FETCH) {
 
722
         if (!texture->fetch_functions[sample_key]) {
 
723
            struct lp_static_sampler_state dummy_sampler = { 0 };
 
724
            texture->fetch_functions[sample_key] = compile_sample_function(ctx, &texture->state, &dummy_sampler, sample_key);
 
725
         }
 
726
         continue;
 
727
      }
 
728
 
 
729
      if (texture->state.format == PIPE_FORMAT_NONE) {
 
730
         if (matrix->sampler_count && !texture->sample_functions[0][sample_key]) {
 
731
            struct lp_static_sampler_state dummy_sampler = { 0 };
 
732
            texture->sample_functions[0][sample_key] = compile_sample_function(ctx, &texture->state, &dummy_sampler, sample_key);
 
733
         }
 
734
         continue;
 
735
      }
 
736
 
 
737
      for (uint32_t sampler_index = 0; sampler_index < matrix->sampler_count; sampler_index++) {
 
738
         if (!texture->sample_functions[sampler_index][sample_key]) {
 
739
            texture->sample_functions[sampler_index][sample_key] = compile_sample_function(
 
740
               ctx, &texture->state, matrix->samplers + sampler_index, sample_key);
 
741
         }
 
742
      }
 
743
   }
 
744
}
 
745
 
 
746
static void
 
747
unregister_sample_key(struct llvmpipe_context *ctx, uint32_t sample_key)
 
748
{
 
749
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
750
 
 
751
   assert(matrix->sampler_keys[sample_key]);
 
752
   matrix->sampler_keys[sample_key]--;
 
753
}
 
754
 
 
755
static void
 
756
register_image_op(struct llvmpipe_context *ctx, uint32_t op)
 
757
{
 
758
   struct lp_sampler_matrix *matrix = &ctx->sampler_matrix;
 
759
   if (BITSET_TEST(matrix->image_ops, op))
 
760
      return;
 
761
 
 
762
   BITSET_SET(matrix->image_ops, op);
 
763
 
 
764
   for (uint32_t texture_index = 0; texture_index < matrix->texture_count; texture_index++) {
 
765
      struct lp_texture_functions *texture = matrix->textures[texture_index];
 
766
      if (texture->ref_count && texture->storage)
 
767
         texture->image_functions[op] = compile_image_function(ctx, &texture->state, op);
 
768
   }
 
769
}
 
770
 
 
771
struct register_shader_state {
 
772
   struct llvmpipe_context *ctx;
 
773
   bool unregister;
 
774
};
 
775
 
 
776
static bool
 
777
register_instr(nir_builder *b, nir_instr *instr, void *_state)
 
778
{
 
779
   struct register_shader_state *state = _state;
 
780
 
 
781
   if (instr->type == nir_instr_type_tex) {
 
782
      nir_tex_instr *tex = nir_instr_as_tex(instr);
 
783
      uint32_t sample_key = lp_build_nir_sample_key(b->shader->info.stage, tex);
 
784
 
 
785
      if (state->unregister)
 
786
         unregister_sample_key(state->ctx, sample_key);
 
787
      else
 
788
         register_sample_key(state->ctx, sample_key);
 
789
   } else if (instr->type == nir_instr_type_intrinsic) {
 
790
      nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
 
791
 
 
792
      struct lp_img_params params;
 
793
      lp_img_op_from_intrinsic(&params, intrin);
 
794
 
 
795
      if (params.img_op == -1)
 
796
         return false;
 
797
 
 
798
      uint32_t op = params.img_op;
 
799
      if (op == LP_IMG_ATOMIC_CAS)
 
800
         op--;
 
801
      else if (op == LP_IMG_ATOMIC)
 
802
         op = params.op + (LP_IMG_OP_COUNT - 1);
 
803
 
 
804
      if (nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_MS ||
 
805
          nir_intrinsic_image_dim(intrin) == GLSL_SAMPLER_DIM_SUBPASS_MS)
 
806
         op += LP_TOTAL_IMAGE_OP_COUNT / 2;
 
807
 
 
808
      register_image_op(state->ctx, op);
 
809
   }
 
810
 
 
811
   return false;
 
812
}
 
813
 
 
814
void
 
815
llvmpipe_register_shader(struct pipe_context *ctx, const struct pipe_shader_state *shader, bool unregister)
 
816
{
 
817
   if (shader->type != PIPE_SHADER_IR_NIR)
 
818
      return;
 
819
 
 
820
   struct register_shader_state state = {
 
821
      .ctx = llvmpipe_context(ctx),
 
822
      .unregister = unregister,
 
823
   };
 
824
   nir_shader_instructions_pass(shader->ir.nir, register_instr, nir_metadata_all, &state);
 
825
}