wgpu 1.2.0 → 1.2.1

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/README.md +18 -2
  4. data/docs/README.md +2 -2
  5. data/docs/api_coverage.md +23 -15
  6. data/docs/async.md +10 -0
  7. data/docs/command_encoding.md +25 -0
  8. data/docs/getting_started_compute.md +1 -0
  9. data/docs/pipeline_descriptors.md +7 -2
  10. data/docs/releasing.md +11 -1
  11. data/docs/resource_lifetime.md +16 -2
  12. data/docs/texture_readback.md +27 -0
  13. data/docs/troubleshooting.md +5 -0
  14. data/docs/upgrading_wgpu_native.md +16 -5
  15. data/lib/wgpu/async_task.rb +19 -0
  16. data/lib/wgpu/commands/command_buffer.rb +14 -1
  17. data/lib/wgpu/commands/command_encoder.rb +58 -1
  18. data/lib/wgpu/commands/compute_pass.rb +43 -0
  19. data/lib/wgpu/commands/render_bundle.rb +9 -1
  20. data/lib/wgpu/commands/render_bundle_encoder.rb +55 -1
  21. data/lib/wgpu/commands/render_pass.rb +102 -0
  22. data/lib/wgpu/core/adapter.rb +91 -12
  23. data/lib/wgpu/core/async_waiter.rb +15 -0
  24. data/lib/wgpu/core/canvas_context.rb +32 -0
  25. data/lib/wgpu/core/device.rb +296 -46
  26. data/lib/wgpu/core/instance.rb +20 -0
  27. data/lib/wgpu/core/queue.rb +139 -24
  28. data/lib/wgpu/core/surface.rb +49 -1
  29. data/lib/wgpu/data_types.rb +16 -0
  30. data/lib/wgpu/descriptor_helpers.rb +65 -0
  31. data/lib/wgpu/error.rb +15 -0
  32. data/lib/wgpu/native/abi_verifier.rb +37 -3
  33. data/lib/wgpu/native/callbacks.rb +6 -0
  34. data/lib/wgpu/native/capabilities.rb +16 -2
  35. data/lib/wgpu/native/distribution.rb +63 -0
  36. data/lib/wgpu/native/enum_helper.rb +17 -0
  37. data/lib/wgpu/native/enums.rb +8 -0
  38. data/lib/wgpu/native/fixtures/webgpu-v27.0.4.0-enums.h +848 -0
  39. data/lib/wgpu/native/functions.rb +11 -0
  40. data/lib/wgpu/native/installer.rb +48 -17
  41. data/lib/wgpu/native/loader.rb +22 -0
  42. data/lib/wgpu/native/structs.rb +18 -1
  43. data/lib/wgpu/native_resource.rb +174 -3
  44. data/lib/wgpu/pipeline/bind_group.rb +9 -0
  45. data/lib/wgpu/pipeline/bind_group_layout.rb +17 -4
  46. data/lib/wgpu/pipeline/compute_pipeline.rb +20 -32
  47. data/lib/wgpu/pipeline/pipeline_layout.rb +8 -0
  48. data/lib/wgpu/pipeline/render_pipeline.rb +27 -42
  49. data/lib/wgpu/pipeline/shader_module.rb +54 -29
  50. data/lib/wgpu/resources/buffer.rb +258 -31
  51. data/lib/wgpu/resources/query_set.rb +12 -0
  52. data/lib/wgpu/resources/sampler.rb +7 -0
  53. data/lib/wgpu/resources/texture.rb +45 -6
  54. data/lib/wgpu/resources/texture_view.rb +24 -4
  55. data/lib/wgpu/texture_format.rb +14 -0
  56. data/lib/wgpu/version.rb +1 -1
  57. data/lib/wgpu/window.rb +26 -0
  58. data/sig/wgpu.rbs +84 -5
  59. metadata +3 -1
@@ -3,10 +3,14 @@
3
3
  module WGPU
4
4
  module Native
5
5
  class << self
6
+ # Reports whether future-based callback waiting is available.
7
+ # @return [Boolean]
6
8
  def future_api?
7
9
  optional_function_available?(:wgpuInstanceWaitAny)
8
10
  end
9
11
 
12
+ # Reports whether explicit device polling is available.
13
+ # @return [Boolean]
10
14
  def device_poll_available?
11
15
  optional_function_available?(:wgpuDevicePoll)
12
16
  end
@@ -15,13 +19,23 @@ module WGPU
15
19
  # implementation is a Rust panic stub. Calling it aborts the process, so
16
20
  # symbol presence alone cannot be used as a capability check.
17
21
  def compilation_info_available?
18
- Distribution::VERSION != "v27.0.4.0"
22
+ Distribution.capability_implemented?(:compilation_info)
19
23
  end
20
24
 
25
+ # Reports whether querying buffer map state is safe in the pinned runtime.
26
+ # @return [Boolean]
21
27
  def buffer_map_state_available?
22
- Distribution::VERSION != "v27.0.4.0"
28
+ Distribution.capability_implemented?(:buffer_map_state)
23
29
  end
24
30
 
31
+ # Reports whether native asynchronous pipeline creation is implemented.
32
+ # @return [Boolean]
33
+ def pipeline_async_available?
34
+ Distribution.capability_implemented?(:pipeline_async)
35
+ end
36
+
37
+ # Reports whether native logging callbacks and levels are available.
38
+ # @return [Boolean]
25
39
  def logging_available?
26
40
  optional_function_available?(:wgpuSetLogCallback) &&
27
41
  optional_function_available?(:wgpuSetLogLevel)
@@ -7,6 +7,17 @@ module WGPU
7
7
  module Distribution
8
8
  VERSION = "v27.0.4.0"
9
9
  RELEASE_BASE_URL = "https://github.com/gfx-rs/wgpu-native/releases/download/#{VERSION}"
10
+ VERSION_COMPONENTS = VERSION.delete_prefix("v").split(".").map { |part| Integer(part, 10) }.freeze
11
+ unless VERSION_COMPONENTS.length == 4 && VERSION_COMPONENTS.all? { |part| part.between?(0, 255) }
12
+ raise "wgpu-native VERSION must have four byte-sized components: #{VERSION}"
13
+ end
14
+ # wgpuGetVersion packs vMAJOR.MINOR.PATCH.BUILD into four big-endian bytes.
15
+ ENCODED_VERSION = VERSION_COMPONENTS.reduce(0) { |encoded, part| (encoded << 8) | part }
16
+ UNIMPLEMENTED_CAPABILITIES = {
17
+ compilation_info: [VERSION].freeze,
18
+ buffer_map_state: [VERSION].freeze,
19
+ pipeline_async: [VERSION].freeze
20
+ }.freeze
10
21
 
11
22
  ARTIFACTS = [
12
23
  {
@@ -43,6 +54,10 @@ module WGPU
43
54
 
44
55
  module_function
45
56
 
57
+ # Selects the native release artifact for a Ruby platform.
58
+ # @param platform [String] Ruby platform identifier
59
+ # @return [Hash] artifact metadata
60
+ # @raise [LoadError] if the platform is unsupported
46
61
  def artifact_for(platform = RUBY_PLATFORM)
47
62
  raise LoadError, unsupported_platform_message(platform) if platform.include?("musl")
48
63
 
@@ -52,6 +67,12 @@ module WGPU
52
67
  raise LoadError, unsupported_platform_message(platform)
53
68
  end
54
69
 
70
+ # Returns the preferred versioned native-library cache directory.
71
+ #
72
+ # @param env [Hash] environment used for cache overrides
73
+ # @param home [String] user home directory
74
+ # @param host_os [String] host operating-system identifier
75
+ # @return [String] absolute cache directory
55
76
  def primary_cache_dir(env: ENV, home: Dir.home, host_os: RbConfig::CONFIG["host_os"])
56
77
  override = present_value(env["WGPU_CACHE_DIR"])
57
78
  return File.join(File.expand_path(override), VERSION) if override
@@ -62,24 +83,66 @@ module WGPU
62
83
  File.join(default_cache_base(env:, home:, host_os:), "wgpu-ruby", VERSION)
63
84
  end
64
85
 
86
+ # Returns the legacy versioned cache directory.
87
+ #
88
+ # @param home [String] user home directory
89
+ # @return [String] absolute legacy cache directory
65
90
  def legacy_cache_dir(home: Dir.home)
66
91
  File.join(File.expand_path(home), ".cache", "wgpu-ruby", VERSION)
67
92
  end
68
93
 
94
+ # Returns cache directories in lookup order.
95
+ #
96
+ # @param env [Hash] environment used for cache overrides
97
+ # @param home [String] user home directory
98
+ # @param host_os [String] host operating-system identifier
99
+ # @return [Array<String>] unique cache directories
69
100
  def cache_directories(env: ENV, home: Dir.home, host_os: RbConfig::CONFIG["host_os"])
70
101
  [primary_cache_dir(env:, home:, host_os:), legacy_cache_dir(home:)].uniq
71
102
  end
72
103
 
104
+ # Returns candidate cached library paths for a platform.
105
+ #
106
+ # @param platform [String] Ruby platform identifier
107
+ # @param env [Hash] environment used for cache overrides
108
+ # @param home [String] user home directory
109
+ # @param host_os [String] host operating-system identifier
110
+ # @return [Array<String>] candidate shared-library paths
111
+ # @raise [LoadError] if the platform is unsupported
73
112
  def library_paths(platform: RUBY_PLATFORM, env: ENV, home: Dir.home,
74
113
  host_os: RbConfig::CONFIG["host_os"])
75
114
  library = artifact_for(platform)[:library]
76
115
  cache_directories(env:, home:, host_os:).map { |directory| File.join(directory, "lib", library) }
77
116
  end
78
117
 
118
+ # Builds the download URL for an artifact entry.
119
+ #
120
+ # @param artifact [Hash] entry from {ARTIFACTS}
121
+ # @return [String] release archive URL
79
122
  def release_url(artifact)
80
123
  "#{RELEASE_BASE_URL}/#{artifact.fetch(:archive)}"
81
124
  end
82
125
 
126
+ # Decodes the packed native version into a release tag.
127
+ #
128
+ # @param encoded_version [Integer] four-byte packed version
129
+ # @return [String] version in +vMAJOR.MINOR.PATCH.BUILD+ form
130
+ def version_string(encoded_version)
131
+ components = [24, 16, 8, 0].map { |shift| (encoded_version >> shift) & 0xFF }
132
+ "v#{components.join(".")}"
133
+ end
134
+
135
+ # Reports whether a native capability is implemented by the pinned release.
136
+ # @param name [Symbol] capability name
137
+ # @return [Boolean]
138
+ def capability_implemented?(name)
139
+ !UNIMPLEMENTED_CAPABILITIES.fetch(name, []).include?(VERSION)
140
+ end
141
+
142
+ # Builds an actionable unsupported-platform message.
143
+ #
144
+ # @param platform [String] Ruby platform identifier
145
+ # @return [String] diagnostic message
83
146
  def unsupported_platform_message(platform)
84
147
  supported = ARTIFACTS.map { |artifact| artifact[:pattern].inspect }.join(", ")
85
148
  <<~MESSAGE.chomp
@@ -5,6 +5,12 @@ module WGPU
5
5
  module EnumHelper
6
6
  module_function
7
7
 
8
+ # Converts a symbolic enum member to its integer value.
9
+ # @param enum [FFI::Enum, Hash] enum mapping
10
+ # @param value [Symbol, Integer] member or native value
11
+ # @param name [String] name used in validation errors
12
+ # @return [Integer]
13
+ # @raise [ArgumentError] if the value is invalid
8
14
  def coerce(enum, value, name: "enum")
9
15
  return value if value.is_a?(Integer)
10
16
  raise ArgumentError, "#{name} must be a Symbol or Integer, got #{value.class}" unless value.is_a?(Symbol)
@@ -16,6 +22,13 @@ module WGPU
16
22
  raise ArgumentError, unknown_value_message(name, value, mapping.keys)
17
23
  end
18
24
 
25
+ # Converts symbolic flag names to their combined integer bitset.
26
+ #
27
+ # @param enum [FFI::Enum, Hash] flag mapping
28
+ # @param value [Symbol, Integer, Array<Symbol>] flags to convert
29
+ # @param name [String] name used in validation errors
30
+ # @return [Integer] combined bitset
31
+ # @raise [ArgumentError] if a flag is unknown or has an invalid type
19
32
  def coerce_flags(enum, value, name: "flags")
20
33
  return value if value.is_a?(Integer)
21
34
 
@@ -27,6 +40,10 @@ module WGPU
27
40
  values.reduce(0) { |flags, item| flags | coerce(enum, item, name:) }
28
41
  end
29
42
 
43
+ # Expands a bitset into its independent symbolic flags.
44
+ # @param enum [FFI::Enum, Hash] flag mapping
45
+ # @param value [Integer] combined bitset
46
+ # @return [Array<Symbol>]
30
47
  def decompose_flags(enum, value)
31
48
  raise ArgumentError, "flag value must be an Integer" unless value.is_a?(Integer)
32
49
 
@@ -61,6 +61,14 @@ module WGPU
61
61
  :unknown, 0x00000004
62
62
  )
63
63
 
64
+ CreatePipelineAsyncStatus = enum(
65
+ :success, 0x00000001,
66
+ :instance_dropped, 0x00000002,
67
+ :validation_error, 0x00000003,
68
+ :internal_error, 0x00000004,
69
+ :unknown, 0x00000005
70
+ )
71
+
64
72
  DeviceLostReason = enum(
65
73
  :unknown, 0x00000001,
66
74
  :destroyed, 0x00000002,