mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
vulkan: flush allocations if needed
There is no guarantee that the created buffer is actually host coherent. If it is not we have to manually flush it.
This commit is contained in:
@@ -102,6 +102,13 @@ bool Buffer::loadVolatile()
|
||||
throw love::Exception("failed to create texel buffer view");
|
||||
}
|
||||
|
||||
VkMemoryPropertyFlags memoryProperties;
|
||||
vmaGetAllocationMemoryProperties(allocator, allocation, &memoryProperties);
|
||||
if (memoryProperties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
||||
coherent = true;
|
||||
else
|
||||
coherent = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -172,6 +179,9 @@ bool Buffer::fill(size_t offset, size_t size, const void *data)
|
||||
{
|
||||
void *dst = (void*)((char*)allocInfo.pMappedData + offset);
|
||||
memcpy(dst, data, size);
|
||||
|
||||
if (!coherent)
|
||||
vmaFlushAllocation(allocator, allocation, offset, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -193,6 +203,11 @@ bool Buffer::fill(size_t offset, size_t size, const void *data)
|
||||
|
||||
memcpy(fillAllocInfo.pMappedData, data, size);
|
||||
|
||||
VkMemoryPropertyFlags memoryProperties;
|
||||
vmaGetAllocationMemoryProperties(allocator, fillAllocation, &memoryProperties);
|
||||
if (!(memoryProperties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
|
||||
vmaFlushAllocation(allocator, fillAllocation, 0, size);
|
||||
|
||||
VkBufferCopy bufferCopy{};
|
||||
bufferCopy.srcOffset = 0;
|
||||
bufferCopy.dstOffset = offset;
|
||||
@@ -209,13 +224,23 @@ bool Buffer::fill(size_t offset, size_t size, const void *data)
|
||||
|
||||
void Buffer::unmap(size_t usedoffset, size_t usedsize)
|
||||
{
|
||||
if (dataUsage != BUFFERDATAUSAGE_READBACK)
|
||||
if (dataUsage == BUFFERDATAUSAGE_READBACK)
|
||||
{
|
||||
if (!coherent)
|
||||
vmaFlushAllocation(allocator, allocation, usedoffset, usedsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
VkBufferCopy bufferCopy{};
|
||||
bufferCopy.srcOffset = usedoffset - mappedRange.getOffset();
|
||||
bufferCopy.dstOffset = usedoffset;
|
||||
bufferCopy.size = usedsize;
|
||||
|
||||
VkMemoryPropertyFlags memoryProperties;
|
||||
vmaGetAllocationMemoryProperties(allocator, stagingAllocation, &memoryProperties);
|
||||
if (!(memoryProperties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
|
||||
vmaFlushAllocation(allocator, stagingAllocation, bufferCopy.srcOffset, usedsize);
|
||||
|
||||
vkCmdCopyBuffer(vgfx->getCommandBufferForDataTransfer(), stagingBuffer, buffer, 1, &bufferCopy);
|
||||
|
||||
vgfx->queueCleanUp([allocator = allocator, stagingBuffer = stagingBuffer, stagingAllocation = stagingAllocation]() {
|
||||
|
||||
@@ -69,6 +69,7 @@ private:
|
||||
VmaAllocationInfo stagingAllocInfo;
|
||||
BufferUsageFlags usageFlags;
|
||||
Range mappedRange;
|
||||
bool coherent;
|
||||
};
|
||||
|
||||
} // vulkan
|
||||
|
||||
@@ -1557,7 +1557,7 @@ void Graphics::createLogicalDevice()
|
||||
optionalDeviceFeatures.memoryBudget = false;
|
||||
if (optionalDeviceFeatures.spirv14 && !optionalDeviceFeatures.shaderFloatControls)
|
||||
optionalDeviceFeatures.spirv14 = false;
|
||||
if (optionalDeviceFeatures.spirv14 && vulkanApiVersion < VK_MAKE_API_VERSION(0, 1, 1, 0))
|
||||
if (optionalDeviceFeatures.spirv14 && vulkanApiVersion < VK_API_VERSION_1_1)
|
||||
optionalDeviceFeatures.spirv14 = false;
|
||||
|
||||
VkPhysicalDeviceFeatures deviceFeatures{};
|
||||
|
||||
@@ -65,6 +65,13 @@ bool StreamBuffer::loadVolatile()
|
||||
if (vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, &allocInfo) != VK_SUCCESS)
|
||||
throw love::Exception("Cannot create stream buffer: out of graphics memory.");
|
||||
|
||||
VkMemoryPropertyFlags properties;
|
||||
vmaGetAllocationMemoryProperties(allocator, allocation, &properties);
|
||||
if (properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
||||
coherent = true;
|
||||
else
|
||||
coherent = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -99,9 +106,13 @@ love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t /*minsize*/)
|
||||
return info;
|
||||
}
|
||||
|
||||
size_t StreamBuffer::unmap(size_t /*usedSize*/)
|
||||
size_t StreamBuffer::unmap(size_t usedSize)
|
||||
{
|
||||
size_t offset = (frameIndex * bufferSize) + frameGPUReadOffset;
|
||||
|
||||
if (!coherent)
|
||||
vmaFlushAllocation(allocator, allocation, offset, usedSize);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ private:
|
||||
VmaAllocationInfo allocInfo;
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
int frameIndex = 0;
|
||||
bool coherent;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -23,23 +23,6 @@
|
||||
#define VK_NO_PROTOTYPES
|
||||
#include "libraries/vulkanheaders/vulkan.h"
|
||||
|
||||
#ifndef VK_MAKE_API_VERSION
|
||||
#define VK_MAKE_API_VERSION(variant, major, minor, patch) \
|
||||
((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))
|
||||
#endif
|
||||
|
||||
#ifndef VK_API_VERSION_MAJOR
|
||||
#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU)
|
||||
#endif
|
||||
|
||||
#ifndef VK_API_VERSION_MINOR
|
||||
#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU)
|
||||
#endif
|
||||
|
||||
#ifndef VK_API_VERSION_PATCH
|
||||
#define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU)
|
||||
#endif
|
||||
|
||||
#include "libraries/volk/volk.h"
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
|
||||
|
||||
Reference in New Issue
Block a user