Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/etnaviv/etnaviv_disk_cache.c
4570 views
1
/*
2
* Copyright © 2020 Google, Inc.
3
* Copyright (c) 2020 Etnaviv Project
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sub license,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice (including the
13
* next paragraph) shall be included in all copies or substantial portions
14
* of the Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
* DEALINGS IN THE SOFTWARE.
23
*
24
* Authors:
25
* Christian Gmeiner <[email protected]>
26
*/
27
28
#include "etnaviv_debug.h"
29
#include "etnaviv_disk_cache.h"
30
#include "nir_serialize.h"
31
32
#define debug 0
33
34
void
35
etna_disk_cache_init(struct etna_compiler *compiler, const char *renderer)
36
{
37
if (!(etna_mesa_debug & ETNA_DBG_NIR))
38
return;
39
40
if (etna_mesa_debug & ETNA_DBG_NOCACHE)
41
return;
42
43
const struct build_id_note *note =
44
build_id_find_nhdr_for_addr(etna_disk_cache_init);
45
assert(note && build_id_length(note) == 20); /* sha1 */
46
47
const uint8_t *id_sha1 = build_id_data(note);
48
assert(id_sha1);
49
50
char timestamp[41];
51
_mesa_sha1_format(timestamp, id_sha1);
52
53
compiler->disk_cache = disk_cache_create(renderer, timestamp, etna_mesa_debug);
54
}
55
56
void
57
etna_disk_cache_init_shader_key(struct etna_compiler *compiler, struct etna_shader *shader)
58
{
59
if (!compiler->disk_cache)
60
return;
61
62
struct mesa_sha1 ctx;
63
64
_mesa_sha1_init(&ctx);
65
66
/* Serialize the NIR to a binary blob that we can hash for the disk
67
* cache. Drop unnecessary information (like variable names)
68
* so the serialized NIR is smaller, and also to let us detect more
69
* isomorphic shaders when hashing, increasing cache hits.
70
*/
71
struct blob blob;
72
73
blob_init(&blob);
74
nir_serialize(&blob, shader->nir, true);
75
_mesa_sha1_update(&ctx, blob.data, blob.size);
76
blob_finish(&blob);
77
78
_mesa_sha1_final(&ctx, shader->cache_key);
79
}
80
81
static void
82
compute_variant_key(struct etna_compiler *compiler, struct etna_shader_variant *v,
83
cache_key cache_key)
84
{
85
struct blob blob;
86
87
blob_init(&blob);
88
89
blob_write_bytes(&blob, &v->shader->cache_key, sizeof(v->shader->cache_key));
90
blob_write_bytes(&blob, &v->key, sizeof(v->key));
91
92
disk_cache_compute_key(compiler->disk_cache, blob.data, blob.size, cache_key);
93
94
blob_finish(&blob);
95
}
96
97
static void
98
retrieve_variant(struct blob_reader *blob, struct etna_shader_variant *v)
99
{
100
blob_copy_bytes(blob, VARIANT_CACHE_PTR(v), VARIANT_CACHE_SIZE);
101
102
v->code = malloc(4 * v->code_size);
103
blob_copy_bytes(blob, v->code, 4 * v->code_size);
104
105
blob_copy_bytes(blob, &v->uniforms.count, sizeof(v->uniforms.count));
106
v->uniforms.contents = malloc(v->uniforms.count * sizeof(v->uniforms.contents));
107
v->uniforms.data = malloc(v->uniforms.count * sizeof(v->uniforms.data));
108
109
blob_copy_bytes(blob, v->uniforms.contents, v->uniforms.count * sizeof(v->uniforms.contents));
110
blob_copy_bytes(blob, v->uniforms.data, v->uniforms.count * sizeof(v->uniforms.data));
111
}
112
113
static void
114
store_variant(struct blob *blob, const struct etna_shader_variant *v)
115
{
116
const uint32_t imm_count = v->uniforms.count;
117
118
blob_write_bytes(blob, VARIANT_CACHE_PTR(v), VARIANT_CACHE_SIZE);
119
blob_write_bytes(blob, v->code, 4 * v->code_size);
120
121
blob_write_bytes(blob, &v->uniforms.count, sizeof(v->uniforms.count));
122
blob_write_bytes(blob, v->uniforms.contents, imm_count * sizeof(v->uniforms.contents));
123
blob_write_bytes(blob, v->uniforms.data, imm_count * sizeof(v->uniforms.data));
124
}
125
126
bool
127
etna_disk_cache_retrieve(struct etna_compiler *compiler, struct etna_shader_variant *v)
128
{
129
if (!compiler->disk_cache)
130
return false;
131
132
cache_key cache_key;
133
134
compute_variant_key(compiler, v, cache_key);
135
136
if (debug) {
137
char sha1[41];
138
139
_mesa_sha1_format(sha1, cache_key);
140
fprintf(stderr, "[mesa disk cache] retrieving variant %s: ", sha1);
141
}
142
143
size_t size;
144
void *buffer = disk_cache_get(compiler->disk_cache, cache_key, &size);
145
146
if (debug)
147
fprintf(stderr, "%s\n", buffer ? "found" : "missing");
148
149
if (!buffer)
150
return false;
151
152
struct blob_reader blob;
153
blob_reader_init(&blob, buffer, size);
154
155
retrieve_variant(&blob, v);
156
157
free(buffer);
158
159
return true;
160
}
161
162
void
163
etna_disk_cache_store(struct etna_compiler *compiler, struct etna_shader_variant *v)
164
{
165
if (!compiler->disk_cache)
166
return;
167
168
cache_key cache_key;
169
170
compute_variant_key(compiler, v, cache_key);
171
172
if (debug) {
173
char sha1[41];
174
175
_mesa_sha1_format(sha1, cache_key);
176
fprintf(stderr, "[mesa disk cache] storing variant %s\n", sha1);
177
}
178
179
struct blob blob;
180
blob_init(&blob);
181
182
store_variant(&blob, v);
183
184
disk_cache_put(compiler->disk_cache, cache_key, blob.data, blob.size, NULL);
185
blob_finish(&blob);
186
}
187
188