[Native] WindowsDX12 fixes #2 by arosolino · Pull Request #9031 · MonoGame/MonoGame

@tomspilman There is a major bug where a buffer remains on the free list when it doesn't match the exact size.

Not being removed from the free list on this line:

I supplied a fix for now but I noticed that Vulkan takes a different approach to the the free, pending, discarded by using a linked list. Since we are trying to accomplish the same goal on both of these platforms which approach should be taken here?

DX12: MGDX_BufferDiscard

static MGG_Buffer* MGDX_BufferDiscard(MGG_GraphicsDevice* device, MGG_Buffer* buffer)
{
// Get the info we need to find/allocate a new buffer.
auto dataSize = buffer->dataSize;
auto type = buffer->type;
// Add it to the discard list.
device->discarded.push_back(buffer);
// Search for the best fit from the free list.
MGG_Buffer* best = nullptr;
for (int i=0; i < device->free.size(); i++)
{
auto curr = device->free[i];
if (curr->type != type)
continue;
auto currSize = curr->actualSize;
if (currSize < dataSize)
continue;
if (best == nullptr || best->actualSize > currSize)
{
best = curr;
if (currSize == dataSize)
{
device->free[i] = device->free.back();
device->free.pop_back();
break;
}
}
}
// We didn't find a match, so allocate a new one.
if (best == nullptr)
best = MGG_Buffer_Create(device, type, dataSize);
best->dataSize = dataSize;
return best;
}

Vulkan: MGVK_BufferDiscard

static MGG_Buffer* MGVK_BufferDiscard(MGG_GraphicsDevice* device, MGG_Buffer* buffer)
{
// Get the info we need to find/allocate a new buffer.
auto dataSize = buffer->dataSize;
auto type = buffer->type;
// Discard the current buffer.
assert(buffer->next == nullptr);
buffer->next = device->discarded;
device->discarded = buffer;
buffer = nullptr;
// Search for the best fit from the free list.
MGG_Buffer** curr = &device->free;
MGG_Buffer** best = nullptr;
while (*curr != nullptr)
{
if ((*curr)->type == type)
{
auto currSize = (*curr)->actualSize;
if (currSize >= dataSize)
{
if (best == nullptr || (*best)->actualSize > currSize)
{
best = curr;
if (currSize == dataSize)
break;
}
}
}
curr = &(*curr)->next;
}
// Did we find a match?
if (best != nullptr)
{
buffer = *best;
*best = buffer->next;
buffer->next = nullptr;
buffer->dataSize = dataSize;
//buffer->dirtyMin = 0;
//buffer->dirtyMax = 0;
return buffer;
}
// We didn't find a match, so allocate a new one.
buffer = MGG_Buffer_Create(device, type, dataSize);
return buffer;
}