载入中...
搜索中...
未找到
EcsGpu.h
浏览该文件的文档.
1#pragma once
2
3// Bridge C++ ECS.hpp Views ↔ gpgpu::ShaderSystem storage buffers.
4// Component types must be trivially copyable and a multiple of sizeof(float)
5// (e.g. struct Position { float x, y; }).
6
8
9#include "ECS.hpp"
10
11#include <algorithm>
12#include <cstring>
13#include <type_traits>
14#include <vector>
15
16namespace eve::gpgpu {
17
22template <typename Comp>
25public:
26 static_assert(std::is_trivially_copyable_v<Comp>, "EcsGpu component must be trivially copyable");
27 static_assert(sizeof(Comp) >= sizeof(float) && sizeof(Comp) % sizeof(float) == 0,
28 "EcsGpu component size must be a non-zero multiple of float");
29
31 void reserveEntities(int entityCount) {
32 if (entityCount > 0) floats_.reserve(size_t(entityCount) * size_t(sizeof(Comp) / sizeof(float)));
33 }
34
36 size_t entityCapacity() const { return floats_.capacity() / size_t(sizeof(Comp) / sizeof(float)); }
37
38private:
39 template <typename Base, typename C>
41 template <typename Base, typename C>
43 template <typename Base, typename C>
45 template <typename Base, typename C>
47 std::vector<float> floats_;
48};
49
50template <typename Comp>
52constexpr int componentFloatCount() {
53 static_assert(std::is_trivially_copyable_v<Comp>,
54 "EcsGpu component must be trivially copyable");
55 static_assert(sizeof(Comp) % sizeof(float) == 0,
56 "EcsGpu component size must be a multiple of float");
58 return int(sizeof(Comp) / sizeof(float));
59}
60
62template <typename Base, typename Comp>
65 int n = 0;
66 auto view = ecs::View<Base, Comp>();
67 for (auto it = view.begin(); it != view.end(); ++it)
68 ++n;
69 return n;
70}
71
76template <typename Base, typename Comp>
79 const int floatsPer = componentFloatCount<Comp>();
80 int n = 0;
81 {
82 auto view = ecs::View<Base, Comp>();
83 for (auto it = view.begin(); it != view.end(); ++it)
84 ++n;
85 }
86 if (n <= 0) return 0;
87
88 workspace.floats_.resize(size_t(n) * size_t(floatsPer));
89 int i = 0;
90 auto view = ecs::View<Base, Comp>();
91 for (auto it = view.begin(); it != view.end(); ++it) {
92 auto [comp] = *it;
94 std::memcpy(workspace.floats_.data() + size_t(i) * size_t(floatsPer), static_cast<const void *>(comp),
95 sizeof(Comp));
96 ++i;
97 }
98 sys.upload(binding, workspace.floats_.data(), n * floatsPer);
99 return n;
100}
101
103template <typename Base, typename Comp>
106 EcsGpuWorkspace<Comp> workspace;
107 return packViewComponent<Base, Comp>(sys, binding, workspace);
108}
109
114template <typename Base, typename Comp>
117 if (count <= 0) return;
118 const int floatsPer = componentFloatCount<Comp>();
119 workspace.floats_.resize(size_t(count) * size_t(floatsPer));
120 sys.download(binding, workspace.floats_.data(), count * floatsPer);
121 int i = 0;
122 auto view = ecs::View<Base, Comp>();
123 for (auto it = view.begin(); it != view.end() && i < count; ++it) {
124 auto [comp] = *it;
126 std::memcpy(static_cast<void *>(comp), workspace.floats_.data() + size_t(i) * size_t(floatsPer), sizeof(Comp));
127 ++i;
128 }
129}
130
132template <typename Base, typename Comp>
135 EcsGpuWorkspace<Comp> workspace;
136 unpackViewComponent<Base, Comp>(sys, binding, count, workspace);
137}
138
143template <typename Base, typename Comp>
145int packViewComponentRange(ShaderSystem &sys, int binding, int firstEntity, int entityCount,
146 EcsGpuWorkspace<Comp> &workspace) {
147 if (firstEntity < 0 || entityCount <= 0) return 0;
148 const int floatsPer = componentFloatCount<Comp>();
149 workspace.floats_.resize(size_t(entityCount) * size_t(floatsPer));
150 int viewIndex = 0;
151 int packed = 0;
152 auto view = ecs::View<Base, Comp>();
153 for (auto it = view.begin(); it != view.end() && packed < entityCount; ++it, ++viewIndex) {
154 if (viewIndex < firstEntity) continue;
155 auto [comp] = *it;
157 std::memcpy(workspace.floats_.data() + size_t(packed) * size_t(floatsPer), static_cast<const void *>(comp),
158 sizeof(Comp));
159 ++packed;
160 }
161 if (packed > 0) sys.uploadRange(binding, workspace.floats_.data(), packed * floatsPer, firstEntity * floatsPer);
162 return packed;
163}
164
166template <typename Base, typename Comp>
168int unpackViewComponentRange(ShaderSystem &sys, int binding, int firstEntity, int entityCount,
169 EcsGpuWorkspace<Comp> &workspace) {
170 if (firstEntity < 0 || entityCount <= 0) return 0;
171 const int available = std::max(0, countViewEntities<Base, Comp>() - firstEntity);
172 const int count = std::min(entityCount, available);
173 if (count <= 0) return 0;
174 const int floatsPer = componentFloatCount<Comp>();
175 workspace.floats_.resize(size_t(count) * size_t(floatsPer));
176 sys.downloadRange(binding, workspace.floats_.data(), count * floatsPer, firstEntity * floatsPer);
177 int viewIndex = 0;
178 int unpacked = 0;
179 auto view = ecs::View<Base, Comp>();
180 for (auto it = view.begin(); it != view.end() && unpacked < count; ++it, ++viewIndex) {
181 if (viewIndex < firstEntity) continue;
182 auto [comp] = *it;
184 std::memcpy(static_cast<void *>(comp), workspace.floats_.data() + size_t(unpacked) * size_t(floatsPer),
185 sizeof(Comp));
186 ++unpacked;
187 }
188 return unpacked;
189}
190
196template <typename Base, typename Comp>
199 const int n = packViewComponent<Base, Comp>(sys, binding);
200 if (n <= 0) return 0;
201 sys.dispatch(n, dt);
202 unpackViewComponent<Base, Comp>(sys, binding, n);
203 return n;
204}
205
206} // namespace eve::gpgpu
glm::vec3 n
Definition Grass.cpp:63
eve::action::ActionVfxBinding binding
glm::mat4 view
std::uint32_t count
Reusable typed CPU staging for a GPU ECS component stream. Ownership stays with the caller; one works...
Definition EcsGpu.h:24
friend void unpackViewComponent(ShaderSystem &, int, int, EcsGpuWorkspace< C > &)
friend int packViewComponent(ShaderSystem &, int, EcsGpuWorkspace< C > &)
friend int unpackViewComponentRange(ShaderSystem &, int, int, int, EcsGpuWorkspace< C > &)
void reserveEntities(int entityCount)
Reserve staging storage for at least entityCount components.
Definition EcsGpu.h:31
friend int packViewComponentRange(ShaderSystem &, int, int, int, EcsGpuWorkspace< C > &)
size_t entityCapacity() const
Current allocated staging capacity expressed as entity records.
Definition EcsGpu.h:36
EVENGINE_API_WORLD public API.
void upload(int binding, const float *data, int floatCount)
Uploads upload.
void dispatch(int entityCount, float dt=0.f)
Dispatches dispatch.
void downloadRange(int binding, float *out, int floatCount, int startFloat) const
Download floats from an existing resident buffer range.
void download(int binding, float *out, int floatCount) const
Downloads download.
void uploadRange(int binding, const float *data, int floatCount, int startFloat)
Upload floats into an existing resident buffer range.
Fluids module — interactive surface fluid simulation.
Definition Fluids.h:34
void unpackViewComponent(ShaderSystem &sys, int binding, int count, EcsGpuWorkspace< Comp > &workspace)
Write ShaderSystem binding floats back into View<Base, Comp> (same order as pack)....
Definition EcsGpu.h:116
int packViewComponentRange(ShaderSystem &sys, int binding, int firstEntity, int entityCount, EcsGpuWorkspace< Comp > &workspace)
Pack a stable contiguous View range into an existing resident buffer. The full buffer must have been ...
Definition EcsGpu.h:145
int packViewComponent(ShaderSystem &sys, int binding, EcsGpuWorkspace< Comp > &workspace)
Pack View<Base, Comp> into ShaderSystem binding as AoS floats. Returns entity count (0 if empty).
Definition EcsGpu.h:78
int countViewEntities()
Count live entities matching View<Base, Comp>.
Definition EcsGpu.h:64
int unpackViewComponentRange(ShaderSystem &sys, int binding, int firstEntity, int entityCount, EcsGpuWorkspace< Comp > &workspace)
Unpack a stable contiguous resident-buffer range into a matching View range.
Definition EcsGpu.h:168
constexpr int componentFloatCount()
Component float count.
Definition EcsGpu.h:52
int runViewComponentSystem(ShaderSystem &sys, int binding, float dt)
Pack + dispatch + unpack a single-component GPU system. Additional bindings must be uploaded by the c...
Definition EcsGpu.h:198