mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-14 00:23:50 +00:00
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:
parent
1556559211
commit
a152023e5e
10 changed files with 194 additions and 40 deletions
|
|
@ -49,7 +49,7 @@ bool VkRenderTarget::create(VkContext& ctx, uint32_t width, uint32_t height,
|
|||
}
|
||||
}
|
||||
|
||||
// Create sampler (linear filtering, clamp to edge)
|
||||
// Create sampler (linear filtering, clamp to edge) via cache
|
||||
VkSamplerCreateInfo samplerInfo{};
|
||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||
|
|
@ -61,11 +61,13 @@ bool VkRenderTarget::create(VkContext& ctx, uint32_t width, uint32_t height,
|
|||
samplerInfo.minLod = 0.0f;
|
||||
samplerInfo.maxLod = 0.0f;
|
||||
|
||||
if (vkCreateSampler(device, &samplerInfo, nullptr, &sampler_) != VK_SUCCESS) {
|
||||
sampler_ = ctx.getOrCreateSampler(samplerInfo);
|
||||
if (sampler_ == VK_NULL_HANDLE) {
|
||||
LOG_ERROR("VkRenderTarget: failed to create sampler");
|
||||
destroy(device, allocator);
|
||||
return false;
|
||||
}
|
||||
ownsSampler_ = false;
|
||||
|
||||
// Create render pass
|
||||
if (useMSAA) {
|
||||
|
|
@ -259,10 +261,11 @@ void VkRenderTarget::destroy(VkDevice device, VmaAllocator allocator) {
|
|||
vkDestroyRenderPass(device, renderPass_, nullptr);
|
||||
renderPass_ = VK_NULL_HANDLE;
|
||||
}
|
||||
if (sampler_) {
|
||||
if (sampler_ && ownsSampler_) {
|
||||
vkDestroySampler(device, sampler_, nullptr);
|
||||
sampler_ = VK_NULL_HANDLE;
|
||||
}
|
||||
sampler_ = VK_NULL_HANDLE;
|
||||
ownsSampler_ = true;
|
||||
destroyImage(device, allocator, resolveImage_);
|
||||
destroyImage(device, allocator, depthImage_);
|
||||
destroyImage(device, allocator, colorImage_);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue