1 module sbylib.graphics.compute.compute; 2 3 public import std; 4 public import sbylib.math; 5 public import sbylib.wrapper.vulkan; 6 import sbylib.graphics.core.descriptor; 7 import sbylib.graphics.util.own; 8 9 class Compute { 10 11 mixin Descriptor; 12 13 protected @own { 14 PipelineLayout pipelineLayout; 15 Pipeline pipeline; 16 } 17 18 mixin ImplReleaseOwn; 19 20 mixin template Instance() { 21 import std : getSymbolsByUDA; 22 import sbylib.wrapper.vulkan; 23 import sbylib.graphics.core; 24 import sbylib.graphics.util; 25 import sbylib.graphics.wrapper; 26 27 alias This = typeof(this); 28 29 mixin ImplDescriptor; 30 31 this() { 32 initializeDescriptor(); 33 34 PipelineLayout.CreateInfo pipelineLayoutCreateInfo = { 35 setLayouts: [descriptorSetLayout] 36 }; 37 this.pipelineLayout = new PipelineLayout(VDevice(), pipelineLayoutCreateInfo); 38 39 Pipeline.ComputeCreateInfo pipelineCreateInfo = { 40 stage: getSymbolsByUDA!(typeof(this), stages)[0](), 41 layout: pipelineLayout, 42 }; 43 44 this.pipeline = Pipeline.create(VDevice(), [pipelineCreateInfo])[0]; 45 } 46 47 private static typeof(this) inst; 48 49 static Inst opCall(VQueue queue = null) { 50 if (queue is null) queue = VQueue(VQueue.Type.Compute); 51 if (inst is null) { 52 inst = new typeof(this); 53 VDevice().pushResource(inst); 54 } 55 return Inst(queue, inst.pipeline, inst.pipelineLayout, inst.descriptorPool, inst.descriptorSetLayout); 56 } 57 58 static struct Inst { 59 mixin ImplReleaseOwn; 60 mixin DefineInstanceMembers!(This); 61 62 private @own { 63 DescriptorSet descriptorSet; 64 VCommandBuffer commandBuffer; 65 } 66 private Pipeline pipeline; 67 private PipelineLayout pipelineLayout; 68 private VQueue queue; 69 70 this(VQueue queue, Pipeline pipeline, PipelineLayout pipelineLayout, DescriptorPool descriptorPool, DescriptorSetLayout descriptorSetLayout) { 71 this.queue = queue; 72 this.pipeline = pipeline; 73 this.pipelineLayout = pipelineLayout; 74 initializeDefinedBuffers(); 75 this.descriptorSet = createDescriptorSet(descriptorPool, descriptorSetLayout); 76 this.commandBuffer = VCommandBuffer.allocate(VCommandBuffer.Type.Compute); 77 } 78 79 auto dispatch(int[3] xyz) { 80 record(xyz); 81 auto fence = queue.submitWithFence(commandBuffer, "dispatch"); 82 struct Job { 83 VFence fence; 84 85 ~this() { 86 if (!fence.signaled) wait(); 87 fence.destroy(); 88 } 89 90 void wait() { 91 fence.wait(); 92 } 93 } 94 return Job(fence); 95 } 96 97 auto dispatch(int[3] xyz, VFence fence) { 98 record(xyz); 99 struct Job { 100 VFence fence; 101 102 void wait() { 103 fence.wait(); 104 } 105 } 106 return Job(fence); 107 } 108 109 private void record(int[3] xyz) { 110 with (commandBuffer()) { 111 cmdBindPipeline(PipelineBindPoint.Compute, pipeline); 112 cmdBindDescriptorSets(PipelineBindPoint.Compute, pipelineLayout, 0, [descriptorSet]); 113 cmdDispatch(xyz[0], xyz[1], xyz[2]); 114 } 115 } 116 } 117 } 118 }