载入中...
搜索中...
未找到
VulkanGpgpu.cpp
浏览该文件的文档.
5
6#include "common/Exception.h"
8
9namespace eve::gpgpu {
10
12
13ComputeShader *vulkanNewShaderFromSpirv(const std::vector<uint32_t> &spv) {
14 auto *vkg = requireVulkanGraphics();
15 auto &device = vkg->getDevice();
16
17 auto shader = std::make_unique<VulkanComputeShader>();
18 shader->device_ = &device;
19 shader->module_ = vkb::PipelineBuilder::createShaderModule(device.instance, spv);
20
21 // Fixed layout: set 0, bindings 0..N-1 = storage buffers (compute stage).
22 std::vector<vk::DescriptorSetLayoutBinding> bindings;
24 for (int i = 0; i < ComputeShader::kMaxBindings; ++i) {
25 vk::DescriptorSetLayoutBinding b{};
26 b.binding = uint32_t(i);
27 b.descriptorType = vk::DescriptorType::eStorageBuffer;
28 b.descriptorCount = 1;
29 b.stageFlags = vk::ShaderStageFlagBits::eCompute;
30 bindings.push_back(b);
31 }
32 vk::DescriptorSetLayoutCreateInfo layoutInfo{};
33 layoutInfo.bindingCount = uint32_t(bindings.size());
34 layoutInfo.pBindings = bindings.data();
35 shader->setLayout_ = device->createDescriptorSetLayout(layoutInfo, device.allocation_callbacks);
36
37 vk::PushConstantRange pcr{};
38 pcr.stageFlags = vk::ShaderStageFlagBits::eCompute;
39 pcr.offset = 0;
41
42 vk::PipelineLayoutCreateInfo plInfo{};
43 plInfo.setLayoutCount = 1;
44 plInfo.pSetLayouts = &shader->setLayout_;
45 plInfo.pushConstantRangeCount = 1;
46 plInfo.pPushConstantRanges = &pcr;
47 shader->pipelineLayout_ = device->createPipelineLayout(plInfo, device.allocation_callbacks);
48
49 vk::PipelineShaderStageCreateInfo stage{};
50 stage.stage = vk::ShaderStageFlagBits::eCompute;
51 stage.module = shader->module_;
52 stage.pName = "main";
53
54 vk::ComputePipelineCreateInfo cpInfo{};
55 cpInfo.stage = stage;
56 cpInfo.layout = shader->pipelineLayout_;
57 auto result = device->createComputePipeline(vk::PipelineCache{}, cpInfo, device.allocation_callbacks);
58 if (result.result != vk::Result::eSuccess) {
59 throw Exception("Gpgpu.newShader: createComputePipeline failed");
60 }
61 shader->pipeline_ = result.value;
62 return shader.release();
63}
64
65GpuBuffer *vulkanNewBuffer(int byteSize, const std::string &usage) {
66 if (byteSize <= 0) throw Exception("Gpgpu.newBuffer: byteSize must be > 0");
67 auto *vkg = requireVulkanGraphics();
68 auto &device = vkg->getDevice();
69
70 const bool staging = (usage == "staging");
71 const bool storage = (usage == "storage" || usage.empty());
72 if (!staging && !storage)
73 throw Exception("Gpgpu.newBuffer: usage must be \"storage\" or \"staging\"");
74
75 using buf = vk::BufferUsageFlagBits;
76 using pfb = vk::MemoryPropertyFlagBits;
77
78 vk::BufferUsageFlags flags = buf::eTransferSrc | buf::eTransferDst;
79 if (storage || staging) flags |= buf::eStorageBuffer;
80
81 vk::MemoryPropertyFlags mem =
82 staging ? (pfb::eHostVisible | pfb::eHostCoherent) : pfb::eDeviceLocal;
83
84 auto b = std::make_unique<VulkanGpuBuffer>();
85 b->device_ = &device;
86 b->size_ = vk::DeviceSize(byteSize);
87 b->usage_ = staging ? "staging" : "storage";
88 b->hostVisible_ = staging;
89
90#if defined(VKB_ENABLE_VMA)
91 if (staging && device.hasVmaAllocator()) {
92 // Readback must prefer CPU-cached memory. Host coherence alone can select
93 // uncached memory, making the CPU memcpy much slower than the GPU copy.
94 // Coherence remains required; cached memory is only a performance preference.
95 VkBufferCreateInfo info{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
96 info.size = b->size_;
97 info.usage = static_cast<VkBufferUsageFlags>(flags);
98 info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
99 VmaAllocationCreateInfo allocation{};
100 allocation.requiredFlags = static_cast<VkMemoryPropertyFlags>(mem);
101 allocation.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
102 VkBuffer rawBuffer = VK_NULL_HANDLE;
103 VmaAllocationInfo allocated{};
104 const VkResult result =
105 vmaCreateBuffer(device.vma_allocator, &info, &allocation, &rawBuffer, &b->vmaAllocation_, &allocated);
106 if (result != VK_SUCCESS) throw Exception("Gpgpu.newBuffer: staging allocation failed: %d", int(result));
107 b->buffer_ = rawBuffer;
108 b->memory_ = allocated.deviceMemory;
109 return b.release();
110 }
111#endif
112
113 vkb::GenericBuffer tmp(device, flags, b->size_, mem);
114 b->buffer_ = tmp.buffer;
115 b->memory_ = tmp.memory;
116#if defined(VKB_ENABLE_VMA)
117 b->vmaAllocation_ = tmp.vma_allocation;
118#endif
119 tmp.detach();
120 return b.release();
121}
122
123void vulkanDispatch(ComputeShader *shader, int groupsX, int groupsY, int groupsZ) {
124 auto *vs = dynamic_cast<VulkanComputeShader *>(shader);
125 if (!vs || !vs->pipeline_) return;
126 if (groupsX <= 0) groupsX = 1;
127 if (groupsY <= 0) groupsY = 1;
128 if (groupsZ <= 0) groupsZ = 1;
129
130 auto *vkg = requireVulkanGraphics();
131 auto &device = vkg->getDevice();
132 auto queue = computeQueue(vkg);
133 auto pool = computeCommandPool(vkg);
134 if (!queue) throw Exception("Gpgpu.dispatch: no compute/graphics queue");
135
136 vs->flushDescriptors(device);
137
138 vkb::executeImmediately(device.instance, pool, queue, [&](vk::CommandBuffer cb) {
139 cb.bindPipeline(vk::PipelineBindPoint::eCompute, vs->pipeline_);
140 if (vs->descriptorSet_) {
141 cb.bindDescriptorSets(vk::PipelineBindPoint::eCompute, vs->pipelineLayout_, 0,
142 vs->descriptorSet_, nullptr);
143 }
144 cb.pushConstants(vs->pipelineLayout_, vk::ShaderStageFlagBits::eCompute, 0,
145 ComputeShader::kPushConstantBytes, vs->pushConstantData());
146 cb.dispatch(uint32_t(groupsX), uint32_t(groupsY), uint32_t(groupsZ));
147 });
148}
149
150} // namespace eve::gpgpu
std::string usage
vkb::Device & device
MeleePoint3 b
Definition MeleeHit.cpp:41
std::vector< std::shared_ptr< DeviceBytes > > bindings
Definition OnnxGpgpu.cpp:38
Shader * shader
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
Backend-agnostic compute program. Bind storage buffers then dispatch via Gpgpu::dispatch....
static constexpr int kMaxBindings
static constexpr uint32_t kPushConstantBytes
Backend-agnostic GPU buffer for compute (storage) or CPU staging transfers. Squirrel-owned; derived c...
Definition GpuBuffer.h:18
Vulkan 计算着色器(SPIR-V pipeline + descriptor 管理)。
Fluids module — interactive surface fluid simulation.
Definition Fluids.h:34
bool vulkanGpgpuReady()
Vulkan 后端是否就绪(设备/队列可用)。
ComputeShader * vulkanNewShaderFromSpirv(const std::vector< uint32_t > &spv)
从 SPIR-V 字节码创建计算着色器。
bool vulkanGraphicsReady()
True if Vulkan Graphics device is ready.
GpuBuffer * vulkanNewBuffer(int byteSize, const std::string &usage)
创建 GPU 存储/传输缓冲区;usage 为 "storage" | "vertex" 等。
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.
void vulkanDispatch(ComputeShader *shader, int groupsX, int groupsY, int groupsZ)
派发计算着色器(groupsX/Y/Z 为线程组数)。
glm::uvec4 info