fix: add VkSampler cache to prevent sampler exhaustion crash

Validation layers revealed 9965 VkSamplers allocated against a device
limit of 4000 — every VkTexture created its own sampler even when
configurations were identical. This exhausted NVIDIA's sampler pool
and caused intermittent SIGSEGV in vkCmdBeginRenderPass.

Add a thread-safe sampler cache in VkContext that deduplicates samplers
by FNV-1a hash of all 14 VkSamplerCreateInfo fields. All texture,
render target, renderer, water, and loading screen sampler creation
now goes through getOrCreateSampler(). Textures set ownsSampler_=false
so shared samplers aren't double-freed.

Also auto-disable anisotropy in the cache when the physical device
doesn't support the samplerAnisotropy feature, fixing the validation
error VUID-VkSamplerCreateInfo-anisotropyEnable-01070.
This commit is contained in:
Kelsi 2026-03-24 11:44:54 -07:00
parent 1556559211
commit a152023e5e
10 changed files with 194 additions and 40 deletions

View file

@ -915,7 +915,7 @@ bool AuthScreen::loadBackgroundImage() {
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
vkCreateSampler(device, &samplerInfo, nullptr, &bgSampler);
bgSampler = bgVkCtx->getOrCreateSampler(samplerInfo);
}
bgDescriptorSet = ImGui_ImplVulkan_AddTexture(bgSampler, bgImageView,
@ -930,7 +930,7 @@ void AuthScreen::destroyBackgroundImage() {
VkDevice device = bgVkCtx->getDevice();
vkDeviceWaitIdle(device);
if (bgDescriptorSet) { ImGui_ImplVulkan_RemoveTexture(bgDescriptorSet); bgDescriptorSet = VK_NULL_HANDLE; }
if (bgSampler) { vkDestroySampler(device, bgSampler, nullptr); bgSampler = VK_NULL_HANDLE; }
bgSampler = VK_NULL_HANDLE; // Owned by VkContext sampler cache
if (bgImageView) { vkDestroyImageView(device, bgImageView, nullptr); bgImageView = VK_NULL_HANDLE; }
if (bgImage) { vkDestroyImage(device, bgImage, nullptr); bgImage = VK_NULL_HANDLE; }
if (bgMemory) { vkFreeMemory(device, bgMemory, nullptr); bgMemory = VK_NULL_HANDLE; }