diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index aba59b8f58b..26fed37adac 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -35,6 +35,10 @@ #include #endif +#ifndef _WIN32 +#include +#endif + #include "util/debug.h" #include "util/disk_cache.h" #include "radv_cs.h" @@ -2942,6 +2946,12 @@ radv_parse_vrs_rates(const char *str) return RADV_FORCE_VRS_1x1; } +static const char * +radv_get_force_vrs_config_file(void) +{ + return getenv("RADV_FORCE_VRS_CONFIG_FILE"); +} + static enum radv_force_vrs radv_parse_force_vrs_config_file(const char *config_file) { @@ -2964,6 +2974,98 @@ radv_parse_force_vrs_config_file(const char *config_file) return force_vrs; } +#ifndef _WIN32 + +#define BUF_LEN ((10 * (sizeof(struct inotify_event) + NAME_MAX + 1))) + +static int +radv_notifier_thread_run(void *data) +{ + struct radv_device *device = data; + struct radv_notifier *notifier = &device->notifier; + char buf[BUF_LEN]; + + while (!notifier->quit) { + const char *file = radv_get_force_vrs_config_file(); + struct timespec tm = { .tv_nsec = 100000000 }; /* 1OOms */ + int length, i = 0; + + length = read(notifier->fd, buf, BUF_LEN); + while (i < length) { + struct inotify_event *event = (struct inotify_event *)&buf[i]; + + i += sizeof(struct inotify_event) + event->len; + if (event->mask & IN_MODIFY || event->mask & IN_DELETE_SELF) { + /* Sleep 100ms for editors that use a temporary file and delete the original. */ + thrd_sleep(&tm, NULL); + device->force_vrs = radv_parse_force_vrs_config_file(file); + + fprintf(stderr, "radv: Updated the per-vertex VRS rate to '%d'.\n", device->force_vrs); + + if (event->mask & IN_DELETE_SELF) { + inotify_rm_watch(notifier->fd, notifier->watch); + notifier->watch = inotify_add_watch(notifier->fd, file, IN_MODIFY | IN_DELETE_SELF); + } + } + } + + thrd_sleep(&tm, NULL); + } + + return 0; +} + +#endif + +static int +radv_device_init_notifier(struct radv_device *device) +{ +#ifdef _WIN32 + return true; +#else + struct radv_notifier *notifier = &device->notifier; + const char *file = radv_get_force_vrs_config_file(); + int ret; + + notifier->fd = inotify_init1(IN_NONBLOCK); + if (notifier->fd < 0) + return false; + + notifier->watch = inotify_add_watch(notifier->fd, file, IN_MODIFY | IN_DELETE_SELF); + if (notifier->watch < 0) + goto fail_watch; + + ret = thrd_create(¬ifier->thread, radv_notifier_thread_run, device); + if (ret) + goto fail_thread; + + return true; + +fail_thread: + inotify_rm_watch(notifier->fd, notifier->watch); +fail_watch: + close(notifier->fd); + + return false; +#endif +} + +static void +radv_device_finish_notifier(struct radv_device *device) +{ +#ifndef _WIN32 + struct radv_notifier *notifier = &device->notifier; + + if (!notifier->thread) + return; + + notifier->quit = true; + thrd_join(notifier->thread, NULL); + inotify_rm_watch(notifier->fd, notifier->watch); + close(notifier->fd); +#endif +} + VKAPI_ATTR VkResult VKAPI_CALL radv_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) @@ -3253,9 +3355,13 @@ radv_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCr if (device->physical_device->rad_info.chip_class >= GFX10_3) { if (getenv("RADV_FORCE_VRS_CONFIG_FILE")) { - const char *file = getenv("RADV_FORCE_VRS_CONFIG_FILE"); + const char *file = radv_get_force_vrs_config_file(); device->force_vrs = radv_parse_force_vrs_config_file(file); + + if (!radv_device_init_notifier(device)) { + fprintf(stderr, "radv: Failed to initialize the notifier for RADV_FORCE_VRS_CONFIG_FILE!\n"); + } } else if (getenv("RADV_FORCE_VRS")) { const char *vrs_rates = getenv("RADV_FORCE_VRS"); @@ -3328,6 +3434,7 @@ fail: if (device->gfx_init) device->ws->buffer_destroy(device->ws, device->gfx_init); + radv_device_finish_notifier(device); radv_device_finish_vs_prologs(device); radv_device_finish_border_color(device); diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index b63166653b6..39b006ed838 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -748,6 +748,13 @@ enum radv_force_vrs { RADV_FORCE_VRS_1x2, }; +struct radv_notifier { + int fd; + int watch; + bool quit; + thrd_t thread; +}; + struct radv_device { struct vk_device vk; @@ -849,7 +856,8 @@ struct radv_device { uint64_t allocated_memory_size[VK_MAX_MEMORY_HEAPS]; mtx_t overallocation_mutex; - /* Whether the user forced VRS rates on GFX10.3+. */ + /* RADV_FORCE_VRS. */ + struct radv_notifier notifier; enum radv_force_vrs force_vrs; /* Depth image for VRS when not bound by the app. */