2
0

BufferImpl.cpp 9.6 KB

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