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 }