1 module gfx.graal.device;
2 
3 import core.time : Duration;
4 
5 import gfx.core.rc;
6 import gfx.graal.buffer;
7 import gfx.graal.cmd;
8 import gfx.graal.format;
9 import gfx.graal.image;
10 import gfx.graal.memory;
11 import gfx.graal.pipeline;
12 import gfx.graal.presentation;
13 import gfx.graal.queue;
14 import gfx.graal.renderpass;
15 import gfx.graal.sync;
16 
17 import std.typecons : Flag;
18 
19 struct DeviceFeatures {
20     bool presentation;
21     bool anisotropy;
22 
23     static @property DeviceFeatures all() {
24         return DeviceFeatures(
25             true, true
26         );
27     }
28     static @property DeviceFeatures none() {
29         return DeviceFeatures(
30             false, false
31         );
32     }
33 }
34 
35 struct DeviceLimits
36 {
37     size_t linearOptimalGranularity=1;
38 }
39 
40 enum DeviceType {
41     other,
42     integratedGpu,
43     discreteGpu,
44     virtualGpu,
45     cpu
46 }
47 
48 /// A request for a queue family and each queue to be created within that family.
49 /// The amount of queue to be created is given by priorities.length.
50 /// Priorities represent the relative priority to be given to each queue (from 0 to 1)
51 struct QueueRequest
52 {
53     uint familyIndex;
54     float[] priorities;
55 }
56 
57 /// Represent a physical device. This interface is meant to describe a graphics
58 /// device and open a logical device out of it.
59 interface PhysicalDevice
60 {
61     import gfx.graal : Instance;
62 
63     /// The instance this physical device is issued from
64     @property Instance instance();
65     @property string name();
66 
67     @property DeviceType type();
68     final @property bool softwareRendering() {
69         return type == DeviceType.cpu;
70     }
71 
72     @property DeviceFeatures features();
73 
74     @property DeviceLimits limits();
75 
76     @property MemoryProperties memoryProperties();
77 
78     @property QueueFamily[] queueFamilies();
79 
80     FormatProperties formatProperties(in Format format);
81 
82     bool supportsSurface(uint queueFamilyIndex, Surface surface);
83     SurfaceCaps surfaceCaps(Surface surface);
84     Format[] surfaceFormats(Surface surface);
85     PresentMode[] surfacePresentModes(Surface surface);
86 
87     /// Open a logical device with the specified queues.
88     /// Returns: null if it can't meet all requested queues, the opened device otherwise.
89     Device open(in QueueRequest[] queues, in DeviceFeatures features=DeviceFeatures.all)
90     in {
91         assert(queues.isConsistentWith(queueFamilies));
92     }
93 }
94 
95 /// Checks that the requests are consistent with families
96 private bool isConsistentWith(in QueueRequest[] requests, in QueueFamily[] families)
97 {
98     // TODO
99     return true;
100 }
101 
102 struct MappedMemorySet
103 {
104     package(gfx) static struct MM {
105         DeviceMemory dm;
106         size_t offset;
107         size_t size;
108     }
109 
110     package(gfx) void addMM(MM mm) {
111         mms ~= mm;
112     }
113 
114     package(gfx) MM[] mms;
115 }
116 
117 /// Handle to a logical device
118 interface Device : AtomicRefCounted
119 {
120     import gfx.graal : Instance;
121 
122     @property PhysicalDevice physicalDevice();
123     @property Instance instance();
124 
125     /// Wait that device finishes all operations in progress
126     void waitIdle();
127 
128     Queue getQueue(uint queueFamilyIndex, uint queueIndex);
129 
130     CommandPool createCommandPool(uint queueFamilyIndex);
131 
132     DeviceMemory allocateMemory(uint memPropIndex, size_t size)
133     in {
134         assert(size > 0, "cannot allocate memory of null size");
135     }
136     void flushMappedMemory(MappedMemorySet set);
137     void invalidateMappedMemory(MappedMemorySet set);
138 
139     Buffer createBuffer(BufferUsage usage, size_t size)
140     in {
141         assert(size > 0, "cannot create a buffer of null size");
142     }
143 
144     Image createImage(in ImageInfo info);
145 
146     Sampler createSampler(in SamplerInfo info);
147 
148     Semaphore createSemaphore();
149     Fence createFence(Flag!"signaled" signaled);
150     void resetFences(Fence[] fences);
151     void waitForFences(Fence[] fences, Flag!"waitAll" waitAll, Duration timeout);
152 
153     Swapchain createSwapchain(Surface surface, PresentMode pm, uint numImages,
154                               Format format, uint[2] size, ImageUsage usage,
155                               CompositeAlpha alpha, Swapchain former=null);
156 
157     RenderPass createRenderPass(in AttachmentDescription[] attachments,
158                                 in SubpassDescription[] subpasses,
159                                 in SubpassDependency[] dependencies);
160 
161     Framebuffer createFramebuffer(RenderPass rp, ImageView[] attachments,
162                                   uint width, uint height, uint layers);
163 
164     ShaderModule createShaderModule(const(uint)[] spirV, string entryPoint);
165 
166     DescriptorSetLayout createDescriptorSetLayout(in PipelineLayoutBinding[] bindings);
167 
168     PipelineLayout createPipelineLayout(DescriptorSetLayout[] layouts, PushConstantRange[] ranges);
169 
170     DescriptorPool createDescriptorPool(in uint maxSets, in DescriptorPoolSize[] sizes);
171 
172     void updateDescriptorSets(WriteDescriptorSet[] writeOps, CopyDescritporSet[] copyOps);
173 
174     Pipeline[] createPipelines(PipelineInfo[] infos);
175 }