From 8c0646159f7d8f8ec0f5ccca448583a3eac3e562 Mon Sep 17 00:00:00 2001 From: Spoike Date: Thu, 1 Jul 2021 01:16:11 +0000 Subject: [PATCH] Try to make the vulkan renderer more robust on nvidia. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5925 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/gl/gl_shader.c | 4 +-- engine/gl/gl_vidlinuxglx.c | 4 +++ engine/vk/vk_init.c | 64 +++++++++++++++++++++++++++++++------- engine/vk/vkrenderer.h | 10 ++++++ 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 03b315ff9..29ca02341 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -4118,9 +4118,9 @@ qboolean Shader_Init (void) else { memset(wibuf, 0xff, sizeof(wibuf)); - r_whiteimage = R_LoadTexture("$whiteimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA); + r_whiteimage = R_LoadTexture("$whiteimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA|IF_NOPURGE); memset(wibuf, 0, sizeof(wibuf)); - r_blackimage = R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA); + r_blackimage = R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA|IF_NOPURGE); } Shader_NeedReload(true); diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index ae82d6aa5..12d206b8d 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -103,6 +103,7 @@ static Window vid_root; #ifdef GLQUAKE static GLXContext ctx = NULL; #endif +extern qboolean vid_isfullscreen; static int scrnum; static long vid_x_eventmask; static enum @@ -4430,6 +4431,7 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int x11.pXMoveResizeWindow(vid_dpy, vid_window, fullscreenx, fullscreeny, fullscreenwidth, fullscreenheight); if (fullscreenflags) fullscreenflags |= FULLSCREEN_ACTIVE; + vid_isfullscreen = !!(fullscreenflags &FULLSCREEN_ACTIVE); if (X11_CheckFeature("xi2", true) && XI2_Init()) { @@ -4891,6 +4893,7 @@ void Sys_SendKeyEvents(void) } if (fullscreenflags) fullscreenflags |= FULLSCREEN_ACTIVE; + vid_isfullscreen = !!(fullscreenflags &FULLSCREEN_ACTIVE); } if (modeswitchpending < 0) { @@ -4923,6 +4926,7 @@ void Sys_SendKeyEvents(void) x11.pXMapWindow(vid_dpy, vid_decoywindow); } fullscreenflags &= ~FULLSCREEN_ACTIVE; + vid_isfullscreen = !!(fullscreenflags &FULLSCREEN_ACTIVE); } } modeswitchpending = 0; diff --git a/engine/vk/vk_init.c b/engine/vk/vk_init.c index 6cfd48c76..649845e98 100644 --- a/engine/vk/vk_init.c +++ b/engine/vk/vk_init.c @@ -48,6 +48,7 @@ void VK_RegisterVulkanCvars(void) #endif } void R2D_Console_Resize(void); +static void VK_DestroySampler(VkSampler s); extern qboolean scr_con_forcedraw; @@ -408,7 +409,7 @@ void VK_DestroyVkTexture(vk_image_t *img) if (!img) return; if (img->sampler) - vkDestroySampler(vk.device, img->sampler, vkallocationcb); + VK_DestroySampler(img->sampler); if (img->view) vkDestroyImageView(vk.device, img->view, vkallocationcb); if (img->image) @@ -880,6 +881,8 @@ static qboolean VK_CreateSwapChain(void) free(presentmode); free(surffmts); + if (vid_isfullscreen) //nvidia really doesn't like this. its fine when windowed though. + VK_DestroySwapChain(); swapinfo.oldSwapchain = vk.swapchain; newvkswapchain = VK_NULL_HANDLE; @@ -1149,13 +1152,38 @@ void VK_Draw_Shutdown(void) Image_Shutdown(); } +static void VK_DestroySampler(VkSampler s) +{ + struct vksamplers_s *ref; + for (ref = vk.samplers; ref; ref = ref->next) + { + if (ref->samp == s) + { + if (--ref->usages == 0) + { + vkDestroySampler(vk.device, ref->samp, vkallocationcb); + *ref->link = ref->next; + if (ref->next) + ref->next->link = ref->link; + Z_Free(ref); + } + } + } +} +static void VK_DestroySampler_FrameEnd(void *w) +{ + VK_DestroySampler(*(VkSampler*)w); +} + void VK_CreateSampler(unsigned int flags, vk_image_t *img) { + struct vksamplers_s *ref; qboolean clamptoedge = flags & IF_CLAMP; VkSamplerCreateInfo lmsampinfo = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; + if (img->sampler) - vkDestroySampler(vk.device, img->sampler, vkallocationcb); + VK_DestroySampler(img->sampler); if (flags & IF_LINEAR) { @@ -1196,14 +1224,28 @@ void VK_CreateSampler(unsigned int flags, vk_image_t *img) lmsampinfo.maxLod = vk.mipcap[1]; lmsampinfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; lmsampinfo.unnormalizedCoordinates = VK_FALSE; - VkAssert(vkCreateSampler(vk.device, &lmsampinfo, NULL, &img->sampler)); + + for (ref = vk.samplers; ref; ref = ref->next) + if (ref->flags == flags) + if (!memcmp(&ref->props, &lmsampinfo, sizeof(lmsampinfo))) + break; + + if (!ref) + { + ref = Z_Malloc(sizeof(*ref)); + ref->flags = flags; + ref->props = lmsampinfo; + ref->next = vk.samplers; + ref->link = &vk.samplers; + if (vk.samplers) + vk.samplers->link = &ref->next; + vk.samplers = ref; + VkAssert(vkCreateSampler(vk.device, &ref->props, NULL, &ref->samp)); + } + ref->usages++; + img->sampler = ref->samp; } -static void VK_DestroySampler(void *w) -{ - VkSampler s = *(VkSampler*)w; - vkDestroySampler(vk.device, s, vkallocationcb); -} void VK_UpdateFiltering(image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float lodbias, float anis) { uint32_t i; @@ -1223,7 +1265,7 @@ void VK_UpdateFiltering(image_t *imagelist, int filtermip[3], int filterpic[3], if (imagelist->vkimage->sampler) { //the sampler might still be in use, so clean it up at the end of the frame. //all this to avoid syncing all the queues... - VK_AtFrameEnd(VK_DestroySampler, &imagelist->vkimage->sampler, sizeof(imagelist->vkimage->sampler)); + VK_AtFrameEnd(VK_DestroySampler_FrameEnd, &imagelist->vkimage->sampler, sizeof(imagelist->vkimage->sampler)); imagelist->vkimage->sampler = VK_NULL_HANDLE; } VK_CreateSampler(imagelist->flags, imagelist->vkimage); @@ -2118,10 +2160,10 @@ void VK_DestroyTexture (texid_t tex) void VK_R_Init (void) { uint32_t white[6] = {~0u,~0u,~0u,~0u,~0u,~0u}; - r_blackcubeimage = Image_CreateTexture("***blackcube***", NULL, IF_NEAREST|IF_TEXTYPE_CUBE); + r_blackcubeimage = Image_CreateTexture("***blackcube***", NULL, IF_NEAREST|IF_TEXTYPE_CUBE|IF_NOPURGE); Image_Upload(r_blackcubeimage, TF_RGBX32, NULL, NULL, 1, 1, 6, IF_NEAREST|IF_NOMIPMAP|IF_NOGAMMA|IF_TEXTYPE_CUBE); - r_whitecubeimage = Image_CreateTexture("***whitecube***", NULL, IF_NEAREST|IF_TEXTYPE_CUBE); + r_whitecubeimage = Image_CreateTexture("***whitecube***", NULL, IF_NEAREST|IF_TEXTYPE_CUBE|IF_NOPURGE); Image_Upload(r_whitecubeimage, TF_RGBX32, white, NULL, 1, 1, 6, IF_NEAREST|IF_NOMIPMAP|IF_NOGAMMA|IF_TEXTYPE_CUBE); } void VK_R_DeInit (void) diff --git a/engine/vk/vkrenderer.h b/engine/vk/vkrenderer.h index ac33429a4..121db2ac4 100644 --- a/engine/vk/vkrenderer.h +++ b/engine/vk/vkrenderer.h @@ -395,6 +395,16 @@ extern struct vulkaninfo_s qboolean neednewswapchain; //something changed that invalidates the old one. qboolean devicelost; //we seriously fucked up somewhere. or the gpu is shite. + struct vksamplers_s + { + VkSampler samp; + unsigned int usages; //refcounted. + unsigned int flags; + VkSamplerCreateInfo props; + struct vksamplers_s *next; + struct vksamplers_s **link; + } *samplers; + struct vkwork_s { struct vkwork_s *next;