mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Try a smaller allocation before giving up on a texture upload when the video memory is used up.
On an integrated Radeon 890M the ASTC scratch buffer failed to allocate and then a staging buffer ended the run. The scratch asks for 32 MiB whatever the upload needs, and the staging pool grows only in 64 MiB blocks of one memory type. When the device reports it is out of memory, the scratch is now tried again at the size the upload needs, and a staging buffer that does not fit the pool is tried again outside it with the same mapping, where a smaller block or another host-visible type may still have room. The menu's own upload flushes what it wrote, since such a buffer may lie in memory that is not coherent. Built and run through the memory probe (96 GPU checks pass); the out-of-memory paths themselves were not reached here. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
@@ -134,6 +134,11 @@ static int upload_rgba(Art &a, const uint8_t *rgba, uint32_t w, uint32_t h, uint
|
||||
}
|
||||
memcpy(map, chain, (size_t)bytes);
|
||||
free(chain);
|
||||
// The batch flushes its own staging buffers. This one is caller-owned and can be noncoherent.
|
||||
if (vmaFlushAllocation(c->vma, sa, 0, bytes) != VK_SUCCESS) {
|
||||
vmaDestroyBuffer(c->vma, sb, sa);
|
||||
return art_free(a), 0;
|
||||
}
|
||||
VkCommandBuffer cb = vk_upload_begin();
|
||||
VkImageMemoryBarrier2 b = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2};
|
||||
b.srcStageMask = VK_PIPELINE_STAGE_2_NONE;
|
||||
|
||||
@@ -483,13 +483,19 @@ static VkBuffer scratch_get(VkCtx *c, VkCommandBuffer cb, VkDeviceSize need, int
|
||||
VmaAllocationCreateInfo aci = {.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE};
|
||||
VkBuffer b;
|
||||
VmaAllocation a;
|
||||
if (vmaCreateBuffer(c->vma, &bi, &aci, &b, &a, NULL) != VK_SUCCESS) {
|
||||
VkResult r = vmaCreateBuffer(c->vma, &bi, &aci, &b, &a, NULL);
|
||||
if (r == VK_ERROR_OUT_OF_DEVICE_MEMORY && bi.size > need) {
|
||||
// The usual scratch leaves room for later textures. This upload can still fit without the spare bytes.
|
||||
bi.size = need;
|
||||
r = vmaCreateBuffer(c->vma, &bi, &aci, &b, &a, NULL);
|
||||
}
|
||||
if (r != VK_SUCCESS) {
|
||||
plat_mutex_unlock(&g_lock);
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
// the old one may still be read by its command buffer: freed once the batches recorded so far completed
|
||||
if (S.buf && S.dev == c->device) vk_defer_buffer(S.buf, S.alloc);
|
||||
S.buf = b, S.alloc = a, S.size = size, S.dev = c->device;
|
||||
S.buf = b, S.alloc = a, S.size = bi.size, S.dev = c->device;
|
||||
n_scratch_new++;
|
||||
vk_texstat_time(VK_TS_SCRATCH, t0);
|
||||
} else {
|
||||
|
||||
@@ -3679,6 +3679,12 @@ void *vk_staging(VkDeviceSize size, VkBuffer *buf, VmaAllocation *alloc) {
|
||||
VkBuffer b;
|
||||
VmaAllocation a;
|
||||
VkResult r = vmaCreateBuffer(c->vma, &bi, &aci, &b, &a, &info);
|
||||
if (r == VK_ERROR_OUT_OF_DEVICE_MEMORY && aci.pool) {
|
||||
// The staging pool can grow only in 64 MiB blocks of its one memory type. A smaller allocation may
|
||||
// still fit in a default block or another host-visible type. Keep the same mapping requirements.
|
||||
aci.pool = NULL;
|
||||
r = vmaCreateBuffer(c->vma, &bi, &aci, &b, &a, &info);
|
||||
}
|
||||
if (r != VK_SUCCESS) rt_fatal("vk: staging buffer of %llu bytes failed (%d)", (unsigned long long)size, (int)r);
|
||||
vk_texstat_add(VK_TS_STG_NEW, 1, bi.size);
|
||||
*buf = b;
|
||||
|
||||
Reference in New Issue
Block a user