BufferImpl.cpp 10 KB

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