wgpu 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WGPU
4
+ class Surface
5
+ attr_reader :handle
6
+
7
+ def self.from_metal_layer(instance, layer)
8
+ source = Native::SurfaceSourceMetalLayer.new
9
+ source[:chain][:next] = nil
10
+ source[:chain][:s_type] = Native::SType[:surface_descriptor_from_metal_layer]
11
+ source[:layer] = layer
12
+
13
+ desc = Native::SurfaceDescriptor.new
14
+ desc[:next_in_chain] = source.to_ptr
15
+ desc[:label][:data] = nil
16
+ desc[:label][:length] = 0
17
+
18
+ handle = Native.wgpuInstanceCreateSurface(instance.handle, desc)
19
+ raise SurfaceError, "Failed to create surface from Metal layer" if handle.null?
20
+
21
+ new(handle, instance)
22
+ end
23
+
24
+ def self.from_windows_hwnd(instance, hinstance, hwnd)
25
+ source = Native::SurfaceSourceWindowsHWND.new
26
+ source[:chain][:next] = nil
27
+ source[:chain][:s_type] = Native::SType[:surface_descriptor_from_windows_hwnd]
28
+ source[:hinstance] = hinstance
29
+ source[:hwnd] = hwnd
30
+
31
+ desc = Native::SurfaceDescriptor.new
32
+ desc[:next_in_chain] = source.to_ptr
33
+ desc[:label][:data] = nil
34
+ desc[:label][:length] = 0
35
+
36
+ handle = Native.wgpuInstanceCreateSurface(instance.handle, desc)
37
+ raise SurfaceError, "Failed to create surface from Windows HWND" if handle.null?
38
+
39
+ new(handle, instance)
40
+ end
41
+
42
+ def self.from_xlib_window(instance, display, window)
43
+ source = Native::SurfaceSourceXlibWindow.new
44
+ source[:chain][:next] = nil
45
+ source[:chain][:s_type] = Native::SType[:surface_descriptor_from_xlib_window]
46
+ source[:display] = display
47
+ source[:window] = window
48
+
49
+ desc = Native::SurfaceDescriptor.new
50
+ desc[:next_in_chain] = source.to_ptr
51
+ desc[:label][:data] = nil
52
+ desc[:label][:length] = 0
53
+
54
+ handle = Native.wgpuInstanceCreateSurface(instance.handle, desc)
55
+ raise SurfaceError, "Failed to create surface from Xlib window" if handle.null?
56
+
57
+ new(handle, instance)
58
+ end
59
+
60
+ def self.from_wayland_surface(instance, display, surface)
61
+ source = Native::SurfaceSourceWaylandSurface.new
62
+ source[:chain][:next] = nil
63
+ source[:chain][:s_type] = Native::SType[:surface_descriptor_from_wayland_surface]
64
+ source[:display] = display
65
+ source[:surface] = surface
66
+
67
+ desc = Native::SurfaceDescriptor.new
68
+ desc[:next_in_chain] = source.to_ptr
69
+ desc[:label][:data] = nil
70
+ desc[:label][:length] = 0
71
+
72
+ handle = Native.wgpuInstanceCreateSurface(instance.handle, desc)
73
+ raise SurfaceError, "Failed to create surface from Wayland surface" if handle.null?
74
+
75
+ new(handle, instance)
76
+ end
77
+
78
+ def initialize(handle, instance)
79
+ @handle = handle
80
+ @instance = instance
81
+ @configured = false
82
+ end
83
+
84
+ def configure(device:, format:, usage: :render_attachment, width:, height:, present_mode: :fifo, alpha_mode: :auto, view_formats: [])
85
+ config = Native::SurfaceConfiguration.new
86
+ config[:next_in_chain] = nil
87
+ config[:device] = device.handle
88
+ config[:format] = format
89
+ config[:usage] = normalize_usage(usage)
90
+ config[:width] = width
91
+ config[:height] = height
92
+ config[:view_format_count] = view_formats.size
93
+ config[:view_formats] = nil
94
+ config[:alpha_mode] = Native::CompositeAlphaMode[alpha_mode]
95
+ config[:present_mode] = Native::PresentMode[present_mode]
96
+
97
+ Native.wgpuSurfaceConfigure(@handle, config)
98
+ @configured = true
99
+ @device = device
100
+ end
101
+
102
+ def unconfigure
103
+ Native.wgpuSurfaceUnconfigure(@handle)
104
+ @configured = false
105
+ end
106
+
107
+ def current_texture
108
+ raise SurfaceError, "Surface is not configured" unless @configured
109
+
110
+ surface_texture = Native::SurfaceTexture.new
111
+ Native.wgpuSurfaceGetCurrentTexture(@handle, surface_texture)
112
+
113
+ status = Native::SurfaceGetCurrentTextureStatus[surface_texture[:status]]
114
+ unless status == :success
115
+ raise SurfaceError, "Failed to get current texture: #{status}"
116
+ end
117
+
118
+ Texture.from_handle(surface_texture[:texture])
119
+ end
120
+
121
+ def present
122
+ Native.wgpuSurfacePresent(@handle)
123
+ end
124
+
125
+ def capabilities(adapter)
126
+ caps = Native::SurfaceCapabilities.new
127
+ Native.wgpuSurfaceGetCapabilities(@handle, adapter.handle, caps)
128
+
129
+ formats = []
130
+ if caps[:format_count] > 0 && !caps[:formats].null?
131
+ formats = caps[:formats].read_array_of_uint32(caps[:format_count]).map do |f|
132
+ Native::TextureFormat[f]
133
+ end
134
+ end
135
+
136
+ present_modes = []
137
+ if caps[:present_mode_count] > 0 && !caps[:present_modes].null?
138
+ present_modes = caps[:present_modes].read_array_of_uint32(caps[:present_mode_count]).map do |m|
139
+ Native::PresentMode[m]
140
+ end
141
+ end
142
+
143
+ alpha_modes = []
144
+ if caps[:alpha_mode_count] > 0 && !caps[:alpha_modes].null?
145
+ alpha_modes = caps[:alpha_modes].read_array_of_uint32(caps[:alpha_mode_count]).map do |a|
146
+ Native::CompositeAlphaMode[a]
147
+ end
148
+ end
149
+
150
+ {
151
+ formats: formats,
152
+ present_modes: present_modes,
153
+ alpha_modes: alpha_modes,
154
+ usages: caps[:usages]
155
+ }
156
+ end
157
+
158
+ def release
159
+ return if @handle.null?
160
+ Native.wgpuSurfaceRelease(@handle)
161
+ @handle = FFI::Pointer::NULL
162
+ end
163
+
164
+ private
165
+
166
+ def normalize_usage(usage)
167
+ case usage
168
+ when Integer
169
+ usage
170
+ when Symbol
171
+ Native::TextureUsage[usage]
172
+ when Array
173
+ usage.reduce(0) { |acc, u| acc | Native::TextureUsage[u] }
174
+ else
175
+ raise ArgumentError, "Invalid usage: #{usage}"
176
+ end
177
+ end
178
+ end
179
+ end
data/lib/wgpu/error.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WGPU
4
+ class Error < StandardError; end
5
+ class InitializationError < Error; end
6
+ class AdapterError < Error; end
7
+ class DeviceError < Error; end
8
+ class BufferError < Error; end
9
+ class TextureError < Error; end
10
+ class ResourceError < Error; end
11
+ class ShaderError < Error; end
12
+ class PipelineError < Error; end
13
+ class CommandError < Error; end
14
+ class SurfaceError < Error; end
15
+ class RenderBundleError < Error; end
16
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WGPU
4
+ module Native
5
+ callback :request_adapter_callback,
6
+ [RequestAdapterStatus, :pointer, StringView.by_value, :pointer], :void
7
+
8
+ callback :request_device_callback,
9
+ [RequestDeviceStatus, :pointer, StringView.by_value, :pointer], :void
10
+
11
+ callback :buffer_map_callback,
12
+ [MapAsyncStatus, :pointer], :void
13
+
14
+ callback :error_callback,
15
+ [:uint32, StringView.by_value, :pointer], :void
16
+
17
+ callback :device_lost_callback,
18
+ [:pointer, :uint32, StringView.by_value, :pointer], :void
19
+
20
+ callback :pop_error_scope_callback,
21
+ [PopErrorScopeStatus, ErrorType, StringView.by_value, :pointer, :pointer], :void
22
+
23
+ callback :queue_work_done_callback,
24
+ [QueueWorkDoneStatus, :pointer, :pointer], :void
25
+ end
26
+ end