载入中...
搜索中...
未找到
VulkanGpuBuffer.cpp
浏览该文件的文档.
3
5
6#include "common/Exception.h"
7#include "data/ByteData.h"
8
9#include <cstring>
10#include <vector>
11
12namespace eve::gpgpu {
13
16 if (!buffer_) return view;
17 const VkBuffer raw = static_cast<VkBuffer>(buffer_);
18 static_assert(sizeof(raw) <= sizeof(view.nativeHandle));
19 std::memcpy(&view.nativeHandle, &raw, sizeof(raw));
21 view.sizeBytes = uint64_t(size_);
22 return view;
23}
24
26 if (!device_ || !static_cast<VkDevice>(device_->instance)) return;
27#if defined(VKB_ENABLE_VMA)
28 if (vmaAllocation_) {
29 vmaDestroyBuffer(device_->vma_allocator, static_cast<VkBuffer>(buffer_), vmaAllocation_);
30 buffer_ = vk::Buffer{};
31 memory_ = vk::DeviceMemory{};
32 vmaAllocation_ = VK_NULL_HANDLE;
33 device_ = nullptr;
34 return;
35 }
36#endif
37 if (buffer_) {
38 (*device_)->destroyBuffer(buffer_, device_->allocation_callbacks);
39 buffer_ = vk::Buffer{};
40 }
41 if (memory_) {
42 (*device_)->freeMemory(memory_, device_->allocation_callbacks);
43 memory_ = vk::DeviceMemory{};
44 }
45 device_ = nullptr;
46}
47
48void VulkanGpuBuffer::uploadBytes(const void *src, uint64_t nbytes, uint64_t dstOffset) {
49 if (!device_ || !buffer_ || !src || nbytes == 0) return;
50 if (dstOffset + nbytes > size_)
51 throw Exception("GpuBuffer.write: out of range (offset=%llu size=%llu capacity=%llu)",
52 (unsigned long long)dstOffset, (unsigned long long)nbytes,
53 (unsigned long long)size_);
54
55 auto *vkg = requireVulkanGraphics();
56 auto queue = computeQueue(vkg);
57 auto pool = computeCommandPool(vkg);
58
59 if (hostVisible_) {
60#if defined(VKB_ENABLE_VMA)
61 if (vmaAllocation_) {
62 void *base = nullptr;
63 const VkResult result = vmaMapMemory(device_->vma_allocator, vmaAllocation_, &base);
64 if (result != VK_SUCCESS)
65 throw Exception("GpuBuffer.write: VMA map failed: %d", int(result));
66 std::memcpy(static_cast<unsigned char *>(base) + dstOffset, src, size_t(nbytes));
67 vmaUnmapMemory(device_->vma_allocator, vmaAllocation_);
68 return;
69 }
70#endif
71 void *ptr = (*device_)->mapMemory(memory_, dstOffset, nbytes, vk::MemoryMapFlags{});
72 std::memcpy(ptr, src, size_t(nbytes));
73 (*device_)->unmapMemory(memory_);
74 return;
75 }
76
77 using buf = vk::BufferUsageFlagBits;
78 using pfb = vk::MemoryPropertyFlagBits;
79 vkb::GenericBuffer staging(*device_, buf::eTransferSrc, nbytes,
80 pfb::eHostVisible | pfb::eHostCoherent);
81 staging.updateLocal(vkb::FrameSlot::gpuIdle(), src, nbytes);
82 vkb::executeImmediately(device_->instance, pool, queue, [&](vk::CommandBuffer cb) {
83 vk::BufferCopy bc{0, vk::DeviceSize(dstOffset), vk::DeviceSize(nbytes)};
84 cb.copyBuffer(staging.buffer, buffer_, bc);
85 });
86}
87
88void VulkanGpuBuffer::downloadBytes(void *dst, uint64_t nbytes, uint64_t srcOffset) const {
89 if (!device_ || !buffer_ || !dst || nbytes == 0) return;
90 if (srcOffset + nbytes > size_)
91 throw Exception("GpuBuffer.read: out of range (offset=%llu size=%llu capacity=%llu)",
92 (unsigned long long)srcOffset, (unsigned long long)nbytes,
93 (unsigned long long)size_);
94
95 auto *vkg = requireVulkanGraphics();
96 auto queue = computeQueue(vkg);
97 auto pool = computeCommandPool(vkg);
98
99 if (hostVisible_) {
100#if defined(VKB_ENABLE_VMA)
101 if (vmaAllocation_) {
102 void *base = nullptr;
103 const VkResult result = vmaMapMemory(device_->vma_allocator, vmaAllocation_, &base);
104 if (result != VK_SUCCESS)
105 throw Exception("GpuBuffer.read: VMA map failed: %d", int(result));
106 std::memcpy(dst, static_cast<const unsigned char *>(base) + srcOffset, size_t(nbytes));
107 vmaUnmapMemory(device_->vma_allocator, vmaAllocation_);
108 return;
109 }
110#endif
111 void *ptr = (*device_)->mapMemory(memory_, srcOffset, nbytes, vk::MemoryMapFlags{});
112 std::memcpy(dst, ptr, size_t(nbytes));
113 (*device_)->unmapMemory(memory_);
114 return;
115 }
116
117 using buf = vk::BufferUsageFlagBits;
118 using pfb = vk::MemoryPropertyFlagBits;
119 vkb::GenericBuffer staging(*device_, buf::eTransferDst, nbytes,
120 pfb::eHostVisible | pfb::eHostCoherent);
121 vkb::executeImmediately(device_->instance, pool, queue, [&](vk::CommandBuffer cb) {
122 vk::BufferCopy bc{vk::DeviceSize(srcOffset), 0, vk::DeviceSize(nbytes)};
123 cb.copyBuffer(buffer_, staging.buffer, bc);
124 });
125 void *ptr = staging.map();
126 std::memcpy(dst, ptr, size_t(nbytes));
127 staging.unmap();
128}
129
130void VulkanGpuBuffer::writeData(data::ByteData *data, int dstOffset) {
131 if (!data) return;
132 uploadBytes(data->getData(), data->getSize(), uint64_t(dstOffset < 0 ? 0 : dstOffset));
133}
134
135data::ByteData *VulkanGpuBuffer::readData(int srcOffset, int size) {
136 const int off = srcOffset < 0 ? 0 : srcOffset;
137 int nbytes = size;
138 if (nbytes < 0) nbytes = int(size_) - off;
139 if (nbytes <= 0) return new data::ByteData(size_t(0));
140 auto *out = new data::ByteData(size_t(nbytes));
141 downloadBytes(out->getData(), uint64_t(nbytes), uint64_t(off));
142 return out;
143}
144
145void VulkanGpuBuffer::writeFloat32(int floatIndex, float value) {
146 if (floatIndex < 0) return;
147 uploadBytes(&value, sizeof(float), uint64_t(floatIndex) * sizeof(float));
148}
149
150float VulkanGpuBuffer::readFloat32(int floatIndex) {
151 if (floatIndex < 0) return 0.f;
152 float v = 0.f;
153 downloadBytes(&v, sizeof(float), uint64_t(floatIndex) * sizeof(float));
154 return v;
155}
156
157void VulkanGpuBuffer::writeFloat32s(const float *data, int count, int startIndex) {
158 if (!data || count <= 0 || startIndex < 0) return;
159 uploadBytes(data, uint64_t(count) * sizeof(float),
160 uint64_t(startIndex) * sizeof(float));
161}
162
163void VulkanGpuBuffer::readFloat32s(float *out, int count, int startIndex) const {
164 if (!out || count <= 0 || startIndex < 0) return;
165 downloadBytes(out, uint64_t(count) * sizeof(float),
166 uint64_t(startIndex) * sizeof(float));
167}
168
169void VulkanGpuBuffer::fillFloat32(float value) {
170 if (size_ < sizeof(float)) return;
171 const size_t count = size_t(size_ / sizeof(float));
172 std::vector<float> tmp(count, value);
173 uploadBytes(tmp.data(), count * sizeof(float), 0);
174}
175
176} // namespace eve::gpgpu
double value
float v
void * ptr
glm::mat4 view
std::uint32_t count
float size
Definition TreeMesh.cpp:156
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
In-memory byte buffer implementing eve::Data (ref-counted).
Definition ByteData.h:13
void uploadBytes(const void *src, uint64_t nbytes, uint64_t dstOffset=0) override
Uploads bytes.
GpuResidentBufferView residentView() const override
Resident view.
~VulkanGpuBuffer() override
Releases VulkanGpuBuffer resources.
Fluids module — interactive surface fluid simulation.
Definition Fluids.h:34
vk::Queue computeQueue(graphics::vulkan::Graphics *vkg)
Computes queue.
graphics::vulkan::Graphics * requireVulkanGraphics()
Resolve live Vulkan Graphics (throws if missing / not initialized).
vk::CommandPool computeCommandPool(graphics::vulkan::Graphics *vkg)
Computes command pool.
Transient backend buffer slice shared between sibling GPU modules. @ownership Non-owning; nativeHandl...