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