BufferImpl.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/Vulkan/BufferImpl.h>
  6. #include <AnKi/Gr/Vulkan/GrManagerImpl.h>
  7. namespace anki {
  8. BufferImpl::~BufferImpl()
  9. {
  10. ANKI_ASSERT(!m_mapped);
  11. if(m_handle)
  12. {
  13. vkDestroyBuffer(getDevice(), m_handle, nullptr);
  14. }
  15. if(m_memHandle)
  16. {
  17. getGrManagerImpl().getGpuMemoryManager().freeMemory(m_memHandle);
  18. }
  19. #if ANKI_EXTRA_CHECKS
  20. if(m_needsFlush && m_flushCount.load() == 0)
  21. {
  22. ANKI_VK_LOGW("Buffer needed flushing but you never flushed: %s", getName().cstr());
  23. }
  24. if(m_needsInvalidate && m_invalidateCount.load() == 0)
  25. {
  26. ANKI_VK_LOGW("Buffer needed invalidation but you never invalidated: %s", getName().cstr());
  27. }
  28. #endif
  29. }
  30. Error BufferImpl::init(const BufferInitInfo& inf)
  31. {
  32. ANKI_ASSERT(!isCreated());
  33. const Bool exposeGpuAddress = !!(getGrManagerImpl().getExtensions() & VulkanExtensions::KHR_BUFFER_DEVICE_ADDRESS)
  34. && !!(inf.m_usage & ~BufferUsageBit::ALL_TRANSFER);
  35. PtrSize size = inf.m_size;
  36. BufferMapAccessBit access = inf.m_mapAccess;
  37. BufferUsageBit usage = inf.m_usage;
  38. ANKI_ASSERT(size > 0);
  39. ANKI_ASSERT(usage != BufferUsageBit::NONE);
  40. m_mappedMemoryRangeAlignment = getGrManagerImpl().getPhysicalDeviceProperties().limits.nonCoherentAtomSize;
  41. // Align the size to satisfy fill buffer
  42. alignRoundUp(4, size);
  43. // Align to satisfy the flush and invalidate
  44. alignRoundUp(m_mappedMemoryRangeAlignment, size);
  45. // Create the buffer
  46. VkBufferCreateInfo ci = {};
  47. ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  48. ci.size = size;
  49. ci.usage = convertBufferUsageBit(usage);
  50. if(exposeGpuAddress)
  51. {
  52. ci.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR;
  53. }
  54. ci.queueFamilyIndexCount = getGrManagerImpl().getQueueFamilies().getSize();
  55. ci.pQueueFamilyIndices = &getGrManagerImpl().getQueueFamilies()[0];
  56. ci.sharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
  57. ANKI_VK_CHECK(vkCreateBuffer(getDevice(), &ci, nullptr, &m_handle));
  58. getGrManagerImpl().trySetVulkanHandleName(inf.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, m_handle);
  59. // Get mem requirements
  60. VkMemoryRequirements req;
  61. vkGetBufferMemoryRequirements(getDevice(), m_handle, &req);
  62. U32 memIdx = MAX_U32;
  63. if(access == BufferMapAccessBit::WRITE)
  64. {
  65. // Only write, probably for uploads
  66. VkMemoryPropertyFlags preferDeviceLocal = 0;
  67. VkMemoryPropertyFlags avoidDeviceLocal = 0;
  68. #if !ANKI_PLATFORM_MOBILE
  69. if((usage & (~BufferUsageBit::ALL_TRANSFER)) != BufferUsageBit::NONE)
  70. {
  71. // Will be used for something other than transfer, try to put it in the device
  72. preferDeviceLocal = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
  73. avoidDeviceLocal = 0;
  74. }
  75. else
  76. {
  77. // Will be used only for transfers, don't want it in the device
  78. preferDeviceLocal = 0;
  79. avoidDeviceLocal = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
  80. }
  81. #endif
  82. // Device & host & coherent but not cached
  83. memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(
  84. req.memoryTypeBits,
  85. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | preferDeviceLocal,
  86. VK_MEMORY_PROPERTY_HOST_CACHED_BIT | avoidDeviceLocal);
  87. // Fallback: host & coherent and not cached
  88. if(memIdx == MAX_U32)
  89. {
  90. #if !ANKI_PLATFORM_MOBILE
  91. ANKI_VK_LOGW("Using a fallback mode for write-only buffer");
  92. #endif
  93. memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(
  94. req.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
  95. VK_MEMORY_PROPERTY_HOST_CACHED_BIT | avoidDeviceLocal);
  96. }
  97. }
  98. else if(!!(access & BufferMapAccessBit::READ))
  99. {
  100. // Read or read/write
  101. // Cached & coherent
  102. memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(req.memoryTypeBits,
  103. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
  104. | VK_MEMORY_PROPERTY_HOST_CACHED_BIT
  105. | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
  106. 0);
  107. // Fallback: Just cached
  108. if(memIdx == MAX_U32)
  109. {
  110. #if !ANKI_PLATFORM_MOBILE
  111. ANKI_VK_LOGW("Using a fallback mode for read/write buffer");
  112. #endif
  113. memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(
  114. req.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, 0);
  115. }
  116. }
  117. else
  118. {
  119. // Not mapped
  120. ANKI_ASSERT(access == BufferMapAccessBit::NONE);
  121. // Device only
  122. memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(
  123. req.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
  124. // Fallback: Device with anything else
  125. if(memIdx == MAX_U32)
  126. {
  127. memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(req.memoryTypeBits,
  128. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
  129. }
  130. }
  131. ANKI_ASSERT(memIdx != MAX_U32);
  132. const VkPhysicalDeviceMemoryProperties& props = getGrManagerImpl().getMemoryProperties();
  133. m_memoryFlags = props.memoryTypes[memIdx].propertyFlags;
  134. if(!!(access & BufferMapAccessBit::READ) && !(m_memoryFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
  135. {
  136. m_needsInvalidate = true;
  137. }
  138. if(!!(access & BufferMapAccessBit::WRITE) && !(m_memoryFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
  139. {
  140. m_needsFlush = true;
  141. }
  142. // Allocate
  143. const U32 alignment = U32(max(m_mappedMemoryRangeAlignment, req.alignment));
  144. getGrManagerImpl().getGpuMemoryManager().allocateMemory(memIdx, req.size, alignment, true, m_memHandle);
  145. // Bind mem to buffer
  146. {
  147. ANKI_TRACE_SCOPED_EVENT(VK_BIND_OBJECT);
  148. ANKI_VK_CHECK(vkBindBufferMemory(getDevice(), m_handle, m_memHandle.m_memory, m_memHandle.m_offset));
  149. }
  150. // Get GPU buffer address
  151. if(exposeGpuAddress)
  152. {
  153. VkBufferDeviceAddressInfoKHR info = {};
  154. info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR;
  155. info.buffer = m_handle;
  156. m_gpuAddress = vkGetBufferDeviceAddressKHR(getDevice(), &info);
  157. if(m_gpuAddress == 0)
  158. {
  159. ANKI_VK_LOGE("vkGetBufferDeviceAddressKHR() failed");
  160. return Error::FUNCTION_FAILED;
  161. }
  162. }
  163. m_access = access;
  164. m_size = inf.m_size;
  165. m_actualSize = size;
  166. m_usage = usage;
  167. return Error::NONE;
  168. }
  169. void* BufferImpl::map(PtrSize offset, PtrSize range, BufferMapAccessBit access)
  170. {
  171. ANKI_ASSERT(isCreated());
  172. ANKI_ASSERT(access != BufferMapAccessBit::NONE);
  173. ANKI_ASSERT((access & m_access) != BufferMapAccessBit::NONE);
  174. ANKI_ASSERT(!m_mapped);
  175. ANKI_ASSERT(offset < m_size);
  176. if(range == MAX_PTR_SIZE)
  177. {
  178. range = m_size - offset;
  179. }
  180. ANKI_ASSERT(offset + range <= m_size);
  181. void* ptr = getGrManagerImpl().getGpuMemoryManager().getMappedAddress(m_memHandle);
  182. ANKI_ASSERT(ptr);
  183. #if ANKI_EXTRA_CHECKS
  184. m_mapped = true;
  185. #endif
  186. return static_cast<void*>(static_cast<U8*>(ptr) + offset);
  187. }
  188. VkPipelineStageFlags BufferImpl::computePplineStage(BufferUsageBit usage)
  189. {
  190. VkPipelineStageFlags stageMask = 0;
  191. if(!!(usage & BufferUsageBit::ALL_INDIRECT))
  192. {
  193. stageMask |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
  194. }
  195. if(!!(usage & (BufferUsageBit::INDEX | BufferUsageBit::VERTEX)))
  196. {
  197. stageMask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
  198. }
  199. if(!!(usage & BufferUsageBit::ALL_GEOMETRY))
  200. {
  201. stageMask |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
  202. | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
  203. }
  204. if(!!(usage & BufferUsageBit::ALL_FRAGMENT))
  205. {
  206. stageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  207. }
  208. if(!!(usage & (BufferUsageBit::ALL_COMPUTE & ~BufferUsageBit::INDIRECT_COMPUTE)))
  209. {
  210. stageMask |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  211. }
  212. if(!!(usage & BufferUsageBit::ACCELERATION_STRUCTURE_BUILD))
  213. {
  214. stageMask |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
  215. }
  216. if(!!(usage & (BufferUsageBit::ALL_TRACE_RAYS & ~BufferUsageBit::INDIRECT_TRACE_RAYS)))
  217. {
  218. stageMask |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
  219. }
  220. if(!!(usage & BufferUsageBit::ALL_TRANSFER))
  221. {
  222. stageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
  223. }
  224. if(!stageMask)
  225. {
  226. stageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  227. }
  228. ANKI_ASSERT(stageMask);
  229. return stageMask;
  230. }
  231. VkAccessFlags BufferImpl::computeAccessMask(BufferUsageBit usage)
  232. {
  233. VkAccessFlags mask = 0;
  234. constexpr BufferUsageBit SHADER_READ =
  235. BufferUsageBit::STORAGE_GEOMETRY_READ | BufferUsageBit::STORAGE_FRAGMENT_READ
  236. | BufferUsageBit::STORAGE_COMPUTE_READ | BufferUsageBit::STORAGE_TRACE_RAYS_READ
  237. | BufferUsageBit::TEXTURE_GEOMETRY_READ | BufferUsageBit::TEXTURE_FRAGMENT_READ
  238. | BufferUsageBit::TEXTURE_COMPUTE_READ | BufferUsageBit::TEXTURE_TRACE_RAYS_READ;
  239. constexpr BufferUsageBit SHADER_WRITE =
  240. BufferUsageBit::STORAGE_GEOMETRY_WRITE | BufferUsageBit::STORAGE_FRAGMENT_WRITE
  241. | BufferUsageBit::STORAGE_COMPUTE_WRITE | BufferUsageBit::STORAGE_TRACE_RAYS_WRITE
  242. | BufferUsageBit::TEXTURE_GEOMETRY_WRITE | BufferUsageBit::TEXTURE_FRAGMENT_WRITE
  243. | BufferUsageBit::TEXTURE_COMPUTE_WRITE | BufferUsageBit::TEXTURE_TRACE_RAYS_WRITE;
  244. if(!!(usage & BufferUsageBit::ALL_UNIFORM))
  245. {
  246. mask |= VK_ACCESS_UNIFORM_READ_BIT;
  247. }
  248. if(!!(usage & SHADER_READ))
  249. {
  250. mask |= VK_ACCESS_SHADER_READ_BIT;
  251. }
  252. if(!!(usage & SHADER_WRITE))
  253. {
  254. mask |= VK_ACCESS_SHADER_WRITE_BIT;
  255. }
  256. if(!!(usage & BufferUsageBit::INDEX))
  257. {
  258. mask |= VK_ACCESS_INDEX_READ_BIT;
  259. }
  260. if(!!(usage & BufferUsageBit::VERTEX))
  261. {
  262. mask |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
  263. }
  264. if(!!(usage & BufferUsageBit::ALL_INDIRECT))
  265. {
  266. mask |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
  267. }
  268. if(!!(usage & BufferUsageBit::TRANSFER_DESTINATION))
  269. {
  270. mask |= VK_ACCESS_TRANSFER_WRITE_BIT;
  271. }
  272. if(!!(usage & BufferUsageBit::TRANSFER_SOURCE))
  273. {
  274. mask |= VK_ACCESS_TRANSFER_READ_BIT;
  275. }
  276. if(!!(usage & BufferUsageBit::ACCELERATION_STRUCTURE_BUILD))
  277. {
  278. mask |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
  279. }
  280. return mask;
  281. }
  282. void BufferImpl::computeBarrierInfo(BufferUsageBit before, BufferUsageBit after, VkPipelineStageFlags& srcStages,
  283. VkAccessFlags& srcAccesses, VkPipelineStageFlags& dstStages,
  284. VkAccessFlags& dstAccesses) const
  285. {
  286. ANKI_ASSERT(usageValid(before) && usageValid(after));
  287. ANKI_ASSERT(!!after);
  288. srcStages = computePplineStage(before);
  289. dstStages = computePplineStage(after);
  290. srcAccesses = computeAccessMask(before);
  291. dstAccesses = computeAccessMask(after);
  292. }
  293. } // end namespace anki