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     /// Get the queue families for the device
79     /// See_Also: QueueFamily
80     @property QueueFamily[] queueFamilies();
81 
82     /// Get the features supported for the given format
83     FormatProperties formatProperties(in Format format);
84 
85     /// Check whether the given queue family supports presentation on the
86     /// give surface.
87     bool supportsSurface(uint queueFamilyIndex, Surface surface);
88 
89     /// Get the capabilities of surface on this device.
90     SurfaceCaps surfaceCaps(Surface surface);
91 
92     /// Get the formats supported by the given surface.
93     /// Params:
94     ///     surface = the Surface to query the formats from
95     /// Returns: the formats supported by the surface. `[ Formats.undefined ]`
96     ///         can be returned to indicate that any format is supported.
97     Format[] surfaceFormats(Surface surface);
98 
99     /// Get the present mode supported by the given surface.
100     PresentMode[] surfacePresentModes(Surface surface);
101 
102     /// Open a logical device with the specified queues.
103     /// Returns: null if it can't meet all requested queues, the opened device otherwise.
104     Device open(in QueueRequest[] queues, in DeviceFeatures features=DeviceFeatures.all)
105     in {
106         assert(queues.isConsistentWith(queueFamilies));
107     }
108 }
109 
110 /// Checks that the requests are consistent with families
111 private bool isConsistentWith(in QueueRequest[] requests, in QueueFamily[] families)
112 {
113     // TODO
114     return true;
115 }
116 
117 struct MappedMemorySet
118 {
119     package(gfx) static struct MM {
120         DeviceMemory dm;
121         size_t offset;
122         size_t size;
123     }
124 
125     package(gfx) void addMM(MM mm) {
126         mms ~= mm;
127     }
128 
129     package(gfx) MM[] mms;
130 }
131 
132 /// Handle to a logical device
133 interface Device : IAtomicRefCounted
134 {
135     import gfx.graal : Instance;
136 
137     @property PhysicalDevice physicalDevice();
138     @property Instance instance();
139 
140     /// Wait that device finishes all operations in progress
141     void waitIdle();
142 
143     Queue getQueue(uint queueFamilyIndex, uint queueIndex);
144 
145     CommandPool createCommandPool(uint queueFamilyIndex);
146 
147     DeviceMemory allocateMemory(uint memPropIndex, size_t size)
148     in {
149         assert(size > 0, "cannot allocate memory of null size");
150     }
151     void flushMappedMemory(MappedMemorySet set);
152     void invalidateMappedMemory(MappedMemorySet set);
153 
154     Buffer createBuffer(BufferUsage usage, size_t size)
155     in {
156         assert(size > 0, "cannot create a buffer of null size");
157     }
158 
159     Image createImage(in ImageInfo info);
160 
161     Sampler createSampler(in SamplerInfo info);
162 
163     Semaphore createSemaphore();
164     Fence createFence(Flag!"signaled" signaled);
165     void resetFences(Fence[] fences);
166     void waitForFences(Fence[] fences, Flag!"waitAll" waitAll, Duration timeout);
167 
168     Swapchain createSwapchain(Surface surface, PresentMode pm, uint numImages,
169                               Format format, uint[2] size, ImageUsage usage,
170                               CompositeAlpha alpha, Swapchain former=null);
171 
172     RenderPass createRenderPass(in AttachmentDescription[] attachments,
173                                 in SubpassDescription[] subpasses,
174                                 in SubpassDependency[] dependencies);
175 
176     Framebuffer createFramebuffer(RenderPass rp, ImageView[] attachments,
177                                   uint width, uint height, uint layers);
178 
179     ShaderModule createShaderModule(const(uint)[] spirV, string entryPoint);
180 
181     DescriptorSetLayout createDescriptorSetLayout(in PipelineLayoutBinding[] bindings);
182 
183     PipelineLayout createPipelineLayout(DescriptorSetLayout[] layouts, in PushConstantRange[] ranges);
184 
185     DescriptorPool createDescriptorPool(in uint maxSets, in DescriptorPoolSize[] sizes);
186 
187     void updateDescriptorSets(WriteDescriptorSet[] writeOps, CopyDescritporSet[] copyOps);
188 
189     Pipeline[] createPipelines(PipelineInfo[] infos);
190 }