coral_buffer.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "coral_buffer.h"
  2. #include <cassert>
  3. #define VMA_IMPLEMENTATION
  4. #include "vk_mem_alloc.h"
  5. using namespace coral_3d;
  6. coral_buffer::coral_buffer(
  7. coral_device& device,
  8. VkDeviceSize instance_size,
  9. uint32_t instance_count,
  10. VkBufferUsageFlags usage_flags,
  11. VmaMemoryUsage usage,
  12. VmaAllocationCreateFlags flags,
  13. VkDeviceSize min_offset_alignment)
  14. : device_{device}
  15. , instance_size_{instance_size}
  16. , instance_count_{instance_count}
  17. , usage_{usage}
  18. , usage_flags_{usage_flags}
  19. {
  20. alignment_size_ = get_allignment(instance_size_, min_offset_alignment);
  21. buffer_size_ = alignment_size_ * instance_count_;
  22. buffer_ = device_.create_buffer(buffer_size_, usage_flags_, usage_, flags);
  23. }
  24. coral_buffer::~coral_buffer()
  25. {
  26. unmap();
  27. vmaDestroyBuffer(device_.allocator(), buffer_.buffer, buffer_.allocation);
  28. }
  29. /**
  30. * Map a memory range of this buffer. If successful, mapped points to the specified buffer range.
  31. *
  32. * @param size (Optional) Size of the memory range to map. Pass VK_WHOLE_SIZE to map the complete
  33. * buffer range.
  34. * @param offset (Optional) Byte offset from beginning
  35. *
  36. * @return VkResult of the buffer mapping call
  37. */
  38. VkResult coral_buffer::map()
  39. {
  40. assert(buffer_.buffer && buffer_.allocation && "ERROR! coral_buffer::map() >> Called map on an unitialized buffer");
  41. return vmaMapMemory(device_.allocator(), buffer_.allocation, &mapped_data_);
  42. }
  43. /**
  44. * Unmap a mapped memory range
  45. *
  46. * @note Does not return a result as vkUnmapMemory can't fail
  47. */
  48. void coral_buffer::unmap()
  49. {
  50. if (mapped_data_)
  51. {
  52. vmaUnmapMemory(device_.allocator(), buffer_.allocation);
  53. mapped_data_ = nullptr;
  54. }
  55. }
  56. /**
  57. * Copies the specified data to the mapped buffer. Default value writes_ whole buffer range
  58. *
  59. * @param data Pointer to the data to copy
  60. * @param size (Optional) Size of the data to copy. Pass VK_WHOLE_SIZE to flush the complete buffer
  61. * range.
  62. * @param offset (Optional) Byte offset from beginning of mapped region
  63. *
  64. */
  65. void coral_buffer::write_to_buffer(void* data, VkDeviceSize size, VkDeviceSize offset)
  66. {
  67. assert(mapped_data_ && "ERROR! coral_buffer::write_to_buffer() >> Called write_to_buffer on an unmapped buffer");
  68. if(size == VK_WHOLE_SIZE)
  69. memcpy(mapped_data_, data, buffer_size_);
  70. else
  71. {
  72. char* mem_offset{ reinterpret_cast<char*>(mapped_data_) };
  73. mem_offset += offset;
  74. memcpy(mem_offset, data, size);
  75. }
  76. }
  77. /**
  78. * Flush a memory range of the buffer to make it visible to the device
  79. *
  80. * @note Only required for non-coherent memory
  81. *
  82. * @param size (Optional) Size of the memory range to flush. Pass VK_WHOLE_SIZE to flush the
  83. * complete buffer range.
  84. * @param offset (Optional) Byte offset from beginning
  85. *
  86. * @return VkResult of the flush call
  87. */
  88. VkResult coral_buffer::flush(VkDeviceSize size, VkDeviceSize offset)
  89. {
  90. return vmaFlushAllocation(device_.allocator(), buffer_.allocation, offset, size);
  91. }
  92. /**
  93. * Create a buffer info descriptor
  94. *
  95. * @param size (Optional) Size of the memory range of the descriptor
  96. * @param offset (Optional) Byte offset from beginning
  97. *
  98. * @return VkDescriptorBufferInfo of specified offset and range
  99. */
  100. VkDescriptorBufferInfo coral_buffer::descriptor_info(VkDeviceSize size, VkDeviceSize offset) const
  101. {
  102. return VkDescriptorBufferInfo
  103. {
  104. buffer_.buffer,
  105. offset,
  106. size
  107. };
  108. }
  109. /**
  110. * Invalidate a memory range of the buffer to make it visible to the host
  111. *
  112. * @note Only required for non-coherent memory
  113. *
  114. * @param size (Optional) Size of the memory range to invalidate. Pass VK_WHOLE_SIZE to invalidate
  115. * the complete buffer range.
  116. * @param offset (Optional) Byte offset from beginning
  117. *
  118. * @return VkResult of the invalidate call
  119. */
  120. VkResult coral_buffer::invalidate(VkDeviceSize size, VkDeviceSize offset)
  121. {
  122. return vmaInvalidateAllocation(device_.allocator(), buffer_.allocation, offset, size);
  123. }
  124. /**
  125. * Copies "instanceSize" bytes of data to the mapped buffer at an offset of index * alignment_size_
  126. *
  127. * @param data Pointer to the data to copy
  128. * @param index Used in offset calculation
  129. *
  130. */
  131. void coral_buffer::write_to_index(void* data, uint32_t index)
  132. {
  133. write_to_buffer(data, instance_size_, index * alignment_size_);
  134. }
  135. /**
  136. * Flush the memory range at index * alignment_size_ of the buffer to make it visible to the device
  137. *
  138. * @param index Used in offset calculation
  139. *
  140. */
  141. VkResult coral_buffer::flush_index(uint32_t index)
  142. {
  143. return flush(alignment_size_, index * alignment_size_);
  144. }
  145. /**
  146. * Create a buffer info descriptor
  147. *
  148. * @param index Specifies the region given by index * alignment_size_
  149. *
  150. * @return VkDescriptorBufferInfo for instance at index
  151. */
  152. VkDescriptorBufferInfo coral_buffer::descriptor_info_index(uint32_t index) const
  153. {
  154. return descriptor_info(alignment_size_, index * alignment_size_);
  155. }
  156. /**
  157. * Invalidate a memory range of the buffer to make it visible to the host
  158. *
  159. * @note Only required for non-coherent memory
  160. *
  161. * @param index Specifies the region to invalidate: index * alignment_size_
  162. *
  163. * @return VkResult of the invalidate call
  164. */
  165. VkResult coral_buffer::invalidate_index(uint32_t index)
  166. {
  167. return invalidate(alignment_size_, index * alignment_size_);
  168. }
  169. VkDeviceSize coral_buffer::get_allignment(VkDeviceSize instance_size, VkDeviceSize min_offset_alignment)
  170. {
  171. return min_offset_alignment > 0 ? (instance_size + min_offset_alignment - 1) & ~(min_offset_alignment - 1) : instance_size;
  172. }