Browse Source

Finished Vulkan hardware buffer implementation

BearishSun 9 years ago
parent
commit
90a05366f1
23 changed files with 130 additions and 42 deletions
  1. 7 3
      Source/BansheeCore/Include/BsHardwareBuffer.h
  2. 1 1
      Source/BansheeD3D11RenderAPI/Include/BsD3D11GpuBuffer.h
  3. 1 1
      Source/BansheeD3D11RenderAPI/Include/BsD3D11HardwareBuffer.h
  4. 1 1
      Source/BansheeD3D11RenderAPI/Include/BsD3D11IndexBuffer.h
  5. 1 1
      Source/BansheeD3D11RenderAPI/Include/BsD3D11VertexBuffer.h
  6. 1 1
      Source/BansheeD3D11RenderAPI/Source/BsD3D11GpuBuffer.cpp
  7. 2 2
      Source/BansheeD3D11RenderAPI/Source/BsD3D11HardwareBuffer.cpp
  8. 2 2
      Source/BansheeD3D11RenderAPI/Source/BsD3D11IndexBuffer.cpp
  9. 1 1
      Source/BansheeD3D11RenderAPI/Source/BsD3D11VertexBuffer.cpp
  10. 1 1
      Source/BansheeGLRenderAPI/Include/BsGLGpuBuffer.h
  11. 1 1
      Source/BansheeGLRenderAPI/Include/BsGLIndexBuffer.h
  12. 1 1
      Source/BansheeGLRenderAPI/Include/BsGLVertexBuffer.h
  13. 1 1
      Source/BansheeGLRenderAPI/Source/BsGLGpuBuffer.cpp
  14. 2 2
      Source/BansheeGLRenderAPI/Source/BsGLIndexBuffer.cpp
  15. 2 2
      Source/BansheeGLRenderAPI/Source/BsGLVertexBuffer.cpp
  16. 1 1
      Source/BansheeVulkanRenderAPI/Include/BsVulkanGpuBuffer.h
  17. 3 2
      Source/BansheeVulkanRenderAPI/Include/BsVulkanHardwareBuffer.h
  18. 1 1
      Source/BansheeVulkanRenderAPI/Include/BsVulkanIndexBuffer.h
  19. 1 1
      Source/BansheeVulkanRenderAPI/Include/BsVulkanVertexBuffer.h
  20. 1 1
      Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuBuffer.cpp
  21. 96 13
      Source/BansheeVulkanRenderAPI/Source/BsVulkanHardwareBuffer.cpp
  22. 1 1
      Source/BansheeVulkanRenderAPI/Source/BsVulkanIndexBuffer.cpp
  23. 1 1
      Source/BansheeVulkanRenderAPI/Source/BsVulkanVertexBuffer.cpp

+ 7 - 3
Source/BansheeCore/Include/BsHardwareBuffer.h

@@ -93,7 +93,10 @@ namespace BansheeEngine
 		 *
 		 * @param[in]	offset		Offset in bytes from which to copy the data.
 		 * @param[in]	length		Length of the area you want to copy, in bytes.
-		 * @param[in]	dest		Destination buffer large enough to store the read data.
+		 * @param[in]	dest		Destination buffer large enough to store the read data. Data is written from the start
+		 *							of the buffer (@p offset is only applied to the source).
+		 * @param[in]	deviceIdx	Index of the device whose memory to read. If the buffer doesn't exist on this device,
+		 *							no data will be read.		
 		 * @param[in]	queueIdx	Device queue to perform any read/write operations on. Using a non-default queue index
 		 *							allows the GPU to perform write or read operations while executing rendering or compute
 		 *							operations on the same time.
@@ -105,14 +108,15 @@ namespace BansheeEngine
 		 *							This value is a global queue index which encodes both the queue type and queue index.
 		 *							Retrieve it from CommandSyncMask::getGlobalQueueIdx().
 		 */
-        virtual void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) = 0;
+        virtual void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) = 0;
 
 		/**
 		 * Writes data into a portion of the buffer from the source memory. 
 		 *
 		 * @param[in]	offset		Offset in bytes from which to copy the data.
 		 * @param[in]	length		Length of the area you want to copy, in bytes.
-		 * @param[in]	source		Source buffer containing the data to write.
+		 * @param[in]	source		Source buffer containing the data to write. Data is read from the start of the buffer
+		 *							(@p offset is only applied to the destination).
 		 * @param[in]	writeFlags	Optional write flags that may affect performance.
 		 * @param[in]	queueIdx	Device queue to perform any read/write operations on. Using a non-default queue index
 		 *							allows the GPU to perform write or read operations while executing rendering or compute

+ 1 - 1
Source/BansheeD3D11RenderAPI/Include/BsD3D11GpuBuffer.h

@@ -26,7 +26,7 @@ namespace BansheeEngine
 		void unlock() override;
 
 		/** @copydoc GpuBufferCore::readData */
-		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc GpuBufferCore::writeData */
         void writeData(UINT32 offset, UINT32 length, const void* pSource,

+ 1 - 1
Source/BansheeD3D11RenderAPI/Include/BsD3D11HardwareBuffer.h

@@ -42,7 +42,7 @@ namespace BansheeEngine
 		~D3D11HardwareBuffer();
 
 		/** @copydoc HardwareBuffer::readData */
-		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc HardwareBuffer::writeData */
 		void writeData(UINT32 offset, UINT32 length, const void* source, 

+ 1 - 1
Source/BansheeD3D11RenderAPI/Include/BsD3D11IndexBuffer.h

@@ -21,7 +21,7 @@ namespace BansheeEngine
 		~D3D11IndexBufferCore();
 
 		/** @copydoc IndexBufferCore::readData */
-		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc IndexBufferCore::writeData */
 		void writeData(UINT32 offset, UINT32 length, const void* source, 

+ 1 - 1
Source/BansheeD3D11RenderAPI/Include/BsD3D11VertexBuffer.h

@@ -21,7 +21,7 @@ namespace BansheeEngine
 		~D3D11VertexBufferCore();
 
 		/** @copydoc VertexBufferCore::readData */
-		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc VertexBufferCore::writeData */
 		void writeData(UINT32 offset, UINT32 length, const void* source, 

+ 1 - 1
Source/BansheeD3D11RenderAPI/Source/BsD3D11GpuBuffer.cpp

@@ -93,7 +93,7 @@ namespace BansheeEngine
 		mBuffer->unlock();
 	}
 
-	void D3D11GpuBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx)
+	void D3D11GpuBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_GpuBuffer);
 

+ 2 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11HardwareBuffer.cpp

@@ -250,11 +250,11 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D11HardwareBuffer::readData(UINT32 offset, UINT32 length, void* pDest, UINT32 queueIdx)
+	void D3D11HardwareBuffer::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 		// There is no functional interface in D3D, just do via manual lock, copy & unlock
 		void* pSrc = this->lock(offset, length, GBL_READ_ONLY);
-		memcpy(pDest, pSrc, length);
+		memcpy(dest, pSrc, length);
 		this->unlock();
 	}
 

+ 2 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11IndexBuffer.cpp

@@ -51,9 +51,9 @@ namespace BansheeEngine
 		mBuffer->unlock();
 	}
 
-	void D3D11IndexBufferCore::readData(UINT32 offset, UINT32 length, void* pDest, UINT32 queueIdx)
+	void D3D11IndexBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
-		mBuffer->readData(offset, length, pDest);
+		mBuffer->readData(offset, length, dest);
 
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_IndexBuffer);
 	}

+ 1 - 1
Source/BansheeD3D11RenderAPI/Source/BsD3D11VertexBuffer.cpp

@@ -44,7 +44,7 @@ namespace BansheeEngine
 		mBuffer->unlock();
 	}
 
-	void D3D11VertexBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx)
+	void D3D11VertexBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 		mBuffer->readData(offset, length, dest);
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_VertexBuffer);

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLGpuBuffer.h

@@ -25,7 +25,7 @@ namespace BansheeEngine
 		void unlock() override;
 
 		/** @copydoc GpuBufferCore::readData */
-        void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+        void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc GpuBufferCore::writeData */
         void writeData(UINT32 offset, UINT32 length, const void* pSource,

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLIndexBuffer.h

@@ -20,7 +20,7 @@ namespace BansheeEngine
 		~GLIndexBufferCore();
 
 		/** @copydoc IndexBufferCore::readData */
-        void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+        void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc IndexBufferCore::writeData */
         void writeData(UINT32 offset, UINT32 length, const void* source, 

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLVertexBuffer.h

@@ -21,7 +21,7 @@ namespace BansheeEngine
 		~GLVertexBufferCore();
 
 		/** @copydoc VertexBufferCore::readData */
-        void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+        void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc VertexBufferCore::writeData */
         void writeData(UINT32 offset, UINT32 length, const void* source, 

+ 1 - 1
Source/BansheeGLRenderAPI/Source/BsGLGpuBuffer.cpp

@@ -71,7 +71,7 @@ namespace BansheeEngine
 		mBuffer.unlock();
 	}
 
-	void GLGpuBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx)
+	void GLGpuBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 		mBuffer.readData(offset, length, dest);
 

+ 2 - 2
Source/BansheeGLRenderAPI/Source/BsGLIndexBuffer.cpp

@@ -36,9 +36,9 @@ namespace BansheeEngine
 		mBuffer.unlock();
 	}
 
-	void GLIndexBufferCore::readData(UINT32 offset, UINT32 length, void* pDest, UINT32 queueIdx)
+	void GLIndexBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
-		mBuffer.readData(offset, length, pDest);
+		mBuffer.readData(offset, length, dest);
 	}
 
 	void GLIndexBufferCore::writeData(UINT32 offset, UINT32 length,

+ 2 - 2
Source/BansheeGLRenderAPI/Source/BsGLVertexBuffer.cpp

@@ -53,9 +53,9 @@ namespace BansheeEngine
 		mBuffer.unlock();
     }
 
-	void GLVertexBufferCore::readData(UINT32 offset, UINT32 length, void* pDest, UINT32 queueIdx)
+	void GLVertexBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
     {
-		mBuffer.readData(offset, length, pDest);
+		mBuffer.readData(offset, length, dest);
     }
 
 	void GLVertexBufferCore::writeData(UINT32 offset, UINT32 length,

+ 1 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanGpuBuffer.h

@@ -24,7 +24,7 @@ namespace BansheeEngine
 		void unlock() override;
 
 		/** @copydoc GpuBufferCore::readData */
-		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc GpuBufferCore::writeData */
         void writeData(UINT32 offset, UINT32 length, const void* source,

+ 3 - 2
Source/BansheeVulkanRenderAPI/Include/BsVulkanHardwareBuffer.h

@@ -39,7 +39,8 @@ namespace BansheeEngine
 		 * the destination buffer. Caller must ensure the provided offsets and lengths are within valid bounds of
 		 * both buffers.
 		 */
-		void copy(VulkanTransferBuffer* cb, VulkanBuffer* destination, VkDeviceSize offset, VkDeviceSize length);
+		void copy(VulkanTransferBuffer* cb, VulkanBuffer* destination, VkDeviceSize srcOffset, VkDeviceSize dstOffset, 
+			VkDeviceSize length);
 
 	private:
 		VkBuffer mBuffer;
@@ -71,7 +72,7 @@ namespace BansheeEngine
 		~VulkanHardwareBuffer();
 
 		/** @copydoc HardwareBuffer::readData */
-		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc HardwareBuffer::writeData */
 		void writeData(UINT32 offset, UINT32 length, const void* source, 

+ 1 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanIndexBuffer.h

@@ -20,7 +20,7 @@ namespace BansheeEngine
 		~VulkanIndexBufferCore();
 
 		/** @copydoc IndexBufferCore::readData */
-		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc IndexBufferCore::writeData */
 		void writeData(UINT32 offset, UINT32 length, const void* source, 

+ 1 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanVertexBuffer.h

@@ -19,7 +19,7 @@ namespace BansheeEngine
 		~VulkanVertexBufferCore();
 
 		/** @copydoc VertexBufferCore::readData */
-		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx = 0) override;
+		void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
 
 		/** @copydoc VertexBufferCore::writeData */
 		void writeData(UINT32 offset, UINT32 length, const void* source, 

+ 1 - 1
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuBuffer.cpp

@@ -64,7 +64,7 @@ namespace BansheeEngine
 		
 	}
 
-	void VulkanGpuBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx)
+	void VulkanGpuBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_GpuBuffer);
 	}

+ 96 - 13
Source/BansheeVulkanRenderAPI/Source/BsVulkanHardwareBuffer.cpp

@@ -43,12 +43,13 @@ namespace BansheeEngine
 		vkUnmapMemory(device.getLogical(), mMemory);
 	}
 
-	void VulkanBuffer::copy(VulkanTransferBuffer* cb, VulkanBuffer* destination, VkDeviceSize offset, VkDeviceSize length)
+	void VulkanBuffer::copy(VulkanTransferBuffer* cb, VulkanBuffer* destination, VkDeviceSize srcOffset, 
+		VkDeviceSize dstOffset, VkDeviceSize length)
 	{
 		VkBufferCopy region;
 		region.size = length;
-		region.srcOffset = offset;
-		region.dstOffset = offset;
+		region.srcOffset = srcOffset;
+		region.dstOffset = dstOffset;
 
 		vkCmdCopyBuffer(cb->getCB()->getHandle(), mBuffer, destination->getHandle(), 1, &region);
 	}
@@ -277,7 +278,7 @@ namespace BansheeEngine
 				}
 
 				// Queue copy command
-				buffer->copy(transferCB, mStagingBuffer, offset, length);
+				buffer->copy(transferCB, mStagingBuffer, offset, offset, length);
 
 				// Ensure data written to the staging buffer is visible
 				transferCB->memoryBarrier(buffer->getHandle(),
@@ -346,7 +347,10 @@ namespace BansheeEngine
 				}
 				
 				// Queue copy command
-				mStagingBuffer->copy(transferCB, buffer, mMappedOffset, mMappedSize);
+				mStagingBuffer->copy(transferCB, buffer, mMappedOffset, mMappedOffset, mMappedSize);
+
+				// We don't actually flush the transfer buffer here since it's an expensive operation, but it's instead
+				// done automatically before next "normal" command buffer submission.
 			}
 
 			mStagingBuffer->unmap();
@@ -361,20 +365,99 @@ namespace BansheeEngine
 	void VulkanHardwareBuffer::copyData(HardwareBuffer& srcBuffer, UINT32 srcOffset,
 		UINT32 dstOffset, UINT32 length, bool discardWholeBuffer, UINT32 queueIdx)
 	{
-		// TODO - Queue copy command on the requested queue
-		//      - Issue semaphores if src buffer is currently used
-		//      - Otherwise just create a new buffer and write to it
-		//      - If current buffer is currently being written to by the GPU, issue a wait and log a performance warning
+		if ((dstOffset + length) > mSize)
+		{
+			LOGERR("Provided offset(" + toString(dstOffset) + ") + length(" + toString(length) + ") "
+				   "is larger than the destination buffer " + toString(mSize) + ". Copy operation aborted.");
+
+			return;
+		}
+
+		if ((srcOffset + length) > srcBuffer.getSize())
+		{
+			LOGERR("Provided offset(" + toString(srcOffset) + ") + length(" + toString(length) + ") "
+				   "is larger than the source buffer " + toString(srcBuffer.getSize()) + ". Copy operation aborted.");
+
+			return;
+		}
+
+		VulkanHardwareBuffer& vkSource = static_cast<VulkanHardwareBuffer&>(srcBuffer);
+
+		VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPICore::instance());
+		VulkanCommandBufferManager& cbManager = gVulkanCBManager();
+
+		GpuQueueType queueType;
+		UINT32 localQueueIdx = CommandSyncMask::getQueueIdxAndType(queueIdx, queueType);
+
+		// Perform copy on every device that has both buffers
+		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
+		{
+			VulkanBuffer* src = vkSource.mBuffers[i];
+			VulkanBuffer* dst = mBuffers[i];
+
+			if (src == nullptr || dst == nullptr)
+				continue;
+
+			VulkanDevice& device = *rapi._getDevice(i);
+			VulkanTransferBuffer* transferCB = cbManager.getTransferBuffer(i, queueType, localQueueIdx);
+
+			// If either source or destination buffer is currently being written to do need to sync the copy operation so
+			// it executes after both are done
+
+			// If destination is being used on the GPU we need to wait until it finishes before writing to it
+			UINT32 dstUseMask = dst->getUseInfo(VulkanUseFlag::Read | VulkanUseFlag::Write);
+
+			// If discard is enabled and destination is used, instead of waiting just discard the existing buffer and make a new one
+			if(dstUseMask != 0 && discardWholeBuffer)
+			{
+				dst->destroy();
+
+				dst = createBuffer(device, false, mReadable);
+				mBuffers[mMappedDeviceIdx] = dst;
+
+				dstUseMask = 0;
+			}
+
+			// If source buffer is being written to on the GPU we need to wait until it finishes, before executing copy
+			UINT32 srcUseMask = src->getUseInfo(VulkanUseFlag::Write);
+
+			// Wait if anything is using the buffers
+			if(dstUseMask != 0 || srcUseMask != 0)
+				transferCB->appendMask(dstUseMask | srcUseMask);
+
+			src->copy(transferCB, dst, srcOffset, dstOffset, length);
+
+			// We don't actually flush the transfer buffer here since it's an expensive operation, but it's instead
+			// done automatically before next "normal" command buffer submission.
+		}
 	}
 
-	void VulkanHardwareBuffer::readData(UINT32 offset, UINT32 length, void* pDest, UINT32 queueIdx)
+	void VulkanHardwareBuffer::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
-		// TODO - Just use lock/unlock
+		void* lockedData = lock(offset, length, GBL_READ_ONLY, deviceIdx, queueIdx);
+		memcpy(dest, lockedData, length);
+		unlock();
 	}
 
-	void VulkanHardwareBuffer::writeData(UINT32 offset, UINT32 length, const void* pSource, BufferWriteType writeFlags, 
+	void VulkanHardwareBuffer::writeData(UINT32 offset, UINT32 length, const void* source, BufferWriteType writeFlags, 
 		UINT32 queueIdx)
 	{
-		// TODO - Just use lock/unlock
+		GpuLockOptions lockOptions = GBL_WRITE_ONLY;
+
+		if (writeFlags == BTW_NO_OVERWRITE)
+			lockOptions = GBL_WRITE_ONLY_NO_OVERWRITE;
+		else if (writeFlags == BWT_DISCARD)
+			lockOptions = GBL_WRITE_ONLY_DISCARD;
+
+		// Write to every device
+		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
+		{
+			if (mBuffers[i] == nullptr)
+				continue;
+
+			void* lockedData = lock(offset, length, lockOptions, i, queueIdx);
+			memcpy(lockedData, source, length);
+			unlock();
+		}
 	}
 }

+ 1 - 1
Source/BansheeVulkanRenderAPI/Source/BsVulkanIndexBuffer.cpp

@@ -45,7 +45,7 @@ namespace BansheeEngine
 
 	}
 
-	void VulkanIndexBufferCore::readData(UINT32 offset, UINT32 length, void* pDest, UINT32 queueIdx)
+	void VulkanIndexBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_IndexBuffer);
 	}

+ 1 - 1
Source/BansheeVulkanRenderAPI/Source/BsVulkanVertexBuffer.cpp

@@ -36,7 +36,7 @@ namespace BansheeEngine
 
 	}
 
-	void VulkanVertexBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 queueIdx)
+	void VulkanVertexBufferCore::readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx, UINT32 queueIdx)
 	{
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_VertexBuffer);
 	}