Browse Source

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.

niki 2 years ago
parent
commit
ecc272e0ca

+ 26 - 1
src/modules/graphics/vulkan/Buffer.cpp

@@ -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]() {

+ 1 - 0
src/modules/graphics/vulkan/Buffer.h

@@ -69,6 +69,7 @@ private:
 	VmaAllocationInfo stagingAllocInfo;
 	BufferUsageFlags usageFlags;
 	Range mappedRange;
+	bool coherent;
 };
 
 } // vulkan

+ 1 - 1
src/modules/graphics/vulkan/Graphics.cpp

@@ -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{};

+ 12 - 1
src/modules/graphics/vulkan/StreamBuffer.cpp

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

+ 1 - 0
src/modules/graphics/vulkan/StreamBuffer.h

@@ -62,6 +62,7 @@ private:
 	VmaAllocationInfo allocInfo;
 	VkBuffer buffer = VK_NULL_HANDLE;
 	int frameIndex = 0;
+	bool coherent;
 
 };
 

+ 0 - 17
src/modules/graphics/vulkan/VulkanWrapper.h

@@ -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