载入中...
搜索中...
未找到
GraphicsSkin.cpp
浏览该文件的文档.
3
4namespace eve::graphics::vulkan {
5// Per-frame, per-draw storage: queued draws own snapshots until the frame fence.
6// A slot can grow only before that slot has been referenced by this frame.
7size_t Graphics::uploadSkinPalette(Mesh* mesh, Mesh3dFrameSlots& fslots) {
8 const bool skinned = mesh && mesh->hasGpuSkinning() && mesh->getSkinPaletteCount() > 0;
9 const size_t slot = skinned ? fslots.drawIndex + 1 : 0;
10 const size_t bytes = skinned ? mesh->skinPalette().size() * sizeof(float) : sizeof(glm::mat4);
11 if (bytes > device.physical_device.properties.limits.maxStorageBufferRange)
12 throw Exception("Skin palette exceeds device maxStorageBufferRange");
13 if (fslots.palettes.size() <= slot) fslots.palettes.resize(slot + 1);
14 auto& buffer = fslots.palettes[slot];
15 if (!buffer.buffer || buffer.capacity < bytes) {
16 buffer.allocate(frameToken(), device, vk::BufferUsageFlagBits::eStorageBuffer, bytes, kHostVisibleCoherent);
17 // The fence protects earlier frames. Other slots used this frame retain
18 // their buffers and published descriptor sets unchanged.
19 fslots.sets.clear();
20 fslots.skinSets.clear();
21 }
22 const glm::mat4 identity(1.f);
23 updateRingLocal(buffer, 0, skinned ? mesh->skinPalette().data() : &identity[0][0], bytes);
24 fslots.activePalette = slot;
25 return slot;
26}
27
28vk::DescriptorSet Graphics::skinPassSetFor(GpuTexture* albedo, Mesh3dFrameSlots& fslots) {
29 const auto key = std::make_pair(fslots.activePalette, albedo);
30 auto it = fslots.skinSets.find(key);
31 if (it != fslots.skinSets.end()) return it->second;
32 vk::DescriptorSetAllocateInfo alloc{};
33 alloc.descriptorPool = descriptorPool;
34 alloc.descriptorSetCount = 1;
35 alloc.pSetLayouts = &skinPassSetLayout;
36 vkb::UnboundSet unbound{device->allocateDescriptorSets(alloc).front()};
37 vkb::DescriptorSetUpdater updater(2, 1, 0);
38 updater.beginDescriptorSet(unbound)
39 .beginBuffers(0, 0, vk::DescriptorType::eUniformBufferDynamic)
40 .buffer(fslots.uboRing.buffer, 0, sizeof(SkinPassUBO))
41 .beginBuffers(2, 0, vk::DescriptorType::eStorageBuffer)
42 .buffer(fslots.palettes[fslots.activePalette].buffer, 0, fslots.palettes[fslots.activePalette].capacity)
43 .beginImages(1, 0, vk::DescriptorType::eCombinedImageSampler)
44 .image(vkb::SampledImage::forLaterSample(albedo->sampler, albedo->imageView()))
45 .update(device.instance);
46 vkb::BoundSet bound = std::move(unbound).publish();
47 auto [inserted, ignored] = fslots.skinSets.emplace(key, bound);
48 return inserted->second;
49}
50
51bool Graphics::prepareSkinPass(Mesh* mesh, Texture* albedo, const glm::mat4& mvp, const glm::mat4& model,
52 const glm::vec4& clip, vk::DescriptorSet& set, uint32_t& uboOffset) {
53 if (!mesh || !mesh->hasGpuSkinning()) return false;
54 auto& fslots = currentMesh3dFrameSlots();
55 // A 3D frame can inherit an already-open present command buffer (for
56 // example, when script-side 2D clear work precedes render3D). In that
57 // path begin3DFrame may not have initialized this slot yet. Allocate the
58 // empty slot lazily before the first skinned draw; no recorded command can
59 // reference it while capacity is zero.
60 if (!fslots.uboRing.buffer || fslots.capacity == 0) ensureMesh3dRing(fslots);
61 if (fslots.drawIndex >= fslots.capacity) {
62 std::fprintf(stderr, "[vulkan] skin pass UBO ring exhausted (%zu draws); draw skipped\n", fslots.capacity);
63 return false;
64 }
65 SkinPassUBO ubo;
66 ubo.mvp = mvp;
67 ubo.model = model;
68 ubo.clip = clip;
69 ubo.skinInfo.x = static_cast<float>(mesh->getSkinPaletteCount());
70 ubo.skinInfo.y = static_cast<float>(mesh3dSkinInfluenceLimit);
71 uploadSkinPalette(mesh, fslots);
72 const size_t slot = fslots.drawIndex++;
73 ensureMesh3dStrides();
74 uboOffset = uint32_t(slot) * mesh3dUboStride;
75 updateRingLocal(fslots.uboRing, uboOffset, &ubo, sizeof(ubo));
76 Texture* texture = albedo ? albedo : whiteTexture;
77 if (!texture || !texture->gpuHandle) return false;
78 set = skinPassSetFor(static_cast<GpuTexture*>(texture->gpuHandle), fslots);
79 return bool(set);
80}
81
82
83} // namespace eve::graphics::vulkan
graphics::Texture * albedo
std::uint32_t key
glm::vec4 clip
glm::mat4 mvp
std::uint64_t bytes
std::unique_ptr< gpgpu::GpuBuffer > buffer
Definition OnnxGpgpu.cpp:26
Mesh * mesh
glm::mat4 model