Skip to content

Commit c3d53f3

Browse files
committed
nv2a/vk: Start caching shader modules
1 parent d4d1455 commit c3d53f3

File tree

3 files changed

+156
-38
lines changed

3 files changed

+156
-38
lines changed

hw/xbox/nv2a/pgraph/vk/glsl.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ ShaderModuleInfo *pgraph_vk_create_shader_module_from_glsl(
368368
PGRAPHVkState *r, VkShaderStageFlagBits stage, const char *glsl)
369369
{
370370
ShaderModuleInfo *info = g_malloc0(sizeof(*info));
371+
info->refcnt = 0;
371372
info->glsl = strdup(glsl);
372373
info->spirv = pgraph_vk_compile_glsl_to_spv(
373374
vk_shader_stage_to_glslang_stage(stage), glsl);
@@ -386,8 +387,24 @@ static void finalize_uniform_layout(ShaderUniformLayout *layout)
386387
}
387388
}
388389

390+
void pgraph_vk_ref_shader_module(ShaderModuleInfo *info)
391+
{
392+
info->refcnt++;
393+
}
394+
395+
void pgraph_vk_unref_shader_module(PGRAPHVkState *r, ShaderModuleInfo *info)
396+
{
397+
assert(info->refcnt >= 1);
398+
399+
info->refcnt--;
400+
if (info->refcnt == 0) {
401+
pgraph_vk_destroy_shader_module(r, info);
402+
}
403+
}
404+
389405
void pgraph_vk_destroy_shader_module(PGRAPHVkState *r, ShaderModuleInfo *info)
390406
{
407+
assert(info->refcnt == 0);
391408
if (info->glsl) {
392409
free(info->glsl);
393410
}

hw/xbox/nv2a/pgraph/vk/renderer.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ typedef struct SurfaceBinding {
146146
} SurfaceBinding;
147147

148148
typedef struct ShaderModuleInfo {
149+
int refcnt;
149150
char *glsl;
150151
GByteArray *spirv;
151152
VkShaderModule module;
@@ -155,6 +156,26 @@ typedef struct ShaderModuleInfo {
155156
ShaderUniformLayout push_constants;
156157
} ShaderModuleInfo;
157158

159+
typedef struct ShaderModuleCacheKey {
160+
VkShaderStageFlagBits kind;
161+
union {
162+
VshState vsh;
163+
GeomState geom;
164+
PshState psh;
165+
} state;
166+
union {
167+
GenVshGlslOptions vsh;
168+
GenGeomGlslOptions geom;
169+
GenPshGlslOptions psh;
170+
} glsl_options;
171+
} ShaderModuleCacheKey;
172+
173+
typedef struct ShaderModuleCacheEntry {
174+
LruNode node;
175+
ShaderModuleCacheKey key;
176+
ShaderModuleInfo *module_info;
177+
} ShaderModuleCacheEntry;
178+
158179
typedef struct ShaderBinding {
159180
LruNode node;
160181
bool initialized;
@@ -380,6 +401,9 @@ typedef struct PGRAPHVkState {
380401
bool shader_bindings_changed;
381402
bool use_push_constants_for_uniform_attrs;
382403

404+
Lru shader_module_cache;
405+
ShaderModuleCacheEntry *shader_module_cache_entries;
406+
383407
// FIXME: Merge these into a structure
384408
uint64_t uniform_buffer_hashes[2];
385409
size_t uniform_buffer_offsets[2];
@@ -435,6 +459,8 @@ VkShaderModule pgraph_vk_create_shader_module_from_spv(PGRAPHVkState *r,
435459
GByteArray *spv);
436460
ShaderModuleInfo *pgraph_vk_create_shader_module_from_glsl(
437461
PGRAPHVkState *r, VkShaderStageFlagBits stage, const char *glsl);
462+
void pgraph_vk_ref_shader_module(ShaderModuleInfo *info);
463+
void pgraph_vk_unref_shader_module(PGRAPHVkState *r, ShaderModuleInfo *info);
438464
void pgraph_vk_destroy_shader_module(PGRAPHVkState *r, ShaderModuleInfo *info);
439465

440466
// buffer.c

hw/xbox/nv2a/pgraph/vk/shaders.c

Lines changed: 113 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static void shader_cache_entry_init(Lru *lru, LruNode *node, void *state)
258258

259259
static void shader_cache_entry_post_evict(Lru *lru, LruNode *node)
260260
{
261-
PGRAPHVkState *r = container_of(lru, PGRAPHVkState, shader_cache);
261+
PGRAPHVkState *r = container_of(lru, PGRAPHVkState, shader_module_cache);
262262
ShaderBinding *snode = container_of(node, ShaderBinding, node);
263263

264264
ShaderModuleInfo *modules[] = {
@@ -268,7 +268,7 @@ static void shader_cache_entry_post_evict(Lru *lru, LruNode *node)
268268
};
269269
for (int i = 0; i < ARRAY_SIZE(modules); i++) {
270270
if (modules[i]) {
271-
pgraph_vk_destroy_shader_module(r, modules[i]);
271+
pgraph_vk_unref_shader_module(r, modules[i]);
272272
}
273273
}
274274

@@ -281,6 +281,60 @@ static bool shader_cache_entry_compare(Lru *lru, LruNode *node, void *key)
281281
return memcmp(&snode->state, key, sizeof(ShaderState));
282282
}
283283

284+
static void shader_module_cache_entry_init(Lru *lru, LruNode *node, void *key)
285+
{
286+
ShaderModuleCacheEntry *module =
287+
container_of(node, ShaderModuleCacheEntry, node);
288+
memcpy(&module->key, key, sizeof(ShaderModuleCacheKey));
289+
290+
MString *code;
291+
292+
switch (module->key.kind) {
293+
case VK_SHADER_STAGE_VERTEX_BIT:
294+
code = pgraph_glsl_gen_vsh(
295+
&module->key.state.vsh, module->key.glsl_options.vsh);
296+
break;
297+
case VK_SHADER_STAGE_GEOMETRY_BIT:
298+
code = pgraph_glsl_gen_geom(
299+
&module->key.state.geom, module->key.glsl_options.geom);
300+
break;
301+
case VK_SHADER_STAGE_FRAGMENT_BIT:
302+
code = pgraph_glsl_gen_psh(
303+
&module->key.state.psh, module->key.glsl_options.psh);
304+
break;
305+
default:
306+
assert(!"Invalid shader module kind");
307+
code = NULL;
308+
}
309+
310+
PGRAPHVkState *r = container_of(lru, PGRAPHVkState, shader_module_cache);
311+
module->module_info = pgraph_vk_create_shader_module_from_glsl(
312+
r, module->key.kind, mstring_get_str(code));
313+
pgraph_vk_ref_shader_module(module->module_info);
314+
mstring_unref(code);
315+
}
316+
317+
static void shader_module_cache_entry_post_evict(Lru *lru, LruNode *node)
318+
{
319+
ShaderModuleCacheEntry *module =
320+
container_of(node, ShaderModuleCacheEntry, node);
321+
if (module->module_info) {
322+
PGRAPHVkState *r =
323+
container_of(lru, PGRAPHVkState, shader_module_cache);
324+
pgraph_vk_unref_shader_module(r, module->module_info);
325+
module->module_info = NULL;
326+
}
327+
memset(&module->key, 0, sizeof(ShaderModuleCacheKey));
328+
}
329+
330+
static bool shader_module_cache_entry_compare(Lru *lru, LruNode *node,
331+
void *key)
332+
{
333+
ShaderModuleCacheEntry *module =
334+
container_of(node, ShaderModuleCacheEntry, node);
335+
return memcmp(&module->key, key, sizeof(ShaderModuleCacheKey));
336+
}
337+
284338
static void shader_cache_init(PGRAPHState *pg)
285339
{
286340
PGRAPHVkState *r = pg->vk_renderer_state;
@@ -295,6 +349,22 @@ static void shader_cache_init(PGRAPHState *pg)
295349
r->shader_cache.init_node = shader_cache_entry_init;
296350
r->shader_cache.compare_nodes = shader_cache_entry_compare;
297351
r->shader_cache.post_node_evict = shader_cache_entry_post_evict;
352+
353+
/* FIXME: Make this configurable */
354+
const size_t shader_module_cache_size = 50 * 1024;
355+
lru_init(&r->shader_module_cache);
356+
r->shader_module_cache_entries =
357+
g_malloc_n(shader_module_cache_size, sizeof(ShaderModuleCacheEntry));
358+
assert(r->shader_module_cache_entries != NULL);
359+
for (int i = 0; i < shader_module_cache_size; i++) {
360+
lru_add_free(&r->shader_module_cache,
361+
&r->shader_module_cache_entries[i].node);
362+
}
363+
364+
r->shader_module_cache.init_node = shader_module_cache_entry_init;
365+
r->shader_module_cache.compare_nodes = shader_module_cache_entry_compare;
366+
r->shader_module_cache.post_node_evict =
367+
shader_module_cache_entry_post_evict;
298368
}
299369

300370
static void shader_cache_finalize(PGRAPHState *pg)
@@ -304,6 +374,21 @@ static void shader_cache_finalize(PGRAPHState *pg)
304374
lru_flush(&r->shader_cache);
305375
g_free(r->shader_cache_entries);
306376
r->shader_cache_entries = NULL;
377+
378+
lru_flush(&r->shader_module_cache);
379+
g_free(r->shader_module_cache_entries);
380+
r->shader_module_cache_entries = NULL;
381+
}
382+
383+
static ShaderModuleInfo *
384+
get_shader_module_for_key(PGRAPHVkState *r, ShaderModuleCacheKey *key)
385+
{
386+
uint64_t hash = fast_hash((void *)key, sizeof(ShaderModuleCacheKey));
387+
LruNode *node = lru_lookup(&r->shader_module_cache, hash, key);
388+
ShaderModuleCacheEntry *module =
389+
container_of(node, ShaderModuleCacheEntry, node);
390+
pgraph_vk_ref_shader_module(module->module_info);
391+
return module->module_info;
307392
}
308393

309394
static ShaderBinding *gen_shaders(PGRAPHState *pg, ShaderState *state)
@@ -328,46 +413,36 @@ static ShaderBinding *gen_shaders(PGRAPHState *pg, ShaderState *state)
328413
/* Ensure numeric values are printed with '.' radix, no grouping */
329414
setlocale(LC_NUMERIC, "C");
330415

331-
MString *geometry_shader_code = pgraph_glsl_gen_geom(
332-
&state->geom, (GenGeomGlslOptions){ .vulkan = true });
333-
if (geometry_shader_code) {
334-
NV2A_VK_DPRINTF("geometry shader: \n%s",
335-
mstring_get_str(geometry_shader_code));
336-
snode->geometry = pgraph_vk_create_shader_module_from_glsl(
337-
r, VK_SHADER_STAGE_GEOMETRY_BIT,
338-
mstring_get_str(geometry_shader_code));
339-
mstring_unref(geometry_shader_code);
416+
ShaderModuleCacheKey key;
417+
418+
bool need_geometry_shader = pgraph_glsl_need_gsh(&state->geom);
419+
if (need_geometry_shader) {
420+
memset(&key, 0, sizeof(key));
421+
key.kind = VK_SHADER_STAGE_GEOMETRY_BIT;
422+
key.state.geom = state->geom;
423+
key.glsl_options.geom = (GenGeomGlslOptions){ .vulkan = true };
424+
snode->geometry = get_shader_module_for_key(r, &key);
340425
} else {
341426
snode->geometry = NULL;
342427
}
343428

344-
MString *vertex_shader_code = pgraph_glsl_gen_vsh(
345-
&state->vsh, (GenVshGlslOptions){
346-
.vulkan = true,
347-
.prefix_outputs = geometry_shader_code != NULL,
348-
.use_push_constants_for_uniform_attrs =
349-
r->use_push_constants_for_uniform_attrs,
350-
.ubo_binding = VSH_UBO_BINDING,
351-
});
352-
NV2A_VK_DPRINTF("vertex shader: \n%s",
353-
mstring_get_str(vertex_shader_code));
354-
snode->vertex = pgraph_vk_create_shader_module_from_glsl(
355-
r, VK_SHADER_STAGE_VERTEX_BIT,
356-
mstring_get_str(vertex_shader_code));
357-
mstring_unref(vertex_shader_code);
358-
359-
MString *fragment_shader_code = pgraph_glsl_gen_psh(
360-
&state->psh, (GenPshGlslOptions){
361-
.vulkan = true,
362-
.ubo_binding = PSH_UBO_BINDING,
363-
.tex_binding = PSH_TEX_BINDING,
364-
});
365-
NV2A_VK_DPRINTF("fragment shader: \n%s",
366-
mstring_get_str(fragment_shader_code));
367-
snode->fragment = pgraph_vk_create_shader_module_from_glsl(
368-
r, VK_SHADER_STAGE_FRAGMENT_BIT,
369-
mstring_get_str(fragment_shader_code));
370-
mstring_unref(fragment_shader_code);
429+
memset(&key, 0, sizeof(key));
430+
key.kind = VK_SHADER_STAGE_VERTEX_BIT;
431+
key.state.vsh = state->vsh;
432+
key.glsl_options.vsh.vulkan = true;
433+
key.glsl_options.vsh.prefix_outputs = need_geometry_shader,
434+
key.glsl_options.vsh.use_push_constants_for_uniform_attrs =
435+
r->use_push_constants_for_uniform_attrs;
436+
key.glsl_options.vsh.ubo_binding = VSH_UBO_BINDING;
437+
snode->vertex = get_shader_module_for_key(r, &key);
438+
439+
memset(&key, 0, sizeof(key));
440+
key.kind = VK_SHADER_STAGE_FRAGMENT_BIT;
441+
key.state.psh = state->psh;
442+
key.glsl_options.psh.vulkan = true;
443+
key.glsl_options.psh.ubo_binding = PSH_UBO_BINDING;
444+
key.glsl_options.psh.tex_binding = PSH_TEX_BINDING;
445+
snode->fragment = get_shader_module_for_key(r, &key);
371446

372447
if (previous_numeric_locale) {
373448
setlocale(LC_NUMERIC, previous_numeric_locale);

0 commit comments

Comments
 (0)