载入中...
搜索中...
未找到
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 = new 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;
23 bindings.reserve(ComputeShader::kMaxBindings);
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 delete shader;
60 throw Exception("Gpgpu.newShader: createComputePipeline failed");
61 }
62 shader->pipeline_ = result.value;
63 return shader;
64}
65
66GpuBuffer *vulkanNewBuffer(int byteSize, const std::string &usage) {
67 if (byteSize <= 0) throw Exception("Gpgpu.newBuffer: byteSize must be > 0");
68 auto *vkg = requireVulkanGraphics();
69 auto &device = vkg->getDevice();
70
71 const bool staging = (usage == "staging");
72 const bool storage = (usage == "storage" || usage.empty());
73 if (!staging && !storage)
74 throw Exception("Gpgpu.newBuffer: usage must be \"storage\" or \"staging\"");
75
76 using buf = vk::BufferUsageFlagBits;
77 using pfb = vk::MemoryPropertyFlagBits;
78
79 vk::BufferUsageFlags flags = buf::eTransferSrc | buf::eTransferDst;
80 if (storage || staging) flags |= buf::eStorageBuffer;
81
82 vk::MemoryPropertyFlags mem =
83 staging ? (pfb::eHostVisible | pfb::eHostCoherent) : pfb::eDeviceLocal;
84
85 auto *b = new VulkanGpuBuffer();
86 b->device_ = &device;
87 b->size_ = vk::DeviceSize(byteSize);
88 b->usage_ = staging ? "staging" : "storage";
89 b->hostVisible_ = staging;
90
91 vkb::GenericBuffer tmp(device, flags, b->size_, mem);
92 b->buffer_ = tmp.buffer;
93 b->memory_ = tmp.memory;
94 tmp.detach();
95 return b;
96}
97
98void vulkanDispatch(ComputeShader *shader, int groupsX, int groupsY, int groupsZ) {
99 auto *vs = dynamic_cast<VulkanComputeShader *>(shader);
100 if (!vs || !vs->pipeline_) return;
101 if (groupsX <= 0) groupsX = 1;
102 if (groupsY <= 0) groupsY = 1;
103 if (groupsZ <= 0) groupsZ = 1;
104
105 auto *vkg = requireVulkanGraphics();
106 auto &device = vkg->getDevice();
107 auto queue = computeQueue(vkg);
108 auto pool = computeCommandPool(vkg);
109 if (!queue) throw Exception("Gpgpu.dispatch: no compute/graphics queue");
110
111 vs->flushDescriptors(device);
112
113 vkb::executeImmediately(device.instance, pool, queue, [&](vk::CommandBuffer cb) {
114 cb.bindPipeline(vk::PipelineBindPoint::eCompute, vs->pipeline_);
115 if (vs->descriptorSet_) {
116 cb.bindDescriptorSets(vk::PipelineBindPoint::eCompute, vs->pipelineLayout_, 0,
117 vs->descriptorSet_, nullptr);
118 }
119 cb.pushConstants(vs->pipelineLayout_, vk::ShaderStageFlagBits::eCompute, 0,
120 ComputeShader::kPushConstantBytes, vs->pushConstantData());
121 cb.dispatch(uint32_t(groupsX), uint32_t(groupsY), uint32_t(groupsZ));
122 });
123}
124
125} // namespace eve::gpgpu
vkb::Device & device
uint32_t b
Shader * shader
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:16
Vulkan 计算着色器(SPIR-V pipeline + descriptor 管理)。
Vulkan 计算缓冲区实现(storage/vertex buffer + device memory)。
ComputeShader * vulkanNewShaderFromSpirv(const std::vector< uint32_t > &spv)
从 SPIR-V 字节码创建计算着色器。
GpuBuffer * vulkanNewBuffer(int byteSize, const std::string &usage)
创建 GPU 存储/传输缓冲区;usage 为 "storage" | "vertex" 等。
bool vulkanGpgpuReady()
Vulkan 后端是否就绪(设备/队列可用)。
bool vulkanGraphicsReady()
True if Vulkan Graphics device is ready.
void vulkanDispatch(ComputeShader *shader, int groupsX, int groupsY, int groupsZ)
派发计算着色器(groupsX/Y/Z 为线程组数)。
vk::Queue computeQueue(graphics::vulkan::Graphics *vkg)
graphics::vulkan::Graphics * requireVulkanGraphics()
Resolve live Vulkan Graphics (throws if missing / not initialized).
vk::CommandPool computeCommandPool(graphics::vulkan::Graphics *vkg)