1 /// An idiomatic D wrapper for <a href="https://github.com/gfx-rs/wgpu-native">wgpu-native</a>.
2 ///
3 /// Authors: Chance Snow
4 /// Copyright: Copyright © 2020 Chance Snow. All rights reserved.
5 /// License: MIT License
6 module wgpu.api;
7 
8 import core.stdc.config : c_ulong;
9 import std.conv : to;
10 import std.string : toStringz;
11 import std.traits : fullyQualifiedName;
12 
13 import wgpu.bindings;
14 
15 /// Version of <a href="https://github.com/gfx-rs/wgpu-native">wgpu-native</a> this library binds.
16 /// See_Also: <a href="https://github.com/gfx-rs/wgpu-native/releases/tag/v0.6.0">github.com/gfx-rs/wgpu-native/releases/tag/v0.6.0</a>
17 static const VERSION = "0.6.0";
18 /// Buffer-Texture copies must have bytes_per_row aligned to this number.
19 ///
20 /// This doesn't apply to `Queue.writeTexture`.
21 static const COPY_BYTES_PER_ROW_ALIGNMENT = 256;
22 
23 // TODO: Does the library need these?
24 /// Unknown
25 static const DESIRED_NUM_FRAMES = 3;
26 /// Maximum anisotropy.
27 static const MAX_ANISOTROPY = 16;
28 /// Maximum number of color targets.
29 static const MAX_COLOR_TARGETS = 4;
30 /// Maximum amount of mipmap levels.
31 static const MAX_MIP_LEVELS = 16;
32 /// Maximum number of vertex buffers.
33 static const MAX_VERTEX_BUFFERS = 16;
34 
35 alias WgpuId = c_ulong;
36 alias RequestAdapterOptions = WGPURequestAdapterOptions;
37 /// Metadata about a backend adapter.
38 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.AdapterInfo.html">wgpu::AdapterInfo</a>
39 alias AdapterInfo = WGPUCAdapterInfo;
40 /// Features that are not guaranteed to be supported.
41 ///
42 /// These are either part of the webgpu standard, or are extension features supported by wgpu when targeting native.
43 ///
44 /// If you want to use a feature, you need to first verify that the adapter supports the feature. If the adapter
45 /// does not support the feature, requesting a device with it enabled will panic.
46 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Features.html">wgpu::Features</a>
47 alias Features = WGPUFeatures;
48 /// Represents the sets of limits an adapter/device supports.
49 ///
50 /// Limits "better" than the default must be supported by the adapter and requested when requesting a device.
51 /// If limits "better" than the adapter supports are requested, requesting a device will panic. Once a device is
52 /// requested, you may only use resources up to the limits requested even if the adapter supports "better" limits.
53 ///
54 /// Requesting limits that are "better" than you need may cause performance to decrease because the implementation
55 /// needs to support more than is needed. You should ideally only request exactly what you need.
56 ///
57 /// <strong>See Also</strong>: https://gpuweb.github.io/gpuweb/#dictdef-gpulimits
58 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Limits.html">wgpu::Limits</a>
59 alias Limits = WGPUCLimits;
60 /// RGBA double precision color.
61 ///
62 /// This is not to be used as a generic color type, only for specific wgpu interfaces.
63 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Color.html">wgpu::Color</a>
64 alias Color = WGPUColor;
65 /// Describes a `Texture`.
66 alias TextureDescriptor = WGPUTextureDescriptor;
67 /// Describes a `TextureView`.
68 alias TextureViewDescriptor = WGPUTextureViewDescriptor;
69 /// Describes a `Sampler`.
70 alias SamplerDescriptor = WGPUSamplerDescriptor;
71 /// Extent of a texture related operation.
72 alias Extent3d = WGPUExtent3d;
73 /// Describes a `SwapChain`.
74 alias SwapChainDescriptor = WGPUSwapChainDescriptor;
75 
76 /// Integral type used for buffer offsets.
77 alias BufferAddress = WGPUBufferAddress;
78 /// Describes a `Buffer`.
79 alias BufferDescriptor = WGPUBufferDescriptor;
80 /// Describes a `CommandEncoder`.
81 alias CommandEncoderDescriptor = WGPUCommandEncoderDescriptor;
82 /// Origin of a copy to/from a texture.
83 alias Origin3d = WGPUOrigin3d;
84 /// View of a texture which can be used to copy to/from a buffer/texture.
85 alias TextureCopyView = WGPUTextureCopyView;
86 /// Layout of a texture in a buffer's memory.
87 alias TextureDataLayout = WGPUTextureDataLayout;
88 /// View of a buffer which can be used to copy to/from a texture.
89 alias BufferCopyView = WGPUBufferCopyView;
90 /// Describes a `BindGroup`.
91 alias BindGroupDescriptor = WGPUBindGroupDescriptor;
92 /// Describes a single binding inside a bind group.
93 alias BindGroupLayoutEntry = WGPUBindGroupLayoutEntry;
94 /// Describes a `BindGroupLayout`.
95 alias BindGroupLayoutDescriptor = WGPUBindGroupLayoutDescriptor;
96 /// Describes a `PipelineLayout`.
97 alias PipelineLayoutDescriptor = WGPUPipelineLayoutDescriptor;
98 /// Describes a `RenderPipeline`.
99 alias RenderPipelineDescriptor = WGPURenderPipelineDescriptor;
100 /// Describes a `ComputePipeline`.
101 alias ComputePipelineDescriptor = WGPUComputePipelineDescriptor;
102 /// Describes a `RenderPass`.
103 alias RenderPassDescriptor = WGPURenderPassDescriptor;
104 /// Describes a color attachment to a `RenderPass`.
105 alias RenderPassColorAttachmentDescriptor = WGPURenderPassColorAttachmentDescriptor;
106 alias PassChannel_Color = WGPUPassChannel_Color;
107 /// Describes a `ComputePass`.
108 alias ComputePassDescriptor = WGPUComputePassDescriptor;
109 /// Describes a `CommandBuffer`.
110 alias CommandBufferDescriptor = WGPUCommandBufferDescriptor;
111 
112 public import wgpu.bindings: AddressMode, Backend, BindingType, BlendFactor, BlendOperation, CDeviceType,
113   CompareFunction, CullMode, FilterMode, FrontFace, IndexFormat, InputStepMode, LoadOp, LogLevel, PowerPreference,
114   PresentMode, PrimitiveTopology, SType, StencilOperation, StoreOp, SwapChainStatus, TextureAspect,
115   TextureComponentType, TextureDimension, TextureFormat, TextureViewDimension, VertexFormat;
116 
117 /// Describes the shader stages that a binding will be visible from.
118 ///
119 /// These can be combined in a bitwise combination.
120 ///
121 /// For example, something that is visible from both vertex and fragment shaders can be defined as:
122 ///
123 /// `ShaderStage.vertex | ShaderStage.fragment`
124 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.ShaderStage.html">wgpu::ShaderStage</a>
125 enum ShaderStage : WGPUShaderStage {
126   /// Binding is not visible from any shader stage.
127   none = 0,
128   /// Binding is visible from the vertex shader of a render pipeline.
129   vertex = 1,
130   /// Binding is visible from the fragment shader of a render pipeline.
131   fragment = 2,
132   /// Binding is visible from the compute shader of a compute pipeline.
133   compute = 4
134 }
135 
136 /// Different ways that you can use a buffer.
137 ///
138 /// The usages determine what kind of memory the buffer is allocated from and what actions the buffer can partake in.
139 ///
140 /// These can be combined in a bitwise combination.
141 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.BufferUsage.html">wgpu::BufferUsage</a>
142 enum BufferUsage : WGPUBufferUsage {
143   mapRead = 1,
144   mapWrite = 2,
145   copySrc = 4,
146   copyDst = 8,
147   index = 16,
148   vertex = 32,
149   uniform = 64,
150   storage = 128,
151   indirect = 256
152 }
153 
154 /// Different ways that you can use a texture.
155 ///
156 /// The usages determine what kind of memory the texture is allocated from and what actions the texture can partake in.
157 ///
158 /// These can be combined in a bitwise combination.
159 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.TextureUsage.html">wgpu::TextureUsage</a>
160 enum TextureUsage : WGPUTextureUsage {
161   copySrc = 1,
162   copyDst = 2,
163   sampled = 4,
164   storage = 8,
165   outputAttachment = 16
166 }
167 
168 extern (C) private void wgpu_request_adapter_callback(ulong id, void* data) {
169   assert(data !is null);
170   auto adapter = cast(Adapter*) data;
171   assert(id > 0);
172   adapter.id = id;
173 }
174 
175 /// A handle to a physical graphics and/or compute device.
176 ///
177 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Adapter.html">wgpu::Adapter</a>
178 struct Adapter {
179   /// Handle identifier.
180   WgpuId id;
181 
182   /// Requests a new Adapter, asynchronously.
183   ///
184   /// Use `ready` to determine whether an Adapter was successfully requested.
185   this(const RequestAdapterOptions options) {
186     const allowedBackends = Backend.Vulkan | Backend.Metal | Backend.Dx12;
187     wgpu_request_adapter_async(&options, allowedBackends, false, &wgpu_request_adapter_callback, &this);
188   }
189 
190   /// Release the given handle.
191   void destroy() {
192     if (ready) wgpu_adapter_destroy(id);
193     id = 0;
194   }
195 
196   /// Whether this Adapter handle has finished being requested and is ready for use.
197   bool ready() @property const {
198     return id > 0;
199   }
200 
201   /// Information about this Adapter.
202   AdapterInfo info() @property const {
203     assert(ready);
204     AdapterInfo info;
205     wgpu_adapter_get_info(id, &info);
206     return info;
207   }
208 
209   /// List all features that are supported with this adapter.
210   ///
211   /// Features must be explicitly requested in `Adapter.requestDevice` in order to use them.
212   Features features() @property const {
213     return wgpu_adapter_features(id);
214   }
215 
216   /// List the "best" limits that are supported by this adapter.
217   ///
218   /// Limits must be explicitly requested in `Adapter.requestDevice` to set the values that you are allowed to use.
219   Limits limits() @property const {
220     return wgpu_adapter_limits(id);
221   }
222 
223   /// Requests a connection to a physical device, creating a logical device.
224   ///
225   /// Params:
226   /// limits = The sets of limits the device supports.
227   /// label = Optional label for the `Device`.
228   Device requestDevice(const Limits limits, string label = fullyQualifiedName!Device) {
229     assert(ready);
230     auto id = wgpu_adapter_request_device(id, 0, &limits, true, toStringz(label));
231     return Device(id, label);
232   }
233 }
234 
235 /// An open connection to a graphics and/or compute device.
236 ///
237 /// The `Device` is the responsible for the creation of most rendering and compute resources, as well as exposing `Queue` objects.
238 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Device.html">wgpu::Device</a>
239 struct Device {
240   /// Handle identifier.
241   WgpuId id;
242   /// Label for this Device.
243   string label;
244 
245   /// Release the given handle.
246   void destroy() {
247     if (ready) wgpu_device_destroy(id);
248     id = 0;
249   }
250 
251   /// Whether this Device handle is valid and ready for use.
252   ///
253   /// If `false`, `Adapter.requestDevice` likely failed.
254   bool ready() @property const {
255     return id > 0;
256   }
257 
258   /// List all limits that were requested of this device.
259   ///
260   /// If any of these limits are exceeded, functions may panic.
261   Limits limits() @property const {
262     return wgpu_device_limits(id);
263   }
264 
265   /// Obtains a queue which can accept `CommandBuffer` submissions.
266   Queue queue() @property const {
267     return Queue(wgpu_device_get_default_queue(id));
268   }
269 
270   /// Check for resource cleanups and mapping callbacks.
271   /// Params:
272   /// forceWait = Whether or not the call should block.
273   void poll(bool forceWait = false) {
274     wgpu_device_poll(id, forceWait);
275   }
276 
277   /// Creates a shader module from SPIR-V source code.
278   ShaderModule createShaderModule(const byte[] spv) {
279     import std.algorithm.iteration : map;
280     import std.array : array;
281 
282     const bytes = spv.map!(byte_ => byte_.to!(const uint)).array;
283     return ShaderModule(wgpu_device_create_shader_module(
284       id,
285       WGPUShaderSource(bytes.ptr, spv.length))
286     );
287   }
288 
289   /// Creates an empty `CommandEncoder`.
290   CommandEncoder createCommandEncoder(const CommandEncoderDescriptor descriptor) {
291     return CommandEncoder(wgpu_device_create_command_encoder(id, &descriptor), descriptor);
292   }
293 
294   /// Creates a new bind group.
295   BindGroup createBindGroup(const BindGroupDescriptor descriptor) {
296     return BindGroup(wgpu_device_create_bind_group(id, &descriptor), descriptor);
297   }
298 
299   /// Creates a bind group layout.
300   BindGroupLayout createBindGroupLayout(const BindGroupLayoutDescriptor descriptor) {
301     return BindGroupLayout(wgpu_device_create_bind_group_layout(id, &descriptor), descriptor);
302   }
303 
304   /// Creates a bind group layout.
305   PipelineLayout createPipelineLayout(const PipelineLayoutDescriptor descriptor) {
306     return PipelineLayout(wgpu_device_create_pipeline_layout(id, &descriptor), descriptor);
307   }
308 
309   /// Creates a render pipeline.
310   RenderPipeline createRenderPipeline(const RenderPipelineDescriptor descriptor) {
311     return RenderPipeline(wgpu_device_create_render_pipeline(id, &descriptor), descriptor);
312   }
313 
314   /// Creates a compute pipeline.
315   ComputePipeline createComputePipeline(const ComputePipelineDescriptor descriptor) {
316     return ComputePipeline(wgpu_device_create_compute_pipeline(id, &descriptor), descriptor);
317   }
318 
319   /// Creates a new buffer.
320   Buffer createBuffer(const BufferDescriptor descriptor) {
321     return Buffer(wgpu_device_create_buffer(id, &descriptor), descriptor);
322   }
323 
324   /// Creates a new `Texture`.
325   ///
326   /// Params:
327   /// descriptor = Specifies the general format of the texture.
328   Texture createTexture(const TextureDescriptor descriptor) {
329     return Texture(wgpu_device_create_texture(id, &descriptor), descriptor);
330   }
331 
332   /// Creates a new `Sampler`.
333   ///
334   /// Params:
335   /// descriptor = Specifies the behavior of the sampler.
336   Sampler createSampler(const SamplerDescriptor descriptor) {
337     return Sampler(wgpu_device_create_sampler(id, &descriptor), descriptor);
338   }
339 
340   /// Create a new `SwapChain` which targets `surface`.
341   SwapChain createSwapChain(const Surface surface, const SwapChainDescriptor descriptor) {
342     return SwapChain(wgpu_device_create_swap_chain(id, surface.id, &descriptor), descriptor);
343   }
344 }
345 
346 /// A handle to a presentable surface.
347 ///
348 /// A Surface represents a platform-specific surface (e.g. a window) to which rendered images may be presented.
349 /// A Surface may be created with `Surface.create`.
350 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Surface.html">wgpu::Surface</a>
351 struct Surface {
352   /// Handle identifier.
353   WgpuId id;
354 
355   version (Windows) {
356     /// Create a new `Surface` from an Android handle.
357     static Surface fromAndroid(void* androidNativeWindow) {
358       return Surface(wgpu_create_surface_from_android( androidNativeWindow));
359     }
360   }
361   version (OSX) {
362     /// Create a new `Surface` from a Metal layer.
363     static Surface fromMetalLayer(void* layer) {
364       return Surface(wgpu_create_surface_from_metal_layer(layer));
365     }
366   }
367   version (linux) {
368     /// Create a new `Surface` from a Wayland window handle.
369     static Surface fromWayland(void* surface, void* display) {
370       return Surface(wgpu_create_surface_from_wayland(surface, display));
371     }
372   }
373   version (Windows) {
374     /// Create a new `Surface` from a Windows window handle.
375     static Surface fromWindowsHwnd(void* _hinstance, void* hwnd) {
376       return Surface(wgpu_create_surface_from_windows_hwnd(_hinstance, hwnd));
377     }
378   }
379   version (linux) {
380     /// Create a new `Surface` from a Xlib window handle.
381     static Surface fromXlib(const(void)** display, c_ulong window) {
382       return Surface(wgpu_create_surface_from_xlib(display, window));
383     }
384   }
385   version (D_Ddoc) {
386     /// Create a new `Surface` from an Android handle.
387     static Surface fromAndroid(void* androidNativeWindow) {
388       return Surface(wgpu_create_surface_from_android( androidNativeWindow));
389     }
390     /// Create a new `Surface` from a Metal layer.
391     static Surface fromMetalLayer(void* layer) {
392       return Surface(wgpu_create_surface_from_metal_layer(layer));
393     }
394     /// Create a new `Surface` from a Wayland window handle.
395     static Surface fromWayland(void* surface, void* display) {
396       return Surface(wgpu_create_surface_from_wayland(surface, display));
397     }
398     /// Create a new `Surface` from a Windows window handle.
399     static Surface fromWindowsHwnd(void* _hinstance, void* hwnd) {
400       return Surface(wgpu_create_surface_from_windows_hwnd(_hinstance, hwnd));
401     }
402     /// Create a new `Surface` from a Xlib window handle.
403     static Surface fromXlib(const(void)** display, c_ulong window) {
404       return Surface(wgpu_create_surface_from_xlib(display, window));
405     }
406   }
407 }
408 
409 /// A handle to a swap chain.
410 ///
411 /// A `SwapChain` represents the image or series of images that will be presented to a `Surface`.
412 /// A `SwapChain` may be created with `Device.createSwapChain`.
413 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.SwapChain.html">wgpu::SwapChain</a>
414 struct SwapChain {
415   /// Handle identifier.
416   WgpuId id;
417   /// Describes this `SwapChain.`
418   SwapChainDescriptor descriptor;
419 
420   /// Returns the next texture to be presented by the swapchain for drawing.
421   SwapChainOutput getNextTexture() {
422     auto output = wgpu_swap_chain_get_next_texture(id);
423     auto status = output.status.to!int.to!SwapChainStatus;
424     auto successful = status == SwapChainStatus.Good || status == SwapChainStatus.Suboptimal;
425     TextureView* view = null;
426     if (successful) view = new TextureView(output.view_id);
427 
428     return SwapChainOutput(
429       view,
430       successful,
431       status == SwapChainStatus.Suboptimal,
432       output.status.to!int > 1 ? output.status.to!int.to!SwapChainError : SwapChainError.None
433     );
434   }
435 }
436 
437 /// Result of an unsuccessful call to `SwapChain.getNextTexture`.
438 enum SwapChainError {
439   None = 0,
440   /// A timeout was encountered while trying to acquire the next frame.
441   Timeout = 2,
442   /// The underlying surface has changed, and therefore the swap chain must be updated.
443   Outdated = 3,
444   /// The swap chain has been lost and needs to be recreated.
445   Lost = 4,
446   /// There is no more memory left to allocate a new frame.
447   OutOfMemory = 5,
448 }
449 
450 /// Result of a call to `SwapChain.getNextTexture`.
451 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.SwapChainFrame.html">wgpu::SwapChainFrame</a>
452 const struct SwapChainOutput {
453   /// The texture into which the next frame should be rendered. `null` if the call to `SwapChain.getNextTexture` was unsuccessful.
454   TextureView* view;
455   /// Whether a call to `SwapChain.getNextTexture` was successful.
456   bool success = false;
457   /// `true` if the acquired buffer can still be used for rendering, but should be recreated for maximum performance.
458   bool suboptimal = false;
459   /// Result of an unsuccessful call to `SwapChain.getNextTexture`. `SwapChainError.None` if the call was successful.
460   SwapChainError error = SwapChainError.None;
461 }
462 
463 /// Result of a call to `Buffer.mapReadAsync` or `Buffer.mapWriteAsync`.
464 enum BufferMapAsyncStatus {
465   success = 0,
466   error = 1,
467   unknown = 2,
468   contextLost = 3
469 }
470 
471 extern (C) private void wgpu_buffer_map_callback(WGPUBufferMapAsyncStatus status, ubyte* data) {
472   assert(data !is null);
473   auto buffer = cast(Buffer*) data;
474   assert(buffer.id);
475 
476   buffer.status = status.to!int.to!BufferMapAsyncStatus;
477 }
478 
479 /// A handle to a GPU-accessible buffer.
480 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Buffer.html">wgpu::Buffer</a>
481 struct Buffer {
482   /// Handle identifier.
483   WgpuId id;
484   /// Describes this `Buffer`.
485   BufferDescriptor descriptor;
486   /// Result of a call to `Buffer.mapReadAsync` or `Buffer.mapWriteAsync`.
487   BufferMapAsyncStatus status = BufferMapAsyncStatus.unknown;
488 
489   /// Release the given handle.
490   void destroy() {
491     if (id) wgpu_buffer_destroy(id);
492     id = 0;
493   }
494 
495   /// Get the sliced `Buffer` data requested by either `Buffer.mapReadAsync` or `Buffer.mapWriteAsync`.
496   ubyte[] getMappedRange(BufferAddress start, BufferAddress size) {
497     assert(status == BufferMapAsyncStatus.success);
498 
499     auto data = wgpu_buffer_get_mapped_range(id, start, size);
500     return data[0 .. size];
501   }
502 
503   /// Map the buffer for reading asynchronously.
504   /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.BufferSlice.html#method.map_async">wgpu::BufferSlice::map_async</a>
505   void mapReadAsync(BufferAddress start, BufferAddress size) {
506     wgpu_buffer_map_read_async(id, start, size, &wgpu_buffer_map_callback, cast(ubyte*) &this);
507   }
508 
509   /// Map the buffer for writing asynchronously.
510   /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.BufferSlice.html#method.map_async">wgpu::BufferSlice::map_async</a>
511   void mapWriteAsync(BufferAddress start, BufferAddress size) {
512     wgpu_buffer_map_write_async(id, start, size, &wgpu_buffer_map_callback, cast(ubyte*) &this);
513   }
514 
515   /// Flushes any pending write operations and unmaps the buffer from host memory.
516   void unmap() {
517     wgpu_buffer_unmap(id);
518   }
519 }
520 
521 /// A handle to a texture on the GPU.
522 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Texture.html">wgpu::Texture</a>
523 struct Texture {
524   /// Handle identifier.
525   WgpuId id;
526   /// Describes this `Texture`.
527   TextureDescriptor descriptor;
528 
529   /// Release the given handle.
530   void destroy() {
531     if (id) wgpu_texture_destroy(id);
532     id = 0;
533   }
534 
535   /// Creates a view of this texture.
536   TextureView createView(const TextureViewDescriptor descriptor) {
537     return TextureView(wgpu_texture_create_view(id, &descriptor));
538   }
539 
540   /// Creates a default view of this whole texture.
541   TextureView createDefaultView() {
542     return TextureView(wgpu_texture_create_view(id, null));
543   }
544 }
545 
546 /// A handle to a texture view.
547 ///
548 /// A `TextureView` object describes a texture and associated metadata needed by a `RenderPipeline` or `BindGroup`.
549 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.TextureView.html">wgpu::TextureView</a>
550 struct TextureView {
551   /// Handle identifier.
552   WgpuId id;
553 }
554 
555 /// A handle to a sampler.
556 ///
557 /// A Sampler object defines how a pipeline will sample from a `TextureView`. Samplers define image
558 /// filters (including anisotropy) and address (wrapping) modes, among other things.
559 ///
560 /// See the documentation for `SamplerDescriptor` for more information.
561 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Sampler.html">wgpu::Sampler</a>
562 struct Sampler {
563   /// Handle identifier.
564   WgpuId id;
565   /// Describes this `Sampler`.
566   SamplerDescriptor descriptor;
567 }
568 
569 /// A Queue executes finished C`ommandBuffer` objects.
570 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.Queue.html">wgpu::Queue</a>
571 struct Queue {
572   /// Handle identifier.
573   WgpuId id;
574 
575   /// Submits a finished command buffer for execution.
576   void submit(CommandBuffer commands) {
577     submit([commands]);
578   }
579   /// Submits a series of finished command buffers for execution.
580   void submit(CommandBuffer[] commandBuffers) {
581     import std.algorithm.iteration : map;
582     import std.array : array;
583 
584     const commandBufferIds = commandBuffers.map!(c => c.id).array;
585     wgpu_queue_submit(id, commandBufferIds.ptr, commandBuffers.length);
586   }
587 }
588 
589 /// An opaque handle to a command buffer on the GPU.
590 ///
591 /// A `CommandBuffer` represents a complete sequence of commands that may be submitted to a command queue with `Queue.submit`.
592 /// A `CommandBuffer` is obtained by recording a series of commands to a `CommandEncoder` and then calling `CommandEncoder.finish`.
593 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.CommandBuffer.html">wgpu::CommandBuffer</a>
594 struct CommandBuffer {
595   /// Handle identifier.
596   WgpuId id;
597   /// Describes a `CommandBuffer`.
598   const CommandBufferDescriptor descriptor;
599 }
600 
601 /// A handle to a compiled shader module.
602 ///
603 /// A `ShaderModule` represents a compiled shader module on the GPU. It can be created by passing valid SPIR-V source code to `Device.createShaderModule`.
604 /// Shader modules are used to define programmable stages of a pipeline.
605 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.ShaderModule.html">wgpu::ShaderModule</a>
606 struct ShaderModule {
607   /// Handle identifier.
608   WgpuId id;
609 }
610 
611 /// An object that encodes GPU operations.
612 ///
613 /// A `CommandEncoder` can record `RenderPass`es, `ComputePass`es, and transfer operations between driver-managed resources like `Buffer`s and `Texture`s.
614 ///
615 /// When finished recording, call `CommandEncoder.finish` to obtain a `CommandBuffer` which may be submitted for execution.
616 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.CommandEncoder.html">wgpu::CommandEncoder</a>
617 struct CommandEncoder {
618   /// Handle identifier.
619   WgpuId id;
620   /// Describes a `CommandEncoder`.
621   const CommandEncoderDescriptor descriptor;
622 
623   /// Finishes recording and returns a `CommandBuffer` that can be submitted for execution.
624   CommandBuffer finish() {
625     auto commandBufferDescriptor = CommandBufferDescriptor();
626     return CommandBuffer(wgpu_command_encoder_finish(id, &commandBufferDescriptor), commandBufferDescriptor);
627   }
628 
629   /// Begins recording of a render pass.
630   ///
631   /// This function returns a `RenderPass` object which records a single render pass.
632   RenderPass beginRenderPass(const RenderPassDescriptor descriptor) {
633     return RenderPass(wgpu_command_encoder_begin_render_pass(id, &descriptor));
634   }
635 
636   /// Begins recording of a compute pass.
637   ///
638   /// This function returns a `ComputePass` object which records a single compute pass.
639   ComputePass beginComputePass(const ComputePassDescriptor descriptor) {
640     return ComputePass(wgpu_command_encoder_begin_compute_pass(id, &descriptor));
641   }
642 
643   /// Copy data from a texture to a buffer.
644   void copyTextureToBuffer(const TextureCopyView source, const BufferCopyView destination, const Extent3d copySize) {
645     wgpu_command_encoder_copy_texture_to_buffer(id, &source, &destination, &copySize);
646   }
647 }
648 
649 /// An opaque handle to a binding group.
650 ///
651 /// A `BindGroup` represents the set of resources bound to the bindings described by a `BindGroupLayout`.
652 /// It can be created with `Device.createBindGroup`. A `BindGroup` can be bound to a particular `RenderPass`
653 /// with `RenderPass.setBindGroup`, or to a `ComputePass` with `ComputePass.setBindGroup`.
654 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.BindGroup.html">wgpu::BindGroup</a>
655 struct BindGroup {
656   /// Handle identifier.
657   WgpuId id;
658   /// Describes this `BindGroup`.
659   BindGroupDescriptor descriptor;
660 }
661 
662 /// An opaque handle to a binding group layout.
663 ///
664 /// A `BindGroupLayout` is a handle to the GPU-side layout of a binding group. It can be used to create
665 /// a `BindGroupDescriptor` object, which in turn can be used to create a `BindGroup` object with
666 /// `Device.createBindGroup`. A series of `BindGroupLayout`s can also be used to create a
667 /// `PipelineLayoutDescriptor`, which can be used to create a `PipelineLayout`.
668 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.BindGroupLayout.html">wgpu::BindGroupLayout</a>
669 struct BindGroupLayout {
670   /// Handle identifier.
671   WgpuId id;
672   /// Describes this `BindGroupLayout`.
673   BindGroupLayoutDescriptor descriptor;
674 }
675 
676 /// An opaque handle to a pipeline layout.
677 ///
678 /// A `PipelineLayout` object describes the available binding groups of a pipeline.
679 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.PipelineLayout.html">wgpu::PipelineLayout</a>
680 struct PipelineLayout {
681   /// Handle identifier.
682   WgpuId id;
683   /// Describes this `PipelineLayout`.
684   PipelineLayoutDescriptor descriptor;
685 }
686 
687 /// A handle to a rendering (graphics) pipeline.
688 ///
689 /// A `RenderPipeline` object represents a graphics pipeline and its stages, bindings, vertex buffers and targets.
690 /// A `RenderPipeline` may be created with `Device.createRenderPipeline`.
691 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.RenderPipeline.html">wgpu::RenderPipeline</a>
692 struct RenderPipeline {
693   /// Handle identifier.
694   WgpuId id;
695   /// Describes this `RenderPipeline`.
696   RenderPipelineDescriptor descriptor;
697 
698   /// Release the given handle.
699   void destroy() {
700     if (id) wgpu_render_pipeline_destroy(id);
701     id = 0;
702   }
703 }
704 
705 /// An in-progress recording of a render pass.
706 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.RenderPass.html">wgpu::RenderPass</a>
707 struct RenderPass {
708   import std.typecons : Tuple;
709 
710   package WGPURenderPass* instance;
711   /// Describes this `RenderPass`.
712   RenderPassDescriptor descriptor;
713 
714   /// Sets the active bind group for a given bind group index.
715   void setBindGroup(const uint index, const BindGroup bindGroup, BufferAddress[] offsets) {
716     import std.algorithm.iteration : map;
717     import std.array : array;
718 
719     auto offsetsAsUints = offsets.map!(offset => offset.to!(const uint)).array;
720     wgpu_render_pass_set_bind_group(instance, index, bindGroup.id, offsetsAsUints.ptr, offsets.length);
721   }
722 
723   /// Sets the active render pipeline.
724   ///
725   /// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
726   void setPipeline(const RenderPipeline pipeline) {
727     wgpu_render_pass_set_pipeline(instance, pipeline.id);
728   }
729 
730   void setBlendColor(const Color color) {
731     wgpu_render_pass_set_blend_color(instance, &color);
732   }
733 
734   /// Sets the active index buffer.
735   ///
736   /// Subsequent calls to `drawIndexed` on this `RenderPass` will use buffer as the source index buffer.
737   void setIndexBuffer(const Buffer buffer, const BufferAddress offset) {
738     wgpu_render_pass_set_index_buffer(instance, buffer.id, offset, buffer.descriptor.size);
739   }
740 
741   /// Sets the active vertex buffers, starting from `startSlot`.
742   ///
743   /// Each element of `bufferPairs` describes a vertex buffer and an offset in bytes into that buffer.
744   /// The offset must be aligned to a multiple of 4 bytes.
745   void setVertexBuffers(uint startSlot, Tuple!(Buffer, BufferAddress)[] bufferPairs) {
746     foreach (bufferPair; bufferPairs) {
747       auto buffer = bufferPair[0];
748       auto bufferAddress = bufferPair[1];
749       wgpu_render_pass_set_vertex_buffer(instance, startSlot, buffer.id, bufferAddress, buffer.descriptor.size);
750     }
751   }
752 
753   /// Sets the scissor region.
754   ///
755   /// Subsequent draw calls will discard any fragments that fall outside this region.
756   void setScissorRect(uint x, uint y, uint w, uint h) {
757     wgpu_render_pass_set_scissor_rect(instance, x, y, w, h);
758   }
759 
760   /// Sets the viewport region.
761   ///
762   /// Subsequent draw calls will draw any fragments in this region.
763   void setViewport(float x, float y, float w, float h, float minDepth, float maxDepth) {
764     wgpu_render_pass_set_viewport(instance, x, y, w, h, minDepth, maxDepth);
765   }
766 
767   /// Sets the stencil reference.
768   ///
769   /// Subsequent stencil tests will test against this value.
770   void setStencilReference(uint reference) {
771     wgpu_render_pass_set_stencil_reference(instance, reference);
772   }
773 
774   /// Draws primitives from the active vertex buffer(s).
775   ///
776   /// The active vertex buffers can be set with `RenderPass.setVertexBuffers`.
777   void draw(uint[] vertices, uint[] instances) {
778     assert(vertices.length);
779     assert(instances.length);
780   }
781 
782   /// Draws indexed primitives using the active index buffer and the active vertex buffers.
783   ///
784   /// The active index buffer can be set with `RenderPass.setIndexBuffer`, while the active vertex
785   /// buffers can be set with `RenderPass.setVertexBuffers`.
786   void drawIndexed(uint[] indices, int baseVertex, uint[] instances) {
787     assert(indices.length);
788     assert(baseVertex >= 0);
789     assert(instances.length);
790   }
791 }
792 
793 /// A handle to a compute pipeline.
794 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.ComputePipeline.html">wgpu::ComputePipeline</a>
795 struct ComputePipeline {
796   /// Handle identifier.
797   WgpuId id;
798   /// Describes this `ComputePipeline`.
799   ComputePipelineDescriptor descriptor;
800 
801   /// Release the given handle.
802   void destroy() {
803     if (id) wgpu_compute_pipeline_destroy(id);
804     id = 0;
805   }
806 }
807 
808 /// An in-progress recording of a compute pass.
809 /// See_Also: <a href="https://docs.rs/wgpu/0.6.0/wgpu/struct.ComputePass.html">wgpu::ComputePass</a>
810 struct ComputePass {
811   package WGPUComputePass* instance;
812   /// Describes this `ComputePass`.
813   ComputePassDescriptor descriptor;
814 
815   /// Sets the active bind group for a given bind group index.
816   void setBindGroup(const uint index, const BindGroup bindGroup, BufferAddress[] offsets) {
817     import std.algorithm.iteration : map;
818     import std.array : array;
819 
820     auto offsetsAsUints = offsets.map!(offset => offset.to!(const uint)).array;
821     wgpu_compute_pass_set_bind_group(instance, index, bindGroup.id, offsetsAsUints.ptr, offsets.length);
822   }
823 
824   /// Sets the active compute pipeline.
825   void setPipeline(const ComputePipeline pipeline) {
826     wgpu_compute_pass_set_pipeline(instance, pipeline.id);
827   }
828 
829   ///Dispatches compute work operations.
830   ///
831   /// x, y and z denote the number of work groups to dispatch in each dimension.
832   void dispatch(const uint x, const uint y, const uint z) {
833     wgpu_compute_pass_dispatch(instance, x, y, z);
834   }
835 }