Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/iris/iris_program_cache.c
4565 views
1
/*
2
* Copyright © 2017 Intel 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 shall be included
12
* in all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
* DEALINGS IN THE SOFTWARE.
21
*/
22
23
/**
24
* @file iris_program_cache.c
25
*
26
* The in-memory program cache. This is basically a hash table mapping
27
* API-specified shaders and a state key to a compiled variant. It also
28
* takes care of uploading shader assembly into a BO for use on the GPU.
29
*/
30
31
#include <stdio.h>
32
#include <errno.h>
33
#include "pipe/p_defines.h"
34
#include "pipe/p_state.h"
35
#include "pipe/p_context.h"
36
#include "pipe/p_screen.h"
37
#include "util/u_atomic.h"
38
#include "util/u_upload_mgr.h"
39
#include "compiler/nir/nir.h"
40
#include "compiler/nir/nir_builder.h"
41
#include "intel/common/intel_disasm.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"
47
48
struct keybox {
49
uint16_t size;
50
enum iris_program_cache_id cache_id;
51
uint8_t data[0];
52
};
53
54
static struct keybox *
55
make_keybox(void *mem_ctx,
56
enum iris_program_cache_id cache_id,
57
const void *key,
58
uint32_t key_size)
59
{
60
struct keybox *keybox =
61
ralloc_size(mem_ctx, sizeof(struct keybox) + key_size);
62
63
keybox->cache_id = cache_id;
64
keybox->size = key_size;
65
memcpy(keybox->data, key, key_size);
66
67
return keybox;
68
}
69
70
static uint32_t
71
keybox_hash(const void *void_key)
72
{
73
const struct keybox *key = void_key;
74
return _mesa_hash_data(&key->cache_id, key->size + sizeof(key->cache_id));
75
}
76
77
static bool
78
keybox_equals(const void *void_a, const void *void_b)
79
{
80
const struct keybox *a = void_a, *b = void_b;
81
if (a->size != b->size)
82
return false;
83
84
return memcmp(a->data, b->data, a->size) == 0;
85
}
86
87
struct iris_compiled_shader *
88
iris_find_cached_shader(struct iris_context *ice,
89
enum iris_program_cache_id cache_id,
90
uint32_t key_size,
91
const void *key)
92
{
93
struct keybox *keybox = make_keybox(NULL, cache_id, key, key_size);
94
struct hash_entry *entry =
95
_mesa_hash_table_search(ice->shaders.cache, keybox);
96
97
ralloc_free(keybox);
98
99
return entry ? entry->data : NULL;
100
}
101
102
void
103
iris_delete_shader_variant(struct iris_compiled_shader *shader)
104
{
105
pipe_resource_reference(&shader->assembly.res, NULL);
106
ralloc_free(shader);
107
}
108
109
struct iris_compiled_shader *
110
iris_upload_shader(struct iris_screen *screen,
111
struct iris_uncompiled_shader *ish,
112
struct hash_table *driver_shaders,
113
struct u_upload_mgr *uploader,
114
enum iris_program_cache_id cache_id,
115
uint32_t key_size,
116
const void *key,
117
const void *assembly,
118
struct brw_stage_prog_data *prog_data,
119
uint32_t *streamout,
120
enum brw_param_builtin *system_values,
121
unsigned num_system_values,
122
unsigned kernel_input_size,
123
unsigned num_cbufs,
124
const struct iris_binding_table *bt)
125
{
126
const struct intel_device_info *devinfo = &screen->devinfo;
127
128
void *mem_ctx = ish ? NULL : (void *) driver_shaders;
129
struct iris_compiled_shader *shader =
130
rzalloc_size(mem_ctx, sizeof(struct iris_compiled_shader) +
131
screen->vtbl.derived_program_state_size(cache_id));
132
133
pipe_reference_init(&shader->ref, 1);
134
135
shader->assembly.res = NULL;
136
u_upload_alloc(uploader, 0, prog_data->program_size, 64,
137
&shader->assembly.offset, &shader->assembly.res,
138
&shader->map);
139
memcpy(shader->map, assembly, prog_data->program_size);
140
141
struct iris_resource *res = (void *) shader->assembly.res;
142
uint64_t shader_data_addr = res->bo->gtt_offset +
143
shader->assembly.offset +
144
prog_data->const_data_offset;
145
146
struct brw_shader_reloc_value reloc_values[] = {
147
{
148
.id = BRW_SHADER_RELOC_CONST_DATA_ADDR_LOW,
149
.value = shader_data_addr,
150
},
151
{
152
.id = BRW_SHADER_RELOC_CONST_DATA_ADDR_HIGH,
153
.value = shader_data_addr >> 32,
154
},
155
};
156
brw_write_shader_relocs(&screen->devinfo, shader->map, prog_data,
157
reloc_values, ARRAY_SIZE(reloc_values));
158
159
shader->prog_data = prog_data;
160
shader->streamout = streamout;
161
shader->system_values = system_values;
162
shader->num_system_values = num_system_values;
163
shader->kernel_input_size = kernel_input_size;
164
shader->num_cbufs = num_cbufs;
165
shader->bt = *bt;
166
167
ralloc_steal(shader, shader->prog_data);
168
ralloc_steal(shader->prog_data, (void *)prog_data->relocs);
169
ralloc_steal(shader->prog_data, prog_data->param);
170
ralloc_steal(shader->prog_data, prog_data->pull_param);
171
ralloc_steal(shader, shader->streamout);
172
ralloc_steal(shader, shader->system_values);
173
174
/* Store the 3DSTATE shader packets and other derived state. */
175
screen->vtbl.store_derived_program_state(devinfo, cache_id, shader);
176
177
if (ish) {
178
assert(key_size <= sizeof(union iris_any_prog_key));
179
memcpy(&shader->key, key, key_size);
180
181
simple_mtx_lock(&ish->lock);
182
183
/* While unlikely, it's possible that another thread concurrently
184
* compiled the same variant. Make sure no one beat us to it; if
185
* they did, return the existing one and discard our new one.
186
*/
187
list_for_each_entry(struct iris_compiled_shader, existing,
188
&ish->variants, link) {
189
if (memcmp(&existing->key, key, key_size) == 0) {
190
iris_delete_shader_variant(shader);
191
simple_mtx_unlock(&ish->lock);
192
return existing;
193
}
194
}
195
196
/* Append our new variant to the shader's variant list. */
197
list_addtail(&shader->link, &ish->variants);
198
199
simple_mtx_unlock(&ish->lock);
200
} else {
201
struct keybox *keybox = make_keybox(shader, cache_id, key, key_size);
202
_mesa_hash_table_insert(driver_shaders, keybox, shader);
203
}
204
205
return shader;
206
}
207
208
bool
209
iris_blorp_lookup_shader(struct blorp_batch *blorp_batch,
210
const void *key, uint32_t key_size,
211
uint32_t *kernel_out, void *prog_data_out)
212
{
213
struct blorp_context *blorp = blorp_batch->blorp;
214
struct iris_context *ice = blorp->driver_ctx;
215
struct iris_batch *batch = blorp_batch->driver_batch;
216
struct iris_compiled_shader *shader =
217
iris_find_cached_shader(ice, IRIS_CACHE_BLORP, key_size, key);
218
219
if (!shader)
220
return false;
221
222
struct iris_bo *bo = iris_resource_bo(shader->assembly.res);
223
*kernel_out =
224
iris_bo_offset_from_base_address(bo) + shader->assembly.offset;
225
*((void **) prog_data_out) = shader->prog_data;
226
227
iris_use_pinned_bo(batch, bo, false, IRIS_DOMAIN_NONE);
228
229
return true;
230
}
231
232
bool
233
iris_blorp_upload_shader(struct blorp_batch *blorp_batch, uint32_t stage,
234
const void *key, uint32_t key_size,
235
const void *kernel, UNUSED uint32_t kernel_size,
236
const struct brw_stage_prog_data *prog_data_templ,
237
UNUSED uint32_t prog_data_size,
238
uint32_t *kernel_out, void *prog_data_out)
239
{
240
struct blorp_context *blorp = blorp_batch->blorp;
241
struct iris_context *ice = blorp->driver_ctx;
242
struct iris_batch *batch = blorp_batch->driver_batch;
243
struct iris_screen *screen = batch->screen;
244
245
void *prog_data = ralloc_size(NULL, prog_data_size);
246
memcpy(prog_data, prog_data_templ, prog_data_size);
247
248
struct iris_binding_table bt;
249
memset(&bt, 0, sizeof(bt));
250
251
struct iris_compiled_shader *shader =
252
iris_upload_shader(screen, NULL, ice->shaders.cache,
253
ice->shaders.uploader_driver,
254
IRIS_CACHE_BLORP, key_size, key, kernel,
255
prog_data, NULL, NULL, 0, 0, 0, &bt);
256
257
struct iris_bo *bo = iris_resource_bo(shader->assembly.res);
258
*kernel_out =
259
iris_bo_offset_from_base_address(bo) + shader->assembly.offset;
260
*((void **) prog_data_out) = shader->prog_data;
261
262
iris_use_pinned_bo(batch, bo, false, IRIS_DOMAIN_NONE);
263
264
return true;
265
}
266
267
void
268
iris_init_program_cache(struct iris_context *ice)
269
{
270
ice->shaders.cache =
271
_mesa_hash_table_create(ice, keybox_hash, keybox_equals);
272
273
ice->shaders.uploader_driver =
274
u_upload_create(&ice->ctx, 16384, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE,
275
IRIS_RESOURCE_FLAG_SHADER_MEMZONE |
276
IRIS_RESOURCE_FLAG_DEVICE_MEM);
277
ice->shaders.uploader_unsync =
278
u_upload_create(&ice->ctx, 16384, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE,
279
IRIS_RESOURCE_FLAG_SHADER_MEMZONE |
280
IRIS_RESOURCE_FLAG_DEVICE_MEM);
281
}
282
283
void
284
iris_destroy_program_cache(struct iris_context *ice)
285
{
286
for (int i = 0; i < MESA_SHADER_STAGES; i++) {
287
iris_shader_variant_reference(&ice->shaders.prog[i], NULL);
288
}
289
iris_shader_variant_reference(&ice->shaders.last_vue_shader, NULL);
290
291
hash_table_foreach(ice->shaders.cache, entry) {
292
struct iris_compiled_shader *shader = entry->data;
293
iris_delete_shader_variant(shader);
294
}
295
296
u_upload_destroy(ice->shaders.uploader_driver);
297
u_upload_destroy(ice->shaders.uploader_unsync);
298
299
ralloc_free(ice->shaders.cache);
300
}
301
302