载入中...
搜索中...
未找到
VulkanVirtualGeometry.cpp
浏览该文件的文档.
5
7#include "gpgpu/GpuBuffer.h"
10
11#include <cstring>
12#include <vector>
13
14namespace eve::virtualgeometry {
15
16namespace vulkan {
17
34
35namespace {
36
37gpgpu::ComputeShader *makeShader(const std::vector<uint32_t> &spv) {
39}
40
41void bindStandard(gpgpu::ComputeShader *s, VgState *st) {
42 if (st->positions) s->bindBuffer(0, st->positions);
43 if (st->triangles) s->bindBuffer(1, st->triangles);
44 if (st->clusters) s->bindBuffer(2, st->clusters);
45 if (st->visible) s->bindBuffer(3, st->visible);
46 if (st->pixels) s->bindBuffer(4, st->pixels);
47 if (st->uniforms) s->bindBuffer(5, st->uniforms);
48 if (st->stats) s->bindBuffer(6, st->stats);
49}
50
51void ensurePixels(VgState *st, int w, int h) {
52 int need = w * h;
53 if (need > st->pixelCapacity) {
54 delete st->pixels;
55 st->pixels = gpgpu::vulkanNewBuffer(need * (int)sizeof(uint32_t), "storage");
56 st->pixelCapacity = need;
57 bindStandard(st->cull, st);
58 bindStandard(st->raster, st);
59 }
60}
61
62} // namespace
63
64} // namespace vulkan
65
66// ---- eve::virtualgeometry backend interface ----
67
69 auto *st = new vulkan::VgState();
70 be.state = st;
71 try {
72 st->cull = vulkan::makeShader(
73 std::vector<uint32_t>(vg_cull_compute_spv, vg_cull_compute_spv + vg_cull_compute_spv_count));
74 st->raster = vulkan::makeShader(
75 std::vector<uint32_t>(vg_raster_compute_spv, vg_raster_compute_spv + vg_raster_compute_spv_count));
76 } catch (...) {
77 delete st;
78 be.state = nullptr;
79 throw;
80 }
81}
82
84 auto *st = static_cast<vulkan::VgState *>(be.state);
85 if (!st) return;
86 delete st->cull;
87 delete st->raster;
88 delete st->positions;
89 delete st->triangles;
90 delete st->clusters;
91 delete st->visible;
92 delete st->pixels;
93 delete st->uniforms;
94 delete st->stats;
95 delete st;
96 be.state = nullptr;
97}
98
99void vgUpload(VgBackend &be, const VirtualGeometryAsset &asset) {
100 auto *st = static_cast<vulkan::VgState *>(be.state);
101 if (!st) return;
102
103 delete st->positions;
104 delete st->triangles;
105 delete st->clusters;
106
107 st->positions = gpgpu::vulkanNewBuffer((int)(asset.positions.size() * sizeof(float)), "storage");
108 st->positions->uploadBytes(asset.positions.data(), asset.positions.size() * sizeof(float));
109
110 st->triangles = gpgpu::vulkanNewBuffer((int)(asset.triangles.size() * sizeof(uint32_t)), "storage");
111 st->triangles->uploadBytes(asset.triangles.data(), asset.triangles.size() * sizeof(uint32_t));
112
113 // Cluster table: 4 uvec4 per cluster (see VgGpuCluster layout).
114 std::vector<uint32_t> packed;
115 packed.reserve(asset.clusters.size() * 16);
116 auto fb = [](float f) {
117 union { float f; uint32_t u; } x;
118 x.f = f;
119 return x.u;
120 };
121 for (const auto &c : asset.clusters) {
122 packed.push_back(fb(c.cx)); packed.push_back(fb(c.cy));
123 packed.push_back(fb(c.cz)); packed.push_back(fb(c.r));
124 packed.push_back(c.triStart); packed.push_back(c.triCount);
125 packed.push_back(c.lodLevel); packed.push_back(c.parent);
126 packed.push_back(fb(c.errorR)); packed.push_back(fb(c.errorRScreen));
127 packed.push_back(c.childCount); packed.push_back(0);
128 for (int k = 0; k < 4; ++k) packed.push_back(c.children[k]);
129 }
130 st->clusters = gpgpu::vulkanNewBuffer((int)(packed.size() * sizeof(uint32_t)), "storage");
131 st->clusters->uploadBytes(packed.data(), packed.size() * sizeof(uint32_t));
132
133 // Per-frame buffers (uniforms / visible / stats / pixels) must exist before
134 // we bind the standard layout so no binding is left null.
135 if (!st->uniforms)
136 st->uniforms = gpgpu::vulkanNewBuffer((int)sizeof(VgUniforms), "storage");
137 if (!st->visible)
138 st->visible = gpgpu::vulkanNewBuffer((st->visibleCapacity + 1) * (int)sizeof(uint32_t),
139 "storage");
140 if (!st->stats)
141 st->stats = gpgpu::vulkanNewBuffer(4 * (int)sizeof(uint32_t), "storage");
142 vulkan::ensurePixels(st, st->viewW, st->viewH);
143
144 vulkan::bindStandard(st->cull, st);
145 vulkan::bindStandard(st->raster, st);
146}
147
149 auto *st = static_cast<vulkan::VgState *>(be.state);
150 if (!st) return;
151 if (!st->uniforms)
152 st->uniforms = gpgpu::vulkanNewBuffer((int)sizeof(VgUniforms), "storage");
153 st->uniforms->uploadBytes(&u, sizeof(VgUniforms));
154 st->cull->bindBuffer(5, st->uniforms);
155 st->raster->bindBuffer(5, st->uniforms);
156}
157
158void vgReset(VgBackend &be, int visibleCapacity) {
159 auto *st = static_cast<vulkan::VgState *>(be.state);
160 if (!st || visibleCapacity <= 0) return;
161 if (st->visibleCapacity == visibleCapacity && st->visible && st->stats) return;
162 st->visibleCapacity = visibleCapacity;
163 delete st->visible;
164 delete st->stats;
165 // [counter, data...]
166 st->visible = gpgpu::vulkanNewBuffer((visibleCapacity + 1) * (int)sizeof(uint32_t), "storage");
167 st->stats = gpgpu::vulkanNewBuffer(4 * (int)sizeof(uint32_t), "storage");
168 st->cull->bindBuffer(3, st->visible);
169 st->cull->bindBuffer(6, st->stats);
170 st->raster->bindBuffer(3, st->visible);
171 st->raster->bindBuffer(6, st->stats);
172}
173
174int vgUpdate(VgBackend &be, int clusterCount, int visibleCapacity, int viewW, int viewH) {
175 auto *st = static_cast<vulkan::VgState *>(be.state);
176 if (!st || !st->cull || !st->raster || !st->visible) return 0;
177 st->visible->fillFloat32(0.f);
178 st->stats->fillFloat32(0.f);
179 if (viewW * viewH > 0) vulkan::ensurePixels(st, viewW, viewH);
180 st->viewW = viewW;
181 st->viewH = viewH;
182 float allOnes = 0.f;
183 std::memcpy(&allOnes, "\xff\xff\xff\xff", 4);
184 st->pixels->fillFloat32(allOnes);
185 int cullGroups = (clusterCount + 63) / 64;
186 gpgpu::vulkanDispatch(st->cull, cullGroups, 1, 1);
187 int rasterThreads = visibleCapacity * 124;
188 int rasterGroups = (rasterThreads + 127) / 128;
189 gpgpu::vulkanDispatch(st->raster, rasterGroups, 1, 1);
190
191 uint32_t counter = 0;
192 st->visible->downloadBytes(&counter, sizeof(counter), 0);
193 st->lastVisible = (int)counter;
194 return st->lastVisible;
195}
196
197bool vgReadPixels(VgBackend &be, std::vector<uint32_t> &out) {
198 auto *st = static_cast<vulkan::VgState *>(be.state);
199 if (!st || !st->pixels || st->viewW <= 0 || st->viewH <= 0) return false;
200 size_t n = (size_t)st->viewW * (size_t)st->viewH;
201 out.resize(n);
202 st->pixels->downloadBytes(out.data(), n * sizeof(uint32_t), 0);
203 return true;
204}
205
206} // namespace eve::virtualgeometry
float u
Definition Grass.cpp:234
int x
Definition Grass.cpp:135
glm::vec3 n
Definition Grass.cpp:64
int h
int w
uint32_t c
float f
uint32_t s
Definition Weather.cpp:28
Backend-agnostic compute program. Bind storage buffers then dispatch via Gpgpu::dispatch....
Backend-agnostic GPU buffer for compute (storage) or CPU staging transfers. Squirrel-owned; derived c...
Definition GpuBuffer.h:16
virtual void fillFloat32(float value)=0
ComputeShader * vulkanNewShaderFromSpirv(const std::vector< uint32_t > &spv)
从 SPIR-V 字节码创建计算着色器。
GpuBuffer * vulkanNewBuffer(int byteSize, const std::string &usage)
创建 GPU 存储/传输缓冲区;usage 为 "storage" | "vertex" 等。
void vulkanDispatch(ComputeShader *shader, int groupsX, int groupsY, int groupsZ)
派发计算着色器(groupsX/Y/Z 为线程组数)。
void vgReset(VgBackend &be, int visibleCapacity)
int vgUpdate(VgBackend &be, int clusterCount, int visibleCapacity, int viewW, int viewH)
void vgUploadUniforms(VgBackend &be, const VgUniforms &u)
bool vgReadPixels(VgBackend &be, std::vector< uint32_t > &out)
void vgCreate(VgBackend &be)
void vgDestroy(VgBackend &be)
void vgUpload(VgBackend &be, const VirtualGeometryAsset &asset)
Opaque backend state for one virtual-geometry renderer. Owned by VirtualGeometryRenderer; allocated/f...
Fully processed virtual-geometry asset (CPU representation). Produced by Builder from a Mesh; uploade...
std::vector< std::uint32_t > triangles
Flat global triangle stream; each entry is an index into positions.