diff --git a/docs/envvars.rst b/docs/envvars.rst index e58ed0d2de4..fc894ce7ec0 100644 --- a/docs/envvars.rst +++ b/docs/envvars.rst @@ -1347,6 +1347,8 @@ RADV driver environment variables enable local BOs ``nggc`` enable NGG culling on GPUs where it's not enabled by default (GFX10.1 only). + ``nircache`` + cache per-stage NIR for graphics pipelines ``nosam`` disable optimizations that get enabled when all VRAM is CPU visible. ``pswave32`` diff --git a/src/amd/vulkan/radv_debug.h b/src/amd/vulkan/radv_debug.h index 6dccb489381..591bba3204b 100644 --- a/src/amd/vulkan/radv_debug.h +++ b/src/amd/vulkan/radv_debug.h @@ -91,6 +91,7 @@ enum { RADV_PERFTEST_GS_FAST_LAUNCH_2 = 1u << 13, RADV_PERFTEST_TRANSFER_QUEUE = 1u << 14, RADV_PERFTEST_SHADER_OBJECT = 1u << 15, + RADV_PERFTEST_NIR_CACHE = 1u << 16, }; bool radv_init_trace(struct radv_device *device); diff --git a/src/amd/vulkan/radv_instance.c b/src/amd/vulkan/radv_instance.c index abbda6c82e0..d5b2453a9c8 100644 --- a/src/amd/vulkan/radv_instance.c +++ b/src/amd/vulkan/radv_instance.c @@ -102,6 +102,7 @@ static const struct debug_control radv_perftest_options[] = {{"localbos", RADV_P {"gsfastlaunch2", RADV_PERFTEST_GS_FAST_LAUNCH_2}, {"transfer_queue", RADV_PERFTEST_TRANSFER_QUEUE}, {"shader_object", RADV_PERFTEST_SHADER_OBJECT}, + {"nircache", RADV_PERFTEST_NIR_CACHE}, {NULL, 0}}; const char * diff --git a/src/amd/vulkan/radv_pipeline_cache.c b/src/amd/vulkan/radv_pipeline_cache.c index c0212aeaa52..01117a79648 100644 --- a/src/amd/vulkan/radv_pipeline_cache.c +++ b/src/amd/vulkan/radv_pipeline_cache.c @@ -73,6 +73,18 @@ radv_hash_shaders(const struct radv_device *device, unsigned char *hash, const s _mesa_sha1_final(&ctx, hash); } +void +radv_hash_graphics_spirv_to_nir(blake3_hash hash, const struct radv_shader_stage *stage, + const struct radv_spirv_to_nir_options *options) +{ + struct mesa_blake3 ctx; + _mesa_blake3_init(&ctx); + _mesa_blake3_update(&ctx, &stage->key, sizeof(stage->key)); + _mesa_blake3_update(&ctx, options, sizeof(*options)); + _mesa_blake3_update(&ctx, stage->shader_sha1, sizeof(stage->shader_sha1)); + _mesa_blake3_final(&ctx, hash); +} + void radv_hash_rt_shaders(const struct radv_device *device, unsigned char *hash, const struct radv_ray_tracing_stage *stages, const VkRayTracingPipelineCreateInfoKHR *pCreateInfo, const struct radv_ray_tracing_group *groups) @@ -516,6 +528,33 @@ radv_ray_tracing_pipeline_cache_insert(struct radv_device *device, struct vk_pip pipeline->base.base.cache_object = vk_pipeline_cache_add_object(cache, &pipeline_obj->base); } +nir_shader * +radv_pipeline_cache_lookup_nir(struct radv_device *device, struct vk_pipeline_cache *cache, gl_shader_stage stage, + const blake3_hash key) +{ + if (radv_is_cache_disabled(device)) + return NULL; + + if (!cache) + cache = device->mem_cache; + + return vk_pipeline_cache_lookup_nir(cache, key, sizeof(blake3_hash), &device->physical_device->nir_options[stage], + NULL, NULL); +} + +void +radv_pipeline_cache_insert_nir(struct radv_device *device, struct vk_pipeline_cache *cache, const blake3_hash key, + const nir_shader *nir) +{ + if (radv_is_cache_disabled(device)) + return; + + if (!cache) + cache = device->mem_cache; + + vk_pipeline_cache_add_nir(cache, key, sizeof(blake3_hash), nir); +} + struct vk_pipeline_cache_object * radv_pipeline_cache_lookup_nir_handle(struct radv_device *device, struct vk_pipeline_cache *cache, const uint8_t *sha1) { diff --git a/src/amd/vulkan/radv_pipeline_graphics.c b/src/amd/vulkan/radv_pipeline_graphics.c index e1d9dae6208..96b6c00c284 100644 --- a/src/amd/vulkan/radv_pipeline_graphics.c +++ b/src/amd/vulkan/radv_pipeline_graphics.c @@ -2460,6 +2460,7 @@ radv_graphics_shaders_compile(struct radv_device *device, struct vk_pipeline_cac struct radv_shader **shaders, struct radv_shader_binary **binaries, struct radv_shader **gs_copy_shader, struct radv_shader_binary **gs_copy_binary) { + const bool nir_cache = device->instance->perftest_flags & RADV_PERFTEST_NIR_CACHE; for (unsigned s = 0; s < MESA_VULKAN_SHADER_STAGES; s++) { if (!stages[s].entrypoint) continue; @@ -2473,7 +2474,17 @@ radv_graphics_shaders_compile(struct radv_device *device, struct vk_pipeline_cac .fix_dual_src_mrt1_export = gfx_state->ps.epilog.mrt0_is_dual_src && device->instance->drirc.dual_color_blend_by_location, }; - stages[s].nir = radv_shader_spirv_to_nir(device, &stages[s], &options, is_internal); + blake3_hash key; + + if (nir_cache) { + radv_hash_graphics_spirv_to_nir(key, &stages[s], &options); + stages[s].nir = radv_pipeline_cache_lookup_nir(device, cache, s, key); + } + if (!stages[s].nir) { + stages[s].nir = radv_shader_spirv_to_nir(device, &stages[s], &options, is_internal); + if (nir_cache) + radv_pipeline_cache_insert_nir(device, cache, key, stages[s].nir); + } } stages[s].feedback.duration += os_time_get_nano() - stage_start; diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 40da3174d23..c96b07d8ba5 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -417,6 +417,12 @@ void radv_ray_tracing_pipeline_cache_insert(struct radv_device *device, struct v struct radv_ray_tracing_pipeline *pipeline, unsigned num_stages, const unsigned char *sha1); +nir_shader *radv_pipeline_cache_lookup_nir(struct radv_device *device, struct vk_pipeline_cache *cache, + gl_shader_stage stage, const blake3_hash key); + +void radv_pipeline_cache_insert_nir(struct radv_device *device, struct vk_pipeline_cache *cache, const blake3_hash key, + const nir_shader *nir); + struct vk_pipeline_cache_object *radv_pipeline_cache_lookup_nir_handle(struct radv_device *device, struct vk_pipeline_cache *cache, const unsigned char *sha1); @@ -2053,6 +2059,9 @@ struct radv_ray_tracing_group; void radv_pipeline_stage_init(const VkPipelineShaderStageCreateInfo *sinfo, const struct radv_pipeline_layout *layout, const struct radv_shader_stage_key *stage_key, struct radv_shader_stage *out_stage); +void radv_hash_graphics_spirv_to_nir(blake3_hash hash, const struct radv_shader_stage *stage, + const struct radv_spirv_to_nir_options *options); + void radv_hash_shaders(const struct radv_device *device, unsigned char *hash, const struct radv_shader_stage *stages, uint32_t stage_count, const struct radv_pipeline_layout *layout, const struct radv_graphics_state_key *gfx_state);