PeriDyno 1.0.0
Loading...
Searching...
No Matches
VkProgram.h
Go to the documentation of this file.
1#pragma once
2#include "VkSystem.h"
3#include "VkContext.h"
4#include "VkDeviceArray.h"
5#include "VkDeviceArray2D.h"
6#include "VkDeviceArray3D.h"
7#include "VkUniform.h"
8#include "VkConstant.h"
9#include <memory>
10#include <map>
11
12namespace dyno {
13
14 using uint = unsigned int;
15
16 struct uint3
17 {
18 uint x, y, z;
19 };
20
21 struct dim3
22 {
23 uint x = 1;
24 uint y = 1;
25 uint z = 1;
26 };
27
28 static uint iDivUp(uint a, uint b)
29 {
30 return (a % b != 0) ? (a / b + 1) : (a / b);
31 }
32
33 // compute grid and thread block size for a given number of elements
34 static dim3 vkDispatchSize(uint totalSize, uint blockSize)
35 {
36 dim3 blockDim;
37 blockDim.x = iDivUp(totalSize, blockSize);
38 return blockDim;
39 }
40
41 static dim3 vkDispatchSize2D(uint size_x, uint size_y, uint blockSize)
42 {
43 dim3 blockDims;
44 blockDims.x = iDivUp(size_x, blockSize);
45 blockDims.y = iDivUp(size_y, blockSize);
46 blockDims.z = 1;
47
48 return blockDims;
49 }
50
51 static dim3 vkDispatchSize3D(uint size_x, uint size_y, uint size_z, uint blockSize)
52 {
53 dim3 blockDims;
54 blockDims.x = iDivUp(size_x, blockSize);
55 blockDims.y = iDivUp(size_y, blockSize);
56 blockDims.z = iDivUp(size_z, blockSize);
57
58 return blockDims;
59 }
60
61 template<typename T>
63 {
64 static VkDeviceArray<T> var;
65 return &var;
66 }
67
68 template<typename T>
70 {
71 static VkDeviceArray2D<T> var;
72 return &var;
73 }
74
75 template<typename T>
77 {
78 static VkDeviceArray3D<T> var;
79 return &var;
80 }
81
82 template<typename T>
84 {
85 static VkUniform<T> var;
86 return &var;
87 }
88
89 template<typename T>
91 {
92 static VkConstant<T> var;
93 return &var;
94 }
95
96#define BUFFER(T) bufferPtr<T>()
97#define BUFFER2D(T) buffer2DPtr<T>()
98#define BUFFER3D(T) buffer3DPtr<T>()
99#define UNIFORM(T) uniformPtr<T>()
100#define CONSTANT(T) constantPtr<T>()
101
102 class VkProgram {
103
104 public:
105 template<typename... Args>
106 VkProgram(Args... args);
107
108 ~VkProgram();
109
110
111 void begin();
112
113 void setupArgs(std::vector<VkVariable*>& vars, VkVariable* t)
114 {
115 vars.push_back(t);
116 }
117
118 template<typename... Args>
119 void enqueue(dim3 groupSize, Args... args);
120
121 template<typename... Args>
122 void write(Args... args);
123
124 void dispatch(dim3 groupSize);
125
126 void end();
127
128 void update(bool sync = false);
129
130 void wait();
131
132 template<typename... Args>
133 void flush(dim3 groupSize, Args... args) {
134 this->begin();
135 this->enqueue(groupSize, args...);
136 this->end();
137
138 this->update(true);
139 this->wait();
140 }
141
142 bool load(std::string fileName);
143 void addMacro(std::string key, std::string value);
144
145 void addGraphicsToComputeBarriers(VkCommandBuffer commandBuffer);
146 void addComputeToComputeBarriers(VkCommandBuffer commandBuffer);
147 void addComputeToGraphicsBarriers(VkCommandBuffer commandBuffer);
148
149 // Resources for the compute part of the example
150 struct {
151 struct Semaphores {
152 VkSemaphore ready{ 0L };
153 VkSemaphore complete{ 0L };
156
157 void setVkCommandBuffer(VkCommandBuffer cmdBuffer) { mCommandBuffers = cmdBuffer; }
158 void bindPipeline();
159
160 void suspendInherentCmdBuffer(VkCommandBuffer cmdBuffer);
162
163 protected:
166
171
172 private:
173 VkPipelineShaderStageCreateInfo createComputeStage(std::string fileName);
174
175 VkContext* ctx = nullptr;
176
177 std::vector<VkVariable*> mFormalParamters;
178 std::vector<VkVariable*> mFormalConstants;
179
180 std::vector<VkVariable*> mAllArgs;
181 std::vector<VkVariable*> mBufferArgs;
182 std::vector<VkVariable*> mUniformArgs;
183 std::vector<VkVariable*> mConstArgs;
184
185 // Descriptor set pool
186 VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
187 VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
188 VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
189 VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
190 VkPipeline pipeline = VK_NULL_HANDLE;
191
192 VkFence mFence;
193 VkQueue queue = VK_NULL_HANDLE;
194 VkCommandPool mCommandPool = VK_NULL_HANDLE;
195 VkCommandBuffer mCommandBuffers = VK_NULL_HANDLE;
196
197 VkCommandBuffer mCmdBufferCopy = VK_NULL_HANDLE;
198 std::vector<VkShaderModule> shaderModules;
199 };
200
201 template<typename... Args>
203 {
205
206 // Create the command pool
207 VkCommandPoolCreateInfo cmdPoolInfo = {};
208 cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
209 cmdPoolInfo.queueFamilyIndex = ctx->queueFamilyIndices.compute;
210 cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
211 VK_CHECK_RESULT(vkCreateCommandPool(ctx->deviceHandle(), &cmdPoolInfo, nullptr, &mCommandPool));
212
213 // Create a command buffer for compute operations
214 VkCommandBufferAllocateInfo cmdBufAllocateInfo =
215 vks::initializers::commandBufferAllocateInfo(mCommandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1);
216
217 VK_CHECK_RESULT(vkAllocateCommandBuffers(ctx->deviceHandle(), &cmdBufAllocateInfo, &mCommandBuffers));
218
219 // Semaphores for graphics / compute synchronization
220 VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
221 VK_CHECK_RESULT(vkCreateSemaphore(ctx->deviceHandle(), &semaphoreCreateInfo, nullptr, &compute.semaphores.ready));
222 VK_CHECK_RESULT(vkCreateSemaphore(ctx->deviceHandle(), &semaphoreCreateInfo, nullptr, &compute.semaphores.complete));
223
224 uint32_t nBuffer = 0;
225 uint32_t nUniform = 0;
226 std::initializer_list<VkVariable*> variables{args...};
227 for (auto variable : variables)
228 {
229 switch (variable->type())
230 {
232 this->pushFormalParameter(variable);
233 nBuffer++;
234 break;
236 this->pushFormalParameter(variable);
237 nUniform++;
238 break;
240 this->pushFormalConstant(variable);
241 break;
242 default:
243 break;
244 }
245 }
246
247 //Create descriptor set layout
248 std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
249 for (size_t i = 0; i < mFormalParamters.size(); i++)
250 {
252 {
253 setLayoutBindings.push_back(vks::initializers::descriptorSetLayoutBinding(VkVariable::descriptorType(mFormalParamters[i]->type()), VK_SHADER_STAGE_COMPUTE_BIT, i));
254 }
255 }
256
257 VkDescriptorSetLayoutCreateInfo descriptorLayout =
259
260 VK_CHECK_RESULT(vkCreateDescriptorSetLayout(ctx->deviceHandle(), &descriptorLayout, nullptr, &descriptorSetLayout));
261
262
263 std::vector<VkDescriptorPoolSize> poolSizes;
264
265 if (nBuffer > 0)
266 poolSizes.push_back(vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nBuffer));
267
268 if (nUniform > 0)
269 poolSizes.push_back(vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, nUniform));
270
271 // Create the descriptor pool
272 VkDescriptorPoolCreateInfo descriptorPoolInfo =
273 vks::initializers::descriptorPoolCreateInfo(poolSizes, poolSizes.size());
274 VK_CHECK_RESULT(vkCreateDescriptorPool(ctx->deviceHandle(), &descriptorPoolInfo, nullptr, &descriptorPool));
275
276 VkDescriptorSetAllocateInfo allocInfo =
278
279 // Create two descriptor sets with input and output buffers switched
280 VK_CHECK_RESULT(vkAllocateDescriptorSets(ctx->deviceHandle(), &allocInfo, &descriptorSet));
281
282 // Create a compute capable device queue
283 vkGetDeviceQueue(ctx->deviceHandle(), ctx->queueFamilyIndices.compute, 0, &queue);
284
285 VkFenceCreateInfo fenceInfo = vks::initializers::fenceCreateInfo(VK_FLAGS_NONE);
286 VK_CHECK_RESULT(vkCreateFence(ctx->deviceHandle(), &fenceInfo, nullptr, &mFence));
287 }
288
289 template<typename... Args>
290 void VkProgram::enqueue(dim3 groupSize, Args... args)
291 {
292 std::initializer_list<VkVariable*> variables{args...};
293
294#ifndef NDEBUG
295 assert(mFormalParamters.size() == variables.size());
296 for (std::size_t i = 0; i < variables.size(); i++)
297 {
298 auto variable = *(variables.begin() + i);
299 assert(mFormalParamters[i]->type() == variable->type());
300 }
301#endif // !NDEBUG
302
303
304 mAllArgs.clear();
305 mBufferArgs.clear();
306 mUniformArgs.clear();
307 mConstArgs.clear();
308 for (auto variable : variables)
309 {
310 switch (variable->type())
311 {
313 this->pushDeviceBuffer(variable);
314 break;
316 this->pushUniform(variable);
317 break;
319 this->pushConstant(variable);
320 break;
321 default:
322 break;
323 }
324 }
325
326 //Create descriptor set layout
327 std::vector<VkWriteDescriptorSet> writeDescriptorSets;
328 for (size_t i = 0; i < variables.size(); i++)
329 {
330 auto variable = *(variables.begin() + i);
331 if ((mAllArgs[i]->type() == VariableType::DeviceBuffer && mAllArgs[i]->bufferSize() > 0) || mAllArgs[i]->type() == VariableType::Uniform) {
332 writeDescriptorSets.push_back(
333 vks::initializers::writeDescriptorSet(descriptorSet, VkVariable::descriptorType(variable->type()), i, &variable->getDescriptor()));
334 }
335 }
336
337 vkUpdateDescriptorSets(ctx->deviceHandle(), static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
338 vkCmdBindDescriptorSets(mCommandBuffers, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, &descriptorSet, 0, 0);
339 writeDescriptorSets.clear();
340
341 vkCmdBindPipeline(mCommandBuffers, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
342
343 uint32_t offset = 0;
344 for (size_t i = 0; i < variables.size(); i++)
345 {
346 auto variable = *(variables.begin() + i);
347 if (variable->type() == VariableType::Constant) {
348 vkCmdPushConstants(mCommandBuffers, pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, offset, variable->bufferSize(), variable->data());
349 offset += variable->bufferSize();
350 }
351 }
352
353 vkCmdDispatch(mCommandBuffers, groupSize.x, groupSize.y, groupSize.z);
354
356 }
357
358 template<typename... Args>
359 void VkProgram::write(Args... args)
360 {
361 std::initializer_list<VkVariable*> variables{ args... };
362
363#ifndef NDEBUG
364 assert(mFormalParamters.size() == variables.size());
365 for (std::size_t i = 0; i < variables.size(); i++)
366 {
367 auto variable = *(variables.begin() + i);
368 assert(mFormalParamters[i]->type() == variable->type());
369 }
370#endif // !NDEBUG
371
372 mAllArgs.clear();
373 mBufferArgs.clear();
374 mUniformArgs.clear();
375 mConstArgs.clear();
376 for (auto variable : variables)
377 {
378 switch (variable->type())
379 {
381 this->pushDeviceBuffer(variable);
382 break;
384 this->pushUniform(variable);
385 break;
387 this->pushConstant(variable);
388 break;
389 default:
390 break;
391 }
392 }
393
394 //Create descriptor set layout
395 std::vector<VkWriteDescriptorSet> writeDescriptorSets;
396 for (size_t i = 0; i < variables.size(); i++)
397 {
398 auto variable = *(variables.begin() + i);
399 if ((mAllArgs[i]->type() == VariableType::DeviceBuffer && mAllArgs[i]->bufferSize() > 0) || mAllArgs[i]->type() == VariableType::Uniform) {
400 writeDescriptorSets.push_back(
401 vks::initializers::writeDescriptorSet(descriptorSet, VkVariable::descriptorType(variable->type()), i, &variable->getDescriptor()));
402 }
403 }
404
405 vkUpdateDescriptorSets(ctx->deviceHandle(), static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
406 writeDescriptorSets.clear();
407 }
408
410 {
411 public:
414
415 void add(std::string name, std::shared_ptr<VkProgram> program);
416
417 inline std::shared_ptr<VkProgram> operator [] (std::string name)
418 {
419 return mPrograms[name];
420 }
421
422 void begin();
423 void update(bool sync = false);
424 void end();
425
426 void wait();
427
428 // Resources for the compute part of the example
429 struct {
430 struct Semaphores {
431 VkSemaphore ready{ 0L };
432 VkSemaphore complete{ 0L };
435
436 private:
437 std::map<std::string, std::shared_ptr<VkProgram>> mPrograms;
438
439 VkContext* ctx = nullptr;
440
441 VkFence mFence;
442 VkQueue queue = VK_NULL_HANDLE;
443 VkCommandPool commandPool = VK_NULL_HANDLE;
444 VkCommandBuffer commandBuffers = VK_NULL_HANDLE;
445 };
446}
assert(queueCount >=1)
#define VK_CHECK_RESULT(f)
Definition VulkanTools.h:55
#define VK_FLAGS_NONE
Definition VulkanTools.h:39
struct dyno::VkMultiProgram::@016024047062303122011057236362361021214245030321 compute
struct dyno::VkMultiProgram::@016024047062303122011057236362361021214245030321::Semaphores semaphores
VkSemaphore ready
Definition VkProgram.h:431
std::shared_ptr< VkProgram > operator[](std::string name)
Definition VkProgram.h:417
std::map< std::string, std::shared_ptr< VkProgram > > mPrograms
Definition VkProgram.h:437
void update(bool sync=false)
VkCommandBuffer commandBuffers
Definition VkProgram.h:444
void add(std::string name, std::shared_ptr< VkProgram > program)
VkCommandPool commandPool
Definition VkProgram.h:443
VkSemaphore complete
Definition VkProgram.h:432
void pushArgument(VkVariable *arg)
VkPipeline pipeline
Definition VkProgram.h:190
void pushUniform(VkVariable *arg)
std::vector< VkVariable * > mFormalParamters
Definition VkProgram.h:177
VkDescriptorSetLayout descriptorSetLayout
Definition VkProgram.h:187
void update(bool sync=false)
Definition VkProgram.cpp:63
VkDescriptorSet descriptorSet
Definition VkProgram.h:188
std::vector< VkVariable * > mAllArgs
Definition VkProgram.h:180
bool load(std::string fileName)
std::vector< VkVariable * > mUniformArgs
Definition VkProgram.h:182
void addMacro(std::string key, std::string value)
VkPipelineLayout pipelineLayout
Definition VkProgram.h:189
void pushConstant(VkVariable *arg)
VkProgram(Args... args)
Definition VkProgram.h:202
VkCommandPool mCommandPool
Definition VkProgram.h:194
void setVkCommandBuffer(VkCommandBuffer cmdBuffer)
Definition VkProgram.h:157
VkSemaphore complete
Definition VkProgram.h:153
VkDescriptorPool descriptorPool
Definition VkProgram.h:186
void pushFormalParameter(VkVariable *arg)
std::vector< VkVariable * > mBufferArgs
Definition VkProgram.h:181
void addGraphicsToComputeBarriers(VkCommandBuffer commandBuffer)
Definition VkProgram.cpp:98
VkCommandBuffer mCommandBuffers
Definition VkProgram.h:195
struct dyno::VkProgram::@173005120305027326137125156036200106005335301235 compute
void addComputeToComputeBarriers(VkCommandBuffer commandBuffer)
VkSemaphore ready
Definition VkProgram.h:152
void write(Args... args)
Definition VkProgram.h:359
void restoreInherentCmdBuffer()
struct dyno::VkProgram::@173005120305027326137125156036200106005335301235::Semaphores semaphores
void addComputeToGraphicsBarriers(VkCommandBuffer commandBuffer)
std::vector< VkVariable * > mFormalConstants
Definition VkProgram.h:178
std::vector< VkShaderModule > shaderModules
Definition VkProgram.h:198
void setupArgs(std::vector< VkVariable * > &vars, VkVariable *t)
Definition VkProgram.h:113
VkPipelineShaderStageCreateInfo createComputeStage(std::string fileName)
void pushDeviceBuffer(VkVariable *arg)
std::vector< VkVariable * > mConstArgs
Definition VkProgram.h:183
void dispatch(dim3 groupSize)
Definition VkProgram.cpp:39
void flush(dim3 groupSize, Args... args)
Definition VkProgram.h:133
void enqueue(dim3 groupSize, Args... args)
Definition VkProgram.h:290
void pushFormalConstant(VkVariable *arg)
VkContext * ctx
Definition VkProgram.h:175
VkCommandBuffer mCmdBufferCopy
Definition VkProgram.h:197
void suspendInherentCmdBuffer(VkCommandBuffer cmdBuffer)
VkContext * currentContext()
Definition VkSystem.h:21
static VkSystem * instance()
Definition VkSystem.cpp:10
static VkDescriptorType descriptorType(const VariableType varType)
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
DYN_FUNC Real arg(const Complex< Real > &)
Definition Complex.inl:273
static dim3 vkDispatchSize(uint totalSize, uint blockSize)
Definition VkProgram.h:34
VkConstant< T > * constantPtr()
Definition VkProgram.h:90
VkUniform< T > * uniformPtr()
Definition VkProgram.h:83
static dim3 vkDispatchSize2D(uint size_x, uint size_y, uint blockSize)
Definition VkProgram.h:41
VkDeviceArray2D< T > * buffer2DPtr()
Definition VkProgram.h:69
unsigned int uint
Definition VkProgram.h:14
@ DeviceBuffer
Device buffer.
Definition VkVariable.h:15
@ Uniform
Uniform variable.
Definition VkVariable.h:18
@ Constant
Constant variable.
Definition VkVariable.h:17
static dim3 vkDispatchSize3D(uint size_x, uint size_y, uint size_z, uint blockSize)
Definition VkProgram.h:51
VkDeviceArray3D< T > * buffer3DPtr()
Definition VkProgram.h:76
static uint iDivUp(uint a, uint b)
Definition VkProgram.h:28
VkDeviceArray< T > * bufferPtr()
Definition VkProgram.h:62
VkDescriptorSetLayoutBinding descriptorSetLayoutBinding(VkDescriptorType type, VkShaderStageFlags stageFlags, uint32_t binding, uint32_t descriptorCount=1)
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo(const VkDescriptorSetLayoutBinding *pBindings, uint32_t bindingCount)
VkDescriptorPoolSize descriptorPoolSize(VkDescriptorType type, uint32_t descriptorCount)
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo(uint32_t poolSizeCount, VkDescriptorPoolSize *pPoolSizes, uint32_t maxSets)
VkCommandBufferAllocateInfo commandBufferAllocateInfo(VkCommandPool commandPool, VkCommandBufferLevel level, uint32_t bufferCount)
VkWriteDescriptorSet writeDescriptorSet(VkDescriptorSet dstSet, VkDescriptorType type, uint32_t binding, VkDescriptorBufferInfo *bufferInfo, uint32_t descriptorCount=1)
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo(VkDescriptorPool descriptorPool, const VkDescriptorSetLayout *pSetLayouts, uint32_t descriptorSetCount)
VkFenceCreateInfo fenceCreateInfo(VkFenceCreateFlags flags=0)
VkSemaphoreCreateInfo semaphoreCreateInfo()