2 * Copyright © 2017 Intel Corporation
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
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
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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * @file iris_program_cache.c
27 * The in-memory program cache. This is basically a hash table mapping
28 * API-specified shaders and a state key to a compiled variant. It also
29 * takes care of uploading shader assembly into a BO for use on the GPU.
34 #include "pipe/p_defines.h"
35 #include "pipe/p_state.h"
36 #include "pipe/p_context.h"
37 #include "pipe/p_screen.h"
38 #include "util/u_atomic.h"
39 #include "util/u_upload_mgr.h"
40 #include "compiler/nir/nir.h"
41 #include "compiler/nir/nir_builder.h"
42 #include "intel/compiler/brw_compiler.h"
43 #include "intel/compiler/brw_eu.h"
44 #include "intel/compiler/brw_nir.h"
45 #include "iris_context.h"
46 #include "iris_resource.h"
50 enum iris_program_cache_id cache_id
;
55 key_size_for_cache(enum iris_program_cache_id cache_id
)
57 static const unsigned key_sizes
[] = {
58 [IRIS_CACHE_VS
] = sizeof(struct brw_vs_prog_key
),
59 [IRIS_CACHE_TCS
] = sizeof(struct brw_tcs_prog_key
),
60 [IRIS_CACHE_TES
] = sizeof(struct brw_tes_prog_key
),
61 [IRIS_CACHE_GS
] = sizeof(struct brw_gs_prog_key
),
62 [IRIS_CACHE_FS
] = sizeof(struct brw_wm_prog_key
),
63 [IRIS_CACHE_CS
] = sizeof(struct brw_cs_prog_key
),
66 /* BLORP keys aren't all the same size. */
67 assert(cache_id
!= IRIS_CACHE_BLORP
);
69 return key_sizes
[cache_id
];
72 static struct keybox
*
73 make_keybox(void *mem_ctx
,
74 enum iris_program_cache_id cache_id
,
78 struct keybox
*keybox
=
79 ralloc_size(mem_ctx
, sizeof(struct keybox
) + key_size
);
81 keybox
->cache_id
= cache_id
;
82 keybox
->size
= key_size
;
83 memcpy(keybox
->data
, key
, key_size
);
89 keybox_hash(const void *void_key
)
91 const struct keybox
*key
= void_key
;
92 return _mesa_hash_data(&key
->cache_id
, key
->size
+ sizeof(key
->cache_id
));
96 keybox_equals(const void *void_a
, const void *void_b
)
98 const struct keybox
*a
= void_a
, *b
= void_b
;
99 if (a
->size
!= b
->size
)
102 return memcmp(a
->data
, b
->data
, a
->size
) == 0;
106 dirty_flag_for_cache(enum iris_program_cache_id cache_id
)
108 assert(cache_id
<= MESA_SHADER_STAGES
);
111 // XXX: move this flagging out to a higher level, allow comparison of
112 // XXX: new and old programs to decide what bits to twiddle
113 // XXX: CLIP: toggle if barycentric modes has any NONPERSPECTIVE or not
114 if (cache_id
== IRIS_CACHE_FS
)
115 return IRIS_DIRTY_WM
| IRIS_DIRTY_FS
| IRIS_DIRTY_CLIP
;
116 if (cache_id
== IRIS_CACHE_VS
)
117 return IRIS_DIRTY_VS
| IRIS_DIRTY_VF_SGVS
;
119 return IRIS_DIRTY_VS
<< cache_id
| IRIS_DIRTY_BINDINGS_VS
<< cache_id
;
123 get_program_string_id(enum iris_program_cache_id cache_id
, const void *key
)
127 return ((struct brw_vs_prog_key
*) key
)->program_string_id
;
129 return ((struct brw_tcs_prog_key
*) key
)->program_string_id
;
131 return ((struct brw_tes_prog_key
*) key
)->program_string_id
;
133 return ((struct brw_gs_prog_key
*) key
)->program_string_id
;
135 return ((struct brw_cs_prog_key
*) key
)->program_string_id
;
137 return ((struct brw_wm_prog_key
*) key
)->program_string_id
;
139 unreachable("no program string id for this kind of program");
143 static struct iris_compiled_shader
*
144 iris_find_cached_shader(struct iris_context
*ice
,
145 enum iris_program_cache_id cache_id
,
149 struct keybox
*keybox
=
150 make_keybox(ice
->shaders
.cache
, cache_id
, key
, key_size
);
151 struct hash_entry
*entry
=
152 _mesa_hash_table_search(ice
->shaders
.cache
, keybox
);
156 return entry
? entry
->data
: NULL
;
160 * Looks for a program in the cache and binds it.
162 * If no program was found, returns false and leaves the binding alone.
165 iris_bind_cached_shader(struct iris_context
*ice
,
166 enum iris_program_cache_id cache_id
,
169 unsigned key_size
= key_size_for_cache(cache_id
);
170 struct iris_compiled_shader
*shader
=
171 iris_find_cached_shader(ice
, cache_id
, key
, key_size
);
176 if (memcmp(shader
, ice
->shaders
.prog
[cache_id
], sizeof(*shader
)) != 0) {
177 ice
->shaders
.prog
[cache_id
] = shader
;
178 ice
->state
.dirty
|= dirty_flag_for_cache(cache_id
);
185 iris_unbind_shader(struct iris_context
*ice
,
186 enum iris_program_cache_id cache_id
)
188 if (ice
->shaders
.prog
[cache_id
]) {
189 ice
->shaders
.prog
[cache_id
] = NULL
;
190 ice
->state
.dirty
|= dirty_flag_for_cache(cache_id
);
195 iris_find_previous_compile(const struct iris_context
*ice
,
196 enum iris_program_cache_id cache_id
,
197 unsigned program_string_id
)
199 hash_table_foreach(ice
->shaders
.cache
, entry
) {
200 const struct keybox
*keybox
= entry
->key
;
201 if (keybox
->cache_id
== cache_id
&&
202 get_program_string_id(cache_id
, keybox
->data
) == program_string_id
) {
211 * Look for an existing entry in the cache that has identical assembly code.
213 * This is useful for programs generating shaders at runtime, where multiple
214 * distinct shaders (from an API perspective) may compile to the same assembly
215 * in our backend. This saves space in the program cache buffer.
217 static const struct iris_compiled_shader
*
218 find_existing_assembly(struct hash_table
*cache
,
219 const void *assembly
,
220 unsigned assembly_size
)
222 hash_table_foreach(cache
, entry
) {
223 const struct iris_compiled_shader
*existing
= entry
->data
;
224 if (existing
->prog_data
->program_size
== assembly_size
&&
225 memcmp(existing
->map
, assembly
, assembly_size
) == 0)
231 static struct iris_compiled_shader
*
232 iris_upload_shader(struct iris_context
*ice
,
233 enum iris_program_cache_id cache_id
,
236 const void *assembly
,
237 struct brw_stage_prog_data
*prog_data
,
240 struct iris_screen
*screen
= (void *) ice
->ctx
.screen
;
241 struct gen_device_info
*devinfo
= &screen
->devinfo
;
242 struct hash_table
*cache
= ice
->shaders
.cache
;
243 struct iris_compiled_shader
*shader
=
244 rzalloc_size(cache
, sizeof(struct iris_compiled_shader
) +
245 ice
->vtbl
.derived_program_state_size(cache_id
));
246 const struct iris_compiled_shader
*existing
=
247 find_existing_assembly(cache
, assembly
, prog_data
->program_size
);
249 /* If we can find a matching prog in the cache already, then reuse the
250 * existing stuff without creating new copy into the underlying buffer
251 * object. This is notably useful for programs generating shaders at
252 * runtime, where multiple shaders may compile to the same thing in our
256 pipe_resource_reference(&shader
->assembly
.res
, existing
->assembly
.res
);
257 shader
->assembly
.offset
= existing
->assembly
.offset
;
258 shader
->map
= existing
->map
;
260 shader
->assembly
.res
= NULL
;
261 u_upload_alloc(ice
->shaders
.uploader
, 0, prog_data
->program_size
, 64,
262 &shader
->assembly
.offset
, &shader
->assembly
.res
,
264 memcpy(shader
->map
, assembly
, prog_data
->program_size
);
267 shader
->prog_data
= prog_data
;
268 shader
->streamout
= streamout
;
270 ralloc_steal(shader
, shader
->prog_data
);
271 ralloc_steal(shader
->prog_data
, prog_data
->param
);
272 ralloc_steal(shader
->prog_data
, prog_data
->pull_param
);
273 ralloc_steal(shader
, shader
->streamout
);
275 /* Store the 3DSTATE shader packets and other derived state. */
276 ice
->vtbl
.store_derived_program_state(devinfo
, cache_id
, shader
);
278 struct keybox
*keybox
= make_keybox(cache
, cache_id
, key
, key_size
);
279 _mesa_hash_table_insert(ice
->shaders
.cache
, keybox
, shader
);
285 * Upload a new shader to the program cache, and bind it for use.
287 * \param prog_data must be ralloc'd and will be stolen.
290 iris_upload_and_bind_shader(struct iris_context
*ice
,
291 enum iris_program_cache_id cache_id
,
293 const void *assembly
,
294 struct brw_stage_prog_data
*prog_data
,
297 assert(cache_id
!= IRIS_CACHE_BLORP
);
299 struct iris_compiled_shader
*shader
=
300 iris_upload_shader(ice
, cache_id
, key_size_for_cache(cache_id
), key
,
301 assembly
, prog_data
, streamout
);
303 ice
->shaders
.prog
[cache_id
] = shader
;
304 ice
->state
.dirty
|= dirty_flag_for_cache(cache_id
);
308 iris_blorp_lookup_shader(struct blorp_batch
*blorp_batch
,
309 const void *key
, uint32_t key_size
,
310 uint32_t *kernel_out
, void *prog_data_out
)
312 struct blorp_context
*blorp
= blorp_batch
->blorp
;
313 struct iris_context
*ice
= blorp
->driver_ctx
;
314 struct iris_batch
*batch
= blorp_batch
->driver_batch
;
315 struct iris_compiled_shader
*shader
=
316 iris_find_cached_shader(ice
, IRIS_CACHE_BLORP
, key
, key_size
);
321 struct iris_bo
*bo
= iris_resource_bo(shader
->assembly
.res
);
323 iris_bo_offset_from_base_address(bo
) + shader
->assembly
.offset
;
324 *((void **) prog_data_out
) = shader
->prog_data
;
326 iris_use_pinned_bo(batch
, bo
, false);
332 iris_blorp_upload_shader(struct blorp_batch
*blorp_batch
,
333 const void *key
, uint32_t key_size
,
334 const void *kernel
, UNUSED
uint32_t kernel_size
,
335 const struct brw_stage_prog_data
*prog_data_templ
,
336 UNUSED
uint32_t prog_data_size
,
337 uint32_t *kernel_out
, void *prog_data_out
)
339 struct blorp_context
*blorp
= blorp_batch
->blorp
;
340 struct iris_context
*ice
= blorp
->driver_ctx
;
341 struct iris_batch
*batch
= blorp_batch
->driver_batch
;
343 void *prog_data
= ralloc_size(NULL
, prog_data_size
);
344 memcpy(prog_data
, prog_data_templ
, prog_data_size
);
346 struct iris_compiled_shader
*shader
=
347 iris_upload_shader(ice
, IRIS_CACHE_BLORP
, key_size
, key
, kernel
,
350 struct iris_bo
*bo
= iris_resource_bo(shader
->assembly
.res
);
352 iris_bo_offset_from_base_address(bo
) + shader
->assembly
.offset
;
353 *((void **) prog_data_out
) = shader
->prog_data
;
355 iris_use_pinned_bo(batch
, bo
, false);
361 iris_init_program_cache(struct iris_context
*ice
)
364 _mesa_hash_table_create(ice
, keybox_hash
, keybox_equals
);
366 ice
->shaders
.uploader
=
367 u_upload_create(&ice
->ctx
, 16384, PIPE_BIND_CUSTOM
, PIPE_USAGE_IMMUTABLE
,
368 IRIS_RESOURCE_FLAG_SHADER_MEMZONE
);
372 iris_destroy_program_cache(struct iris_context
*ice
)
374 for (int i
= 0; i
< MESA_SHADER_STAGES
; i
++) {
375 ice
->shaders
.prog
[i
] = NULL
;
378 hash_table_foreach(ice
->shaders
.cache
, entry
) {
379 struct iris_compiled_shader
*shader
= entry
->data
;
380 pipe_resource_reference(&shader
->assembly
.res
, NULL
);
383 u_upload_destroy(ice
->shaders
.uploader
);
385 ralloc_free(ice
->shaders
.cache
);
389 cache_name(enum iris_program_cache_id cache_id
)
391 if (cache_id
== IRIS_CACHE_BLORP
)
394 return _mesa_shader_stage_to_string(cache_id
);
398 iris_print_program_cache(struct iris_context
*ice
)
400 struct iris_screen
*screen
= (struct iris_screen
*)ice
->ctx
.screen
;
401 const struct gen_device_info
*devinfo
= &screen
->devinfo
;
403 hash_table_foreach(ice
->shaders
.cache
, entry
) {
404 const struct keybox
*keybox
= entry
->key
;
405 struct iris_compiled_shader
*shader
= entry
->data
;
406 fprintf(stderr
, "%s:\n", cache_name(keybox
->cache_id
));
407 brw_disassemble(devinfo
, shader
->map
, 0,
408 shader
->prog_data
->program_size
, stderr
);