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 #include "pipe/p_defines.h"
26 #include "pipe/p_state.h"
27 #include "pipe/p_context.h"
28 #include "pipe/p_screen.h"
29 #include "util/u_atomic.h"
30 #include "util/u_upload_mgr.h"
31 #include "compiler/nir/nir.h"
32 #include "compiler/nir/nir_builder.h"
33 #include "intel/compiler/brw_compiler.h"
34 #include "intel/compiler/brw_eu.h"
35 #include "intel/compiler/brw_nir.h"
36 #include "iris_context.h"
40 enum iris_program_cache_id cache_id
;
44 static struct keybox
*
45 make_keybox(void *mem_ctx
,
46 enum iris_program_cache_id cache_id
,
49 static const unsigned key_sizes
[] = {
50 [IRIS_CACHE_VS
] = sizeof(struct brw_vs_prog_key
),
51 [IRIS_CACHE_TCS
] = sizeof(struct brw_tcs_prog_key
),
52 [IRIS_CACHE_TES
] = sizeof(struct brw_tes_prog_key
),
53 [IRIS_CACHE_GS
] = sizeof(struct brw_gs_prog_key
),
54 [IRIS_CACHE_FS
] = sizeof(struct brw_wm_prog_key
),
55 [IRIS_CACHE_CS
] = sizeof(struct brw_cs_prog_key
),
56 //[IRIS_CACHE_BLORP_BLIT] = sizeof(struct brw_blorp_blit_prog_key),
59 struct keybox
*keybox
=
60 ralloc_size(mem_ctx
, sizeof(struct keybox
) + key_sizes
[cache_id
]);
62 keybox
->cache_id
= cache_id
;
63 keybox
->size
= key_sizes
[cache_id
];
64 memcpy(keybox
->data
, key
, key_sizes
[cache_id
]);
70 keybox_hash(const void *void_key
)
72 const struct keybox
*key
= void_key
;
73 return _mesa_hash_data(&key
->cache_id
, key
->size
+ sizeof(key
->cache_id
));
77 keybox_equals(const void *void_a
, const void *void_b
)
79 const struct keybox
*a
= void_a
, *b
= void_b
;
80 if (a
->size
!= b
->size
)
83 return memcmp(a
->data
, b
->data
, a
->size
) == 0;
87 dirty_flag_for_cache(enum iris_program_cache_id cache_id
)
89 assert(cache_id
<= MESA_SHADER_STAGES
);
90 return IRIS_DIRTY_VS
<< cache_id
;
94 get_program_string_id(enum iris_program_cache_id cache_id
, const void *key
)
98 return ((struct brw_vs_prog_key
*) key
)->program_string_id
;
100 return ((struct brw_tcs_prog_key
*) key
)->program_string_id
;
102 return ((struct brw_tes_prog_key
*) key
)->program_string_id
;
104 return ((struct brw_gs_prog_key
*) key
)->program_string_id
;
106 return ((struct brw_cs_prog_key
*) key
)->program_string_id
;
108 return ((struct brw_wm_prog_key
*) key
)->program_string_id
;
110 unreachable("no program string id for this kind of program");
115 * Looks for a program in the cache and binds it.
117 * If no program was found, returns false and leaves the binding alone.
120 iris_bind_cached_shader(struct iris_context
*ice
,
121 enum iris_program_cache_id cache_id
,
124 struct keybox
*keybox
= make_keybox(ice
->shaders
.cache
, cache_id
, key
);
125 struct hash_entry
*entry
=
126 _mesa_hash_table_search(ice
->shaders
.cache
, keybox
);
131 struct iris_compiled_shader
*shader
= entry
->data
;
133 if (cache_id
<= MESA_SHADER_STAGES
&&
134 memcmp(shader
, ice
->shaders
.prog
[cache_id
], sizeof(*shader
)) != 0) {
135 ice
->shaders
.prog
[cache_id
] = shader
;
136 ice
->state
.dirty
|= dirty_flag_for_cache(cache_id
);
143 iris_find_previous_compile(const struct iris_context
*ice
,
144 enum iris_program_cache_id cache_id
,
145 unsigned program_string_id
)
147 hash_table_foreach(ice
->shaders
.cache
, entry
) {
148 const struct keybox
*keybox
= entry
->key
;
149 if (keybox
->cache_id
== cache_id
&&
150 get_program_string_id(cache_id
, keybox
->data
) == program_string_id
) {
159 * Look for an existing entry in the cache that has identical assembly code.
161 * This is useful for programs generating shaders at runtime, where multiple
162 * distinct shaders (from an API perspective) may compile to the same assembly
163 * in our backend. This saves space in the program cache buffer.
165 static const struct iris_compiled_shader
*
166 find_existing_assembly(struct hash_table
*cache
,
167 const void *assembly
,
168 unsigned assembly_size
)
170 hash_table_foreach(cache
, entry
) {
171 const struct iris_compiled_shader
*existing
= entry
->data
;
172 if (existing
->prog_data
->program_size
== assembly_size
&&
173 memcmp(existing
->map
, assembly
, assembly_size
) == 0)
180 * Upload a new shader to the program cache, and bind it for use.
182 * \param prog_data must be ralloc'd and will be stolen.
185 iris_upload_and_bind_shader(struct iris_context
*ice
,
186 enum iris_program_cache_id cache_id
,
188 const void *assembly
,
189 struct brw_stage_prog_data
*prog_data
)
191 struct iris_screen
*screen
= (void *) ice
->ctx
.screen
;
192 struct gen_device_info
*devinfo
= &screen
->devinfo
;
193 struct hash_table
*cache
= ice
->shaders
.cache
;
194 struct iris_compiled_shader
*shader
=
195 ralloc_size(cache
, sizeof(struct iris_compiled_shader
) +
196 ice
->state
.derived_program_state_size(cache_id
));
197 const struct iris_compiled_shader
*existing
=
198 find_existing_assembly(cache
, assembly
, prog_data
->program_size
);
200 /* If we can find a matching prog in the cache already, then reuse the
201 * existing stuff without creating new copy into the underlying buffer
202 * object. This is notably useful for programs generating shaders at
203 * runtime, where multiple shaders may compile to the same thing in our
207 shader
->offset
= existing
->offset
;
209 shader
->buffer
= NULL
;
210 u_upload_alloc(ice
->shaders
.uploader
, 0, prog_data
->program_size
,
211 64, &shader
->offset
, &shader
->buffer
, &shader
->map
);
212 memcpy(shader
->map
, assembly
, prog_data
->program_size
);
215 shader
->prog_data
= prog_data
;
217 ralloc_steal(shader
, shader
->prog_data
);
218 ralloc_steal(shader
->prog_data
, prog_data
->param
);
219 ralloc_steal(shader
->prog_data
, prog_data
->pull_param
);
221 /* Store the 3DSTATE shader packets and other derived state. */
222 ice
->state
.set_derived_program_state(devinfo
, cache_id
, shader
);
224 struct keybox
*keybox
= make_keybox(cache
, cache_id
, key
);
225 _mesa_hash_table_insert(ice
->shaders
.cache
, keybox
, shader
);
227 if (cache_id
<= MESA_SHADER_STAGES
) {
228 ice
->shaders
.prog
[cache_id
] = shader
;
229 ice
->state
.dirty
|= dirty_flag_for_cache(cache_id
);
234 iris_init_program_cache(struct iris_context
*ice
)
237 _mesa_hash_table_create(ice
, keybox_hash
, keybox_equals
);
239 ice
->shaders
.uploader
=
240 u_upload_create(&ice
->ctx
, 16384, PIPE_BIND_CUSTOM
, PIPE_USAGE_IMMUTABLE
,
241 IRIS_RESOURCE_FLAG_INSTRUCTION_CACHE
);
245 iris_destroy_program_cache(struct iris_context
*ice
)
247 for (int i
= 0; i
< MESA_SHADER_STAGES
; i
++) {
248 ice
->shaders
.prog
[i
] = NULL
;
251 u_upload_destroy(ice
->shaders
.uploader
);
253 ralloc_free(ice
->shaders
.cache
);
257 cache_name(enum iris_program_cache_id cache_id
)
259 if (cache_id
== IRIS_CACHE_BLORP_BLIT
)
262 return _mesa_shader_stage_to_string(cache_id
);
266 iris_print_program_cache(struct iris_context
*ice
)
268 struct iris_screen
*screen
= (struct iris_screen
*)ice
->ctx
.screen
;
269 const struct gen_device_info
*devinfo
= &screen
->devinfo
;
271 hash_table_foreach(ice
->shaders
.cache
, entry
) {
272 const struct keybox
*keybox
= entry
->key
;
273 struct iris_compiled_shader
*shader
= entry
->data
;
274 fprintf(stderr
, "%s:\n", cache_name(keybox
->cache_id
));
275 brw_disassemble(devinfo
, shader
->map
, 0,
276 shader
->prog_data
->program_size
, stderr
);