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     size_t maxStorageBufferSize = 0;
39     size_t maxDescriptorSetStorageBuffers = 24;
40     size_t maxDescriptorSetStorageBuffersDynamic = 4;
41     size_t minStorageBufferOffsetAlignment = 1;
42     size_t maxPushConstantsSize = 0;
43     size_t maxUniformBufferSize = 16_384; // Minimum guarenteed value of GL_MAX_UNIFORM_BLOCK_SIZE
44     size_t maxDescriptorSetUniformBuffers = 36; // Minimum guarenteed value of GL_MAX_UNIFORM_BUFFER_BINDINGS
45     size_t maxDescriptorSetUniformBuffersDynamic = 12; // Minimum guarenteed value of GL_MAX_VERTEX_UNIFORM_BLOCKS
46     size_t minUniformBufferOffsetAlignment = 1; // Default of GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
47 }
48 
49 enum DeviceType {
50     other,
51     integratedGpu,
52     discreteGpu,
53     virtualGpu,
54     cpu
55 }
56 
57 /// A request for a queue family and each queue to be created within that family.
58 /// The amount of queue to be created is given by priorities.length.
59 /// Priorities represent the relative priority to be given to each queue (from 0 to 1)
60 struct QueueRequest
61 {
62     uint familyIndex;
63     float[] priorities;
64 }
65 
66 /// Represent a physical device. This interface is meant to describe a graphics
67 /// device and open a logical device out of it.
68 interface PhysicalDevice
69 {
70     import gfx.graal : Instance;
71 
72     /// The instance this physical device is issued from
73     @property Instance instance();
74     @property string name();
75 
76     @property DeviceType type();
77     final @property bool softwareRendering() {
78         return type == DeviceType.cpu;
79     }
80 
81     @property DeviceFeatures features();
82 
83     @property DeviceLimits limits();
84 
85     @property MemoryProperties memoryProperties();
86 
87     /// Get the queue families for the device
88     /// See_Also: QueueFamily
89     @property QueueFamily[] queueFamilies();
90 
91     /// Get the features supported for the given format
92     FormatProperties formatProperties(in Format format);
93 
94     /// Check whether the given queue family supports presentation on the
95     /// give surface.
96     bool supportsSurface(uint queueFamilyIndex, Surface surface);
97 
98     /// Get the capabilities of surface on this device.
99     SurfaceCaps surfaceCaps(Surface surface);
100 
101     /// Get the formats supported by the given surface.
102     /// Params:
103     ///     surface = the Surface to query the formats from
104     /// Returns: the formats supported by the surface. `[ Formats.undefined ]`
105     ///         can be returned to indicate that any format is supported.
106     Format[] surfaceFormats(Surface surface);
107 
108     /// Get the present mode supported by the given surface.
109     PresentMode[] surfacePresentModes(Surface surface);
110 
111     /// Open a logical device with the specified queues.
112     /// Returns: null if it can't meet all requested queues, the opened device otherwise.
113     Device open(in QueueRequest[] queues, in DeviceFeatures features=DeviceFeatures.all)
114     in {
115         assert(queues.isConsistentWith(queueFamilies));
116     }
117 }
118 
119 /// Checks that the requests are consistent with families
120 private bool isConsistentWith(in QueueRequest[] requests, in QueueFamily[] families)
121 {
122     // TODO
123     return true;
124 }
125 
126 struct MappedMemorySet
127 {
128     package(gfx) static struct MM {
129         DeviceMemory dm;
130         size_t offset;
131         size_t size;
132     }
133 
134     package(gfx) void addMM(MM mm) {
135         mms ~= mm;
136     }
137 
138     package(gfx) MM[] mms;
139 }
140 
141 /// Handle to a logical device
142 interface Device : IAtomicRefCounted
143 {
144     import gfx.graal : Instance;
145 
146     @property PhysicalDevice physicalDevice();
147     @property Instance instance();
148 
149     /// Wait that device finishes all operations in progress
150     void waitIdle();
151 
152     Queue getQueue(uint queueFamilyIndex, uint queueIndex);
153 
154     CommandPool createCommandPool(uint queueFamilyIndex);
155 
156     DeviceMemory allocateMemory(uint memPropIndex, size_t size)
157     in {
158         assert(size > 0, "cannot allocate memory of null size");
159     }
160     void flushMappedMemory(MappedMemorySet set);
161     void invalidateMappedMemory(MappedMemorySet set);
162 
163     Buffer createBuffer(BufferUsage usage, size_t size)
164     in {
165         assert(size > 0, "cannot create a buffer of null size");
166     }
167 
168     Image createImage(in ImageInfo info);
169 
170     Sampler createSampler(in SamplerInfo info);
171 
172     Semaphore createSemaphore();
173     Fence createFence(Flag!"signaled" signaled);
174     void resetFences(Fence[] fences);
175     void waitForFences(Fence[] fences, Flag!"waitAll" waitAll, Duration timeout);
176 
177     Swapchain createSwapchain(Surface surface, PresentMode pm, uint numImages,
178                               Format format, uint[2] size, ImageUsage usage,
179                               CompositeAlpha alpha, Swapchain former=null);
180 
181     RenderPass createRenderPass(in AttachmentDescription[] attachments,
182                                 in SubpassDescription[] subpasses,
183                                 in SubpassDependency[] dependencies);
184 
185     Framebuffer createFramebuffer(RenderPass rp, ImageView[] attachments,
186                                   uint width, uint height, uint layers);
187 
188     ShaderModule createShaderModule(const(uint)[] spirV, string entryPoint);
189 
190     DescriptorSetLayout createDescriptorSetLayout(in PipelineLayoutBinding[] bindings);
191 
192     PipelineLayout createPipelineLayout(DescriptorSetLayout[] layouts, in PushConstantRange[] ranges);
193 
194     DescriptorPool createDescriptorPool(in uint maxSets, in DescriptorPoolSize[] sizes);
195 
196     void updateDescriptorSets(WriteDescriptorSet[] writeOps, CopyDescritporSet[] copyOps);
197 
198     Pipeline[] createPipelines(PipelineInfo[] infos);
199 }