radv: allow applications to dynamically change RADV_FORCE_VRS

This introduces inotify support in RADV to handle changes from the
RADV_FORCE_VRS_CONFIG_FILE. This is similar to MangoHUD. I'm personally
not sure it's the best solution but let's try this way and change it
later if we have issues (or if we have a lightweight solution).

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14713>
This commit is contained in:
Samuel Pitoiset 2022-01-25 17:05:17 +01:00
parent 5e2d9202e2
commit c50557d961
2 changed files with 117 additions and 2 deletions

View file

@ -35,6 +35,10 @@
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#endif #endif
#ifndef _WIN32
#include <sys/inotify.h>
#endif
#include "util/debug.h" #include "util/debug.h"
#include "util/disk_cache.h" #include "util/disk_cache.h"
#include "radv_cs.h" #include "radv_cs.h"
@ -2942,6 +2946,12 @@ radv_parse_vrs_rates(const char *str)
return RADV_FORCE_VRS_1x1; 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 static enum radv_force_vrs
radv_parse_force_vrs_config_file(const char *config_file) 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; 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(&notifier->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 VKAPI_ATTR VkResult VKAPI_CALL
radv_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, radv_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) 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 (device->physical_device->rad_info.chip_class >= GFX10_3) {
if (getenv("RADV_FORCE_VRS_CONFIG_FILE")) { 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); 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")) { } else if (getenv("RADV_FORCE_VRS")) {
const char *vrs_rates = getenv("RADV_FORCE_VRS"); const char *vrs_rates = getenv("RADV_FORCE_VRS");
@ -3328,6 +3434,7 @@ fail:
if (device->gfx_init) if (device->gfx_init)
device->ws->buffer_destroy(device->ws, 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_vs_prologs(device);
radv_device_finish_border_color(device); radv_device_finish_border_color(device);

View file

@ -748,6 +748,13 @@ enum radv_force_vrs {
RADV_FORCE_VRS_1x2, RADV_FORCE_VRS_1x2,
}; };
struct radv_notifier {
int fd;
int watch;
bool quit;
thrd_t thread;
};
struct radv_device { struct radv_device {
struct vk_device vk; struct vk_device vk;
@ -849,7 +856,8 @@ struct radv_device {
uint64_t allocated_memory_size[VK_MAX_MEMORY_HEAPS]; uint64_t allocated_memory_size[VK_MAX_MEMORY_HEAPS];
mtx_t overallocation_mutex; 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; enum radv_force_vrs force_vrs;
/* Depth image for VRS when not bound by the app. */ /* Depth image for VRS when not bound by the app. */