载入中...
搜索中...
未找到
GraphicsMeshPool.cpp
浏览该文件的文档.
1#include <algorithm>
2#include <cstring>
3#include <limits>
6
7namespace eve::graphics::vulkan {
8void Graphics::ensureGpuVertexPool() {
9 if (gpuVertexPool_.positions.buffer) return;
10 constexpr uint32_t kInitialVertices = 256u << 10; // 256k verts (~11 MB total)
11 constexpr uint32_t kInitialIndices = 768u << 10; // 768k u32 indices (3 MB)
12 const auto hostMem = kHostVisibleCoherent;
13 gpuVertexPool_.positions = vkb::GenericBuffer(device, vk::BufferUsageFlagBits::eStorageBuffer,
14 kInitialVertices * sizeof(glm::vec4), hostMem);
15 gpuVertexPool_.normals = vkb::GenericBuffer(device, vk::BufferUsageFlagBits::eStorageBuffer,
16 kInitialVertices * sizeof(glm::vec4), hostMem);
17 gpuVertexPool_.uvs = vkb::GenericBuffer(device, vk::BufferUsageFlagBits::eStorageBuffer,
18 kInitialVertices * sizeof(glm::vec2), hostMem);
19 gpuVertexPool_.indices = vkb::GenericBuffer(device, vk::BufferUsageFlagBits::eStorageBuffer,
20 kInitialIndices * sizeof(uint32_t), hostMem);
21 gpuVertexPool_.vertexCount = 0;
22 gpuVertexPool_.indexCount = 0;
23}
24
25void Graphics::growGpuVertexPool(uint32_t needVertices, uint32_t needIndices) {
26 // Pool growth reallocates the buffers; a pending frame may still be reading
27 // them, so drain the GPU first (rare path: first-time mesh registration).
28 device->waitIdle();
29 const uint32_t oldVerts = gpuVertexPool_.vertexCount;
30 const uint32_t oldInds = gpuVertexPool_.indexCount;
31 const auto hostMem = kHostVisibleCoherent;
32 auto copyInto = [&](vkb::GenericBuffer& dst, vkb::GenericBuffer& src, vk::DeviceSize oldBytes,
33 vk::DeviceSize newBytes) {
34 vkb::GenericBuffer grown(device, vk::BufferUsageFlagBits::eStorageBuffer, newBytes, hostMem);
35 if (oldBytes > 0) {
36 void* srcMap = src.map();
37 void* dstMap = grown.map();
38 std::memcpy(dstMap, srcMap, oldBytes);
39 grown.unmap();
40 src.unmap();
41 }
42 src.release();
43 dst = std::move(grown);
44 };
45 // Leave room after a large first insertion. Exact-fit growth made the next
46 // tiny mesh copy the entire large allocation immediately afterwards.
47 const auto capacity = [](uint32_t needed) {
48 return uint32_t(std::min(uint64_t(needed) * 2u, uint64_t(UINT32_MAX)));
49 };
50 const uint32_t newVerts =
51 std::max(capacity(needVertices), uint32_t(gpuVertexPool_.positions.size / sizeof(glm::vec4)));
52 const uint32_t newInds = std::max(capacity(needIndices), uint32_t(gpuVertexPool_.indices.size / sizeof(uint32_t)));
53 copyInto(gpuVertexPool_.positions, gpuVertexPool_.positions, vk::DeviceSize(oldVerts) * sizeof(glm::vec4),
54 vk::DeviceSize(newVerts) * sizeof(glm::vec4));
55 copyInto(gpuVertexPool_.normals, gpuVertexPool_.normals, vk::DeviceSize(oldVerts) * sizeof(glm::vec4),
56 vk::DeviceSize(newVerts) * sizeof(glm::vec4));
57 copyInto(gpuVertexPool_.uvs, gpuVertexPool_.uvs, vk::DeviceSize(oldVerts) * sizeof(glm::vec2),
58 vk::DeviceSize(newVerts) * sizeof(glm::vec2));
59 copyInto(gpuVertexPool_.indices, gpuVertexPool_.indices, vk::DeviceSize(oldInds) * sizeof(uint32_t),
60 vk::DeviceSize(newInds) * sizeof(uint32_t));
61 bindGpuVertexPoolBindless();
62}
63
64void Graphics::bindGpuVertexPoolBindless() {
65 if (bindlessSets_.empty() || !gpuVertexPool_.positions.buffer) return;
66 auto bufWrite = [&](vk::DescriptorSet set, uint32_t binding, vk::Buffer buffer, vk::DeviceSize size) {
67 vk::DescriptorBufferInfo info{buffer, 0, size};
68 vk::WriteDescriptorSet w{};
69 w.dstSet = set;
70 w.dstBinding = binding;
71 w.descriptorCount = 1;
72 w.descriptorType = vk::DescriptorType::eStorageBuffer;
73 w.pBufferInfo = &info;
74 device->updateDescriptorSets(1, &w, 0, nullptr);
75 };
76 const uint32_t cap = [&]() {
77 const vk::DeviceSize bytes = gpuVertexPool_.positions.size;
78 return uint32_t(bytes / sizeof(glm::vec4));
79 }();
80 const uint32_t indCap = uint32_t(gpuVertexPool_.indices.size / sizeof(uint32_t));
81 for (vk::DescriptorSet set : bindlessSets_) {
82 bufWrite(set, 18, gpuVertexPool_.positions.buffer, vk::DeviceSize(cap) * sizeof(glm::vec4));
83 bufWrite(set, 19, gpuVertexPool_.normals.buffer, vk::DeviceSize(cap) * sizeof(glm::vec4));
84 bufWrite(set, 20, gpuVertexPool_.uvs.buffer, vk::DeviceSize(cap) * sizeof(glm::vec2));
85 bufWrite(set, 21, gpuVertexPool_.indices.buffer, vk::DeviceSize(indCap) * sizeof(uint32_t));
86 }
87}
88
89void Graphics::appendGpuMeshToPool(GpuMesh& gpu, const std::vector<MeshVertex>* vertices,
90 const std::vector<uint32_t>* indices) {
91 if (!gpu.vertices.buffer || !gpu.indices.buffer) return;
92 ensureGpuVertexPool();
93 const uint32_t nVerts = gpu.record.vertexCount;
94 const uint32_t nInds = gpu.record.indexCount;
95 if (nVerts == 0 || nInds == 0) return;
96 const uint32_t newVerts = gpuVertexPool_.vertexCount + nVerts;
97 const uint32_t newInds = gpuVertexPool_.indexCount + nInds;
98 const uint32_t capVerts = uint32_t(gpuVertexPool_.positions.size / sizeof(glm::vec4));
99 const uint32_t capInds = uint32_t(gpuVertexPool_.indices.size / sizeof(uint32_t));
100 if (newVerts > capVerts || newInds > capInds) {
101 growGpuVertexPool(newVerts, newInds);
102 }
103
104 const void* vMap = vertices ? vertices->data() : gpu.vertices.map();
105 const void* iMap = indices ? indices->data() : gpu.indices.map();
106 if (!vMap || !iMap) return;
107 auto* verts = static_cast<const MeshVertex*>(vMap);
108 auto* posDst = static_cast<glm::vec4*>(gpuVertexPool_.positions.map());
109 auto* nrmDst = static_cast<glm::vec4*>(gpuVertexPool_.normals.map());
110 auto* uvDst = static_cast<glm::vec2*>(gpuVertexPool_.uvs.map());
111 auto* idxDst = static_cast<uint32_t*>(gpuVertexPool_.indices.map());
112 if (!posDst || !nrmDst || !uvDst || !idxDst) {
113 if (!vertices) gpu.vertices.unmap();
114 if (!indices) gpu.indices.unmap();
115 return;
116 }
117 posDst += gpuVertexPool_.vertexCount;
118 nrmDst += gpuVertexPool_.vertexCount;
119 uvDst += gpuVertexPool_.vertexCount;
120 idxDst += gpuVertexPool_.indexCount;
121 for (uint32_t i = 0; i < nVerts; ++i) {
122 posDst[i] = glm::vec4(verts[i].pos, 0.f);
123 nrmDst[i] = glm::vec4(verts[i].normal, 0.f);
124 uvDst[i] = verts[i].uv;
125 }
126 if (!indices && gpu.indexType == vk::IndexType::eUint16) {
127 const auto* src16 = static_cast<const uint16_t*>(iMap);
128 for (uint32_t i = 0; i < nInds; ++i) idxDst[i] = uint32_t(src16[i]);
129 } else {
130 const auto* src32 = static_cast<const uint32_t*>(iMap);
131 for (uint32_t i = 0; i < nInds; ++i) idxDst[i] = src32[i];
132 }
133 gpuVertexPool_.positions.unmap();
134 gpuVertexPool_.normals.unmap();
135 gpuVertexPool_.uvs.unmap();
136 gpuVertexPool_.indices.unmap();
137 if (!vertices) gpu.vertices.unmap();
138 if (!indices) gpu.indices.unmap();
139
140 // Pool offsets are vertex/index counts, resolved by the vis shaders.
141 gpu.record.vertexOffset = gpuVertexPool_.vertexCount;
142 gpu.record.indexOffset = gpuVertexPool_.indexCount;
143 gpu.record.firstIndex = 0; // vis pass draws non-indexed from the pool
144 gpu.record.vertexBase = 0;
145 gpuVertexPool_.vertexCount = newVerts;
146 gpuVertexPool_.indexCount = newInds;
147}
148
149uint32_t Graphics::registerMeshRecord(GpuMesh* gpu, const std::vector<MeshVertex>* vertices,
150 const std::vector<uint32_t>* indices) {
151 if (!gpu) return kInvalidBindlessSlot;
152 if (gpu->gpuRecordIndex != kInvalidBindlessSlot) return gpu->gpuRecordIndex;
153 if (meshTableRecords_.size() >= meshTableCapacity_) return kInvalidBindlessSlot;
154 // dev's mesh factories do not populate GpuMeshRecord; build it on first
155 // registration from the host-visible buffers (bounds + ranges).
156 if (gpu->record.vertexCount == 0 && gpu->vertices.buffer) {
157 const uint32_t vertexCount = uint32_t(gpu->vertices.size / sizeof(MeshVertex));
158 gpu->record.vertexCount = vertexCount;
159 gpu->record.indexCount = gpu->indexCount;
160 gpu->record.indexType = gpu->indexType == vk::IndexType::eUint16 ? 0u : 1u;
161 const void* map = vertices ? vertices->data() : gpu->vertices.map();
162 if (map && vertexCount > 0) {
163 const auto* verts = static_cast<const MeshVertex*>(map);
164 glm::vec3 minv(1e30f), maxv(-1e30f);
165 for (uint32_t i = 0; i < vertexCount; ++i) {
166 minv = glm::min(minv, verts[i].pos);
167 maxv = glm::max(maxv, verts[i].pos);
168 }
169 const glm::vec3 center = (minv + maxv) * 0.5f;
170 float radius = 0.f;
171 for (uint32_t i = 0; i < vertexCount; ++i) radius = std::max(radius, glm::length(verts[i].pos - center));
172 gpu->record.boundsCenterRadius = glm::vec4(center, radius);
173 }
174 if (map && !vertices) gpu->vertices.unmap();
175 }
176 // Stage 3: lazily pool the mesh's vertices/indices so the vis resolve can
177 // fetch attributes by (pool offset + triangle + barycentric).
178 appendGpuMeshToPool(*gpu, vertices, indices);
179 const uint32_t idx = uint32_t(meshTableRecords_.size());
180 meshTableRecords_.push_back(gpu->record);
181 meshRecordOwners_.push_back(gpu);
182 gpu->gpuRecordIndex = idx;
183 syncMeshTable();
184 return idx;
185}
186
187
188} // namespace eve::graphics::vulkan
float w
Definition AnimClip.cpp:738
std::vector< std::uint32_t > verts
Definition Builder.cpp:27
std::uint32_t vertexCount
std::uint32_t capacity
float u
Definition Grass.cpp:233
std::vector< std::uint32_t > indices
std::uint64_t bytes
Texture * normal
std::unique_ptr< gpgpu::GpuBuffer > buffer
Definition OnnxGpgpu.cpp:26
eve::action::ActionVfxBinding binding
int idx
std::vector< Point > vertices
float radius
float size
Definition TreeMesh.cpp:156
constexpr uint32_t kInvalidBindlessSlot
Definition GpuDriven.h:22
glm::uvec4 info