[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; | |
| } |