1 module gfx.gl3.device; 2 3 package: 4 5 import gfx.graal.cmd : CommandPool; 6 import gfx.graal.device : Device; 7 import gfx.graal.sync : Fence, Semaphore; 8 9 class GlDevice : Device 10 { 11 import core.time : Duration; 12 import gfx.core.rc : atomicRcCode, Rc; 13 import gfx.gl3 : GlPhysicalDevice, GlShare; 14 import gfx.gl3.queue : GlQueue; 15 import gfx.graal.buffer : Buffer, BufferUsage; 16 import gfx.graal.device : MappedMemorySet; 17 import gfx.graal.format : Format; 18 import gfx.graal.image : Image, ImageInfo, ImageUsage, ImageView, 19 Sampler, SamplerInfo; 20 import gfx.graal.memory : DeviceMemory, MemoryProperties; 21 import gfx.graal.presentation : CompositeAlpha, PresentMode, Surface, 22 Swapchain; 23 import gfx.graal.queue : Queue; 24 import gfx.graal.renderpass : AttachmentDescription, Framebuffer, 25 RenderPass, SubpassDependency, 26 SubpassDescription; 27 import gfx.graal.pipeline : CopyDescritporSet, DescriptorSet, 28 DescriptorSetLayout, DescriptorPool, 29 DescriptorPoolSize, Pipeline, PipelineInfo, 30 PipelineLayout, PipelineLayoutBinding, 31 PushConstantRange, ShaderModule, 32 WriteDescriptorSet; 33 import std.typecons : Flag; 34 35 mixin(atomicRcCode); 36 37 private Rc!GlShare _share; 38 private MemoryProperties _memProps; 39 private GlQueue _queue; 40 41 42 this (GlPhysicalDevice phd, GlShare share) { 43 _share = share; 44 _memProps = phd.memoryProperties; 45 _queue = new GlQueue(_share, this); 46 } 47 48 override void dispose() { 49 _queue.dispose(); 50 _share.unload(); 51 } 52 53 override void waitIdle() {} 54 55 override Queue getQueue(uint queueFamilyIndex, uint queueIndex) { 56 return _queue; 57 } 58 59 CommandPool createCommandPool(uint queueFamilyIndex) { 60 import gfx.gl3.queue : GlCommandPool; 61 return new GlCommandPool(_queue); 62 } 63 64 DeviceMemory allocateMemory(uint memPropIndex, size_t size) { 65 import gfx.gl3.resource : GlDeviceMemory; 66 return new GlDeviceMemory(memPropIndex, _memProps.types[memPropIndex].props, size); 67 } 68 69 void flushMappedMemory(MappedMemorySet set) {} 70 void invalidateMappedMemory(MappedMemorySet set) {} 71 72 Buffer createBuffer(BufferUsage usage, size_t size) { 73 import gfx.gl3.resource : GlBuffer; 74 return new GlBuffer(_share, usage, size); 75 } 76 77 Image createImage(in ImageInfo info) { 78 import gfx.gl3.resource : GlImage; 79 return new GlImage(_share, info); 80 } 81 82 Sampler createSampler(in SamplerInfo info) { 83 import gfx.gl3.resource : GlSampler; 84 return new GlSampler(_share, info); 85 } 86 87 Semaphore createSemaphore() { 88 return new GlSemaphore; 89 } 90 91 Fence createFence(Flag!"signaled" signaled) { 92 return new GlFence(signaled); 93 } 94 95 void resetFences(Fence[] fences) {} 96 void waitForFences(Fence[] fences, Flag!"waitAll" waitAll, Duration timeout) {} 97 98 Swapchain createSwapchain(Surface surface, PresentMode pm, uint numImages, 99 Format format, uint[2] size, ImageUsage usage, 100 CompositeAlpha alpha, Swapchain former=null) { 101 import gfx.gl3.swapchain : GlSwapchain; 102 return new GlSwapchain(_share, this, surface, pm, numImages, format, size, usage, alpha, former); 103 } 104 105 RenderPass createRenderPass(in AttachmentDescription[] attachments, 106 in SubpassDescription[] subpasses, 107 in SubpassDependency[] dependencies) { 108 import gfx.gl3.pipeline : GlRenderPass; 109 return new GlRenderPass(attachments, subpasses, dependencies); 110 } 111 112 Framebuffer createFramebuffer(RenderPass rp, ImageView[] attachments, 113 uint width, uint height, uint layers) { 114 import gfx.gl3.pipeline : GlFramebuffer, GlRenderPass; 115 import gfx.gl3.resource : GlImageView; 116 import std.algorithm : map; 117 import std.array : array; 118 119 return new GlFramebuffer(_share, cast(GlRenderPass)rp, 120 attachments.map!(iv => cast(GlImageView)iv).array, 121 width, height, layers); 122 } 123 124 ShaderModule createShaderModule(const(uint)[] code, string entryPoint) { 125 import gfx.gl3.pipeline : GlShaderModule; 126 import std.exception : enforce; 127 128 enforce(entryPoint == "main"); 129 return new GlShaderModule(_share, code); 130 } 131 132 DescriptorSetLayout createDescriptorSetLayout(in PipelineLayoutBinding[] bindings) { 133 import gfx.gl3.pipeline : GlDescriptorSetLayout; 134 return new GlDescriptorSetLayout(bindings); 135 } 136 137 PipelineLayout createPipelineLayout(DescriptorSetLayout[] layouts, PushConstantRange[] ranges) { 138 import gfx.gl3.pipeline : GlPipelineLayout; 139 return new GlPipelineLayout(layouts, ranges); 140 } 141 142 DescriptorPool createDescriptorPool(in uint maxSets, in DescriptorPoolSize[] sizes) { 143 import gfx.gl3.pipeline : GlDescriptorPool; 144 return new GlDescriptorPool(maxSets, sizes); 145 } 146 147 void updateDescriptorSets(WriteDescriptorSet[] writeOps, CopyDescritporSet[] copyOps) { 148 import gfx.gl3.pipeline : GlDescriptorSet; 149 foreach (wo; writeOps) { 150 auto glSet = cast(GlDescriptorSet)wo.dstSet; 151 glSet.write(wo.dstBinding, wo.dstArrayElem, wo.writes); 152 } 153 } 154 155 Pipeline[] createPipelines(PipelineInfo[] infos) { 156 import gfx.gl3.pipeline : GlPipeline; 157 import std.algorithm : map; 158 import std.array : array; 159 return infos.map!(pi => cast(Pipeline)new GlPipeline(_share, pi)).array; 160 } 161 } 162 163 private final class GlSemaphore : Semaphore { 164 import gfx.core.rc : atomicRcCode; 165 mixin(atomicRcCode); 166 this() {} 167 override void dispose() {} 168 } 169 170 private final class GlFence : Fence { 171 import core.time : Duration; 172 import gfx.core.rc : atomicRcCode; 173 mixin(atomicRcCode); 174 private bool _signaled; 175 this(bool signaled) { 176 _signaled = signaled; 177 } 178 override void dispose() {} 179 override @property bool signaled() { return _signaled; } 180 override void reset() {} 181 override void wait(Duration timeout) {} 182 } 183