15 auto &
device = vkg->getDevice();
17 auto shader = std::make_unique<VulkanComputeShader>();
19 shader->module_ = vkb::PipelineBuilder::createShaderModule(
device.instance, spv);
22 std::vector<vk::DescriptorSetLayoutBinding>
bindings;
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;
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);
37 vk::PushConstantRange pcr{};
38 pcr.stageFlags = vk::ShaderStageFlagBits::eCompute;
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);
49 vk::PipelineShaderStageCreateInfo stage{};
50 stage.stage = vk::ShaderStageFlagBits::eCompute;
51 stage.module =
shader->module_;
54 vk::ComputePipelineCreateInfo cpInfo{};
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");
61 shader->pipeline_ = result.value;
66 if (byteSize <= 0)
throw Exception(
"Gpgpu.newBuffer: byteSize must be > 0");
68 auto &
device = vkg->getDevice();
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\"");
75 using buf = vk::BufferUsageFlagBits;
76 using pfb = vk::MemoryPropertyFlagBits;
78 vk::BufferUsageFlags flags = buf::eTransferSrc | buf::eTransferDst;
79 if (storage || staging) flags |= buf::eStorageBuffer;
81 vk::MemoryPropertyFlags mem =
82 staging ? (pfb::eHostVisible | pfb::eHostCoherent) : pfb::eDeviceLocal;
84 auto b = std::make_unique<VulkanGpuBuffer>();
86 b->size_ = vk::DeviceSize(byteSize);
87 b->usage_ = staging ?
"staging" :
"storage";
88 b->hostVisible_ = staging;
90#if defined(VKB_ENABLE_VMA)
91 if (staging &&
device.hasVmaAllocator()) {
95 VkBufferCreateInfo
info{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
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;
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;
125 if (!vs || !vs->pipeline_)
return;
126 if (groupsX <= 0) groupsX = 1;
127 if (groupsY <= 0) groupsY = 1;
128 if (groupsZ <= 0) groupsZ = 1;
131 auto &
device = vkg->getDevice();
134 if (!queue)
throw Exception(
"Gpgpu.dispatch: no compute/graphics queue");
136 vs->flushDescriptors(
device);
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);
144 cb.pushConstants(vs->pipelineLayout_, vk::ShaderStageFlagBits::eCompute, 0,
146 cb.dispatch(uint32_t(groupsX), uint32_t(groupsY), uint32_t(groupsZ));