ngscopeclient 0.1-dev+51fbda87c
ComputePipeline.h
Go to the documentation of this file.
1/***********************************************************************************************************************
2* *
3* libscopeprotocols *
4* *
5* Copyright (c) 2012-2024 Andrew D. Zonenberg and contributors *
6* All rights reserved. *
7* *
8* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
9* following conditions are met: *
10* *
11* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
12* following disclaimer. *
13* *
14* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
15* following disclaimer in the documentation and/or other materials provided with the distribution. *
16* *
17* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
18* derived from this software without specific prior written permission. *
19* *
20* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
21* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
22* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
23* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
25* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
26* POSSIBILITY OF SUCH DAMAGE. *
27* *
28***********************************************************************************************************************/
29
36#ifndef ComputePipeline_h
37#define ComputePipeline_h
38
39#include "scopehal.h"
40#include "AcceleratorBuffer.h"
41
55{
56public:
58 const std::string& shaderPath,
59 size_t numSSBOs,
60 size_t pushConstantSize,
61 size_t numStorageImages = 0,
62 size_t numSampledImages = 0);
63 virtual ~ComputePipeline();
64
65 void Reinitialize(
66 const std::string& shaderPath,
67 size_t numSSBOs,
68 size_t pushConstantSize,
69 size_t numStorageImages = 0,
70 size_t numSampledImages = 0);
71
82 template<class T>
83 void BindBuffer(size_t i, AcceleratorBuffer<T>& buf, bool outputOnly = false)
84 {
85 if(m_computePipeline == nullptr)
87
88 buf.PrepareForGpuAccess(outputOnly);
89
90 m_bufferInfo[i] = buf.GetBufferInfo();
92 {
94 vk::WriteDescriptorSet(nullptr, i, 0, vk::DescriptorType::eStorageBuffer, {}, m_bufferInfo[i]);
95 }
96 else
97 {
99 vk::WriteDescriptorSet(**m_descriptorSet, i, 0, vk::DescriptorType::eStorageBuffer, {}, m_bufferInfo[i]);
100 }
101 }
102
111 void BindStorageImage(size_t i, vk::Sampler sampler, vk::ImageView view, vk::ImageLayout layout)
112 {
113 if(m_computePipeline == nullptr)
114 DeferredInit();
115
116 size_t numImage = i - m_numSSBOs;
117 m_storageImageInfo[numImage] = vk::DescriptorImageInfo(sampler, view, layout);
118
120 {
121 m_writeDescriptors[i] = vk::WriteDescriptorSet(
122 nullptr, i, 0, vk::DescriptorType::eStorageImage, m_storageImageInfo[numImage]);
123 }
124 else
125 {
126 m_writeDescriptors[i] = vk::WriteDescriptorSet(
127 **m_descriptorSet, i, 0, vk::DescriptorType::eStorageImage, m_storageImageInfo[numImage]);
128 }
129 }
130
139 void BindSampledImage(size_t i, vk::Sampler sampler, vk::ImageView view, vk::ImageLayout layout)
140 {
141 if(m_computePipeline == nullptr)
142 DeferredInit();
143
144 size_t numImage = i - (m_numSSBOs + m_numStorageImages);
145 m_sampledImageInfo[numImage] = vk::DescriptorImageInfo(sampler, view, layout);
146
148 {
149 m_writeDescriptors[i] = vk::WriteDescriptorSet(
150 nullptr, i, 0, vk::DescriptorType::eCombinedImageSampler, m_sampledImageInfo[numImage]);
151 }
152 else
153 {
154 m_writeDescriptors[i] = vk::WriteDescriptorSet(
155 **m_descriptorSet, i, 0, vk::DescriptorType::eCombinedImageSampler, m_sampledImageInfo[numImage]);
156 }
157 }
158
170 template<class T>
172 size_t i, AcceleratorBuffer<T>& buf, vk::raii::CommandBuffer& cmdBuf, bool outputOnly = false)
173 {
174 if(buf.empty())
175 {
176 LogWarning("Attempted to bind an empty buffer\n");
177 return;
178 }
179
180 if(m_computePipeline == nullptr)
181 DeferredInit();
182
183 buf.PrepareForGpuAccessNonblocking(outputOnly, cmdBuf);
184
185 m_bufferInfo[i] = buf.GetBufferInfo();
187 {
189 vk::WriteDescriptorSet(nullptr, i, 0, vk::DescriptorType::eStorageBuffer, {}, m_bufferInfo[i]);
190 }
191 else
192 {
194 vk::WriteDescriptorSet(**m_descriptorSet, i, 0, vk::DescriptorType::eStorageBuffer, {}, m_bufferInfo[i]);
195 }
196 }
197
203 static void AddComputeMemoryBarrier(vk::raii::CommandBuffer& cmdBuf)
204 {
205 cmdBuf.pipelineBarrier(
206 vk::PipelineStageFlagBits::eComputeShader,
207 vk::PipelineStageFlagBits::eComputeShader,
208 {},
209 vk::MemoryBarrier(vk::AccessFlagBits::eShaderWrite, vk::AccessFlagBits::eShaderRead),
210 {},
211 {});
212 }
213
219 void Bind(vk::raii::CommandBuffer& cmdBuf)
220 {
221 if(m_computePipeline == nullptr)
222 DeferredInit();
223 cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, **m_computePipeline);
224 }
225
241 template<class T>
242 void Dispatch(vk::raii::CommandBuffer& cmdBuf, T pushConstants, uint32_t x, uint32_t y=1, uint32_t z=1)
243 {
245 g_vkComputeDevice->updateDescriptorSets(m_writeDescriptors, nullptr);
246
247 Bind(cmdBuf);
248 cmdBuf.pushConstants<T>(
250 vk::ShaderStageFlagBits::eCompute,
251 0,
252 pushConstants);
253
255 {
256 cmdBuf.pushDescriptorSetKHR(
257 vk::PipelineBindPoint::eCompute,
259 0,
261 );
262 }
263 else
264 {
265 cmdBuf.bindDescriptorSets(
266 vk::PipelineBindPoint::eCompute,
268 0,
270 {});
271 }
272 cmdBuf.dispatch(x, y, z);
273 }
274
290 template<class T>
291 void DispatchNoRebind(vk::raii::CommandBuffer& cmdBuf, T pushConstants, uint32_t x, uint32_t y=1, uint32_t z=1)
292 {
294 {
295 cmdBuf.pushDescriptorSetKHR(
296 vk::PipelineBindPoint::eCompute,
298 0,
300 );
301 }
302
303 cmdBuf.pushConstants<T>(
305 vk::ShaderStageFlagBits::eCompute,
306 0,
307 pushConstants);
308 cmdBuf.dispatch(x, y, z);
309 }
310
311protected:
312 void DeferredInit();
313
315 std::string m_shaderPath;
316
319
322
325
328
330 std::unique_ptr<vk::raii::ShaderModule> m_shaderModule;
331
333 std::unique_ptr<vk::raii::Pipeline> m_computePipeline;
334
336 std::unique_ptr<vk::raii::PipelineLayout> m_pipelineLayout;
337
339 std::unique_ptr<vk::raii::DescriptorSetLayout> m_descriptorSetLayout;
340
342 std::unique_ptr<vk::raii::DescriptorPool> m_descriptorPool;
343
345 std::unique_ptr<vk::raii::DescriptorSet> m_descriptorSet;
346
348 std::vector<vk::WriteDescriptorSet> m_writeDescriptors;
349
351 std::vector<vk::DescriptorBufferInfo> m_bufferInfo;
352
354 std::vector<vk::DescriptorImageInfo> m_storageImageInfo;
355
357 std::vector<vk::DescriptorImageInfo> m_sampledImageInfo;
358};
359
360#endif
Declaration of AcceleratorBuffer.
A buffer of memory which may be used by GPU acceleration.
Definition: AcceleratorBuffer.h:158
bool empty() const
Returns true if the container is empty.
Definition: AcceleratorBuffer.h:391
vk::DescriptorBufferInfo GetBufferInfo()
Returns a vk::DescriptorBufferInfo suitable for binding this object to.
Definition: AcceleratorBuffer.h:446
void PrepareForGpuAccess(bool outputOnly=false)
Prepares the buffer to be accessed from the GPU.
Definition: AcceleratorBuffer.h:899
void PrepareForGpuAccessNonblocking(bool outputOnly, vk::raii::CommandBuffer &cmdBuf)
Prepares the buffer to be accessed from the GPU.
Definition: AcceleratorBuffer.h:926
Encapsulates a Vulkan compute pipeline and all necessary resources to use it.
Definition: ComputePipeline.h:55
std::unique_ptr< vk::raii::DescriptorPool > m_descriptorPool
Pool for allocating m_descriptorSet from.
Definition: ComputePipeline.h:342
size_t m_numStorageImages
Number of output image bindings in the shader.
Definition: ComputePipeline.h:321
size_t m_numSampledImages
Number of input image bindings in the shader.
Definition: ComputePipeline.h:324
void BindBuffer(size_t i, AcceleratorBuffer< T > &buf, bool outputOnly=false)
Binds an input or output SSBO to a descriptor slot.
Definition: ComputePipeline.h:83
std::unique_ptr< vk::raii::DescriptorSetLayout > m_descriptorSetLayout
Layout of our descriptor set.
Definition: ComputePipeline.h:339
std::string m_shaderPath
Filesystem path to the compiled SPIR-V shader binary.
Definition: ComputePipeline.h:315
size_t m_pushConstantSize
Size of the push constants, in bytes.
Definition: ComputePipeline.h:327
std::vector< vk::WriteDescriptorSet > m_writeDescriptors
Set of bindings to be written to m_descriptorSet.
Definition: ComputePipeline.h:348
void BindStorageImage(size_t i, vk::Sampler sampler, vk::ImageView view, vk::ImageLayout layout)
Binds a storage (output) image to a descriptor slot.
Definition: ComputePipeline.h:111
std::unique_ptr< vk::raii::PipelineLayout > m_pipelineLayout
Layout of the compute pipeline.
Definition: ComputePipeline.h:336
std::unique_ptr< vk::raii::Pipeline > m_computePipeline
Handle to the Vulkan compute pipeline.
Definition: ComputePipeline.h:333
void BindBufferNonblocking(size_t i, AcceleratorBuffer< T > &buf, vk::raii::CommandBuffer &cmdBuf, bool outputOnly=false)
Binds an input or output SSBO to a descriptor slot.
Definition: ComputePipeline.h:171
void DispatchNoRebind(vk::raii::CommandBuffer &cmdBuf, T pushConstants, uint32_t x, uint32_t y=1, uint32_t z=1)
Similar to Dispatch() but does not bind descriptor sets.
Definition: ComputePipeline.h:291
static void AddComputeMemoryBarrier(vk::raii::CommandBuffer &cmdBuf)
Helper function to insert a shader write-to-read memory barrier in a command buffer.
Definition: ComputePipeline.h:203
std::vector< vk::DescriptorBufferInfo > m_bufferInfo
Details about our SSBOs.
Definition: ComputePipeline.h:351
void BindSampledImage(size_t i, vk::Sampler sampler, vk::ImageView view, vk::ImageLayout layout)
Binds a sampled (input) image to a descriptor slot.
Definition: ComputePipeline.h:139
std::unique_ptr< vk::raii::DescriptorSet > m_descriptorSet
The actual descriptor set storing our inputs and outputs.
Definition: ComputePipeline.h:345
void Dispatch(vk::raii::CommandBuffer &cmdBuf, T pushConstants, uint32_t x, uint32_t y=1, uint32_t z=1)
Adds a vkCmdDispatch operation to a command buffer to execute the compute shader.
Definition: ComputePipeline.h:242
std::unique_ptr< vk::raii::ShaderModule > m_shaderModule
Handle to the shader module object.
Definition: ComputePipeline.h:330
void Bind(vk::raii::CommandBuffer &cmdBuf)
Binds the pipeline to a command buffer.
Definition: ComputePipeline.h:219
ComputePipeline(const std::string &shaderPath, size_t numSSBOs, size_t pushConstantSize, size_t numStorageImages=0, size_t numSampledImages=0)
Construct a new compute pipeline.
Definition: ComputePipeline.cpp:56
std::vector< vk::DescriptorImageInfo > m_sampledImageInfo
Details about our input images.
Definition: ComputePipeline.h:357
void Reinitialize(const std::string &shaderPath, size_t numSSBOs, size_t pushConstantSize, size_t numStorageImages=0, size_t numSampledImages=0)
Wipes the state of this object and recreates it with a new shader binary and configuration.
Definition: ComputePipeline.cpp:86
size_t m_numSSBOs
Number of SSBO bindings in the shader.
Definition: ComputePipeline.h:318
std::vector< vk::DescriptorImageInfo > m_storageImageInfo
Details about our output images.
Definition: ComputePipeline.h:354
void DeferredInit()
Performs deferred initialization of the compute pipeline the first time the object is used.
Definition: ComputePipeline.cpp:128
bool g_hasPushDescriptor
Indicates whether the VK_KHR_push_descriptor extension is available.
Definition: VulkanInit.cpp:207
std::shared_ptr< vk::raii::Device > g_vkComputeDevice
The Vulkan device selected for compute operations (may or may not be same device as rendering)
Definition: VulkanInit.cpp:71
Main library include file.