Skip to content

Commit acebbdd

Browse files
committed
Fixes #15: Add Identifiable and Composite for shader management
- Introduced `Identifiable` conformance for `ShaderLibrary` and `ShaderFunction` using a composite identifier for unique identificat ion. - Defined `ShaderLibrary.ID` with cases for bundle and source identification. - Implemented a new `Composite` struct for handling multiple identifier types, equipped with `Equatable`, `Hashable`, and `Sendable` .
1 parent cbbd0d6 commit acebbdd

2 files changed

Lines changed: 49 additions & 5 deletions

File tree

Sources/Compute/ShaderFunction.swift

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import Metal
22

33
/// Represents a Metal shader library.
44
@dynamicMemberLookup
5-
public struct ShaderLibrary: Sendable {
5+
public struct ShaderLibrary: Identifiable, Sendable {
6+
public enum ID: Hashable, Sendable {
7+
case bundle(URL, String?)
8+
case source(String)
9+
}
10+
611
/// The default shader library loaded from the main bundle.
712
public static let `default` = Self.bundle(.main)
813

@@ -13,7 +18,7 @@ public struct ShaderLibrary: Sendable {
1318
/// - name: The name of the metallib file (without extension). If nil, uses the default library.
1419
/// - Returns: A new ShaderLibrary instance.
1520
public static func bundle(_ bundle: Bundle, name: String? = nil) -> Self {
16-
Self { device in
21+
return ShaderLibrary(id: .bundle(bundle.bundleURL, name)) { device in
1722
if let name {
1823
guard let url = bundle.url(forResource: name, withExtension: "metallib") else {
1924
fatalError("Could not load metallib.")
@@ -35,7 +40,7 @@ public struct ShaderLibrary: Sendable {
3540
/// - enableLogging: Enable Metal shader logging.
3641
/// - Returns: A new ShaderLibrary instance.
3742
public static func source(_ source: String, enableLogging: Bool = false) -> Self {
38-
Self { device in
43+
return ShaderLibrary(id: .source(source)) { device in
3944
let options = MTLCompileOptions()
4045
#if !targetEnvironment(simulator)
4146
if enableLogging {
@@ -51,8 +56,10 @@ public struct ShaderLibrary: Sendable {
5156
}
5257
}
5358

59+
public var id: ID
60+
5461
/// A closure that creates an MTLLibrary given an MTLDevice.
55-
var make: @Sendable (MTLDevice) throws -> MTLLibrary
62+
public var make: @Sendable (MTLDevice) throws -> MTLLibrary
5663

5764
/// Creates a ShaderFunction with the given name.
5865
///
@@ -83,7 +90,7 @@ public struct ShaderLibrary: Sendable {
8390
/// Represents a compute shader function within a shader library.
8491
public struct ShaderFunction: Identifiable {
8592
/// A unique identifier for the shader function.
86-
public let id = UUID()
93+
public let id: Composite<ShaderLibrary.ID, String>
8794

8895
/// The shader library containing this function.
8996
public let library: ShaderLibrary
@@ -101,6 +108,8 @@ public struct ShaderFunction: Identifiable {
101108
/// - name: The name of the shader function.
102109
/// - constants: An array of shader constants associated with this function. Defaults to an empty array.
103110
public init(library: ShaderLibrary, name: String, constants: [ShaderConstant] = []) {
111+
// TODO: Make shader constants part of name id
112+
self.id = Composite(library.id, name)
104113
self.library = library
105114
self.name = name
106115
self.constants = constants
@@ -120,6 +129,7 @@ public struct ShaderConstant {
120129
/// - Parameters:
121130
/// - dataType: The Metal data type of the constant.
122131
/// - value: The array value of the constant.
132+
// BUG: https://github.com/schwa/Compute/issues/16 Get away from Any and use an enum.
123133
public init(dataType: MTLDataType, value: [some Any]) {
124134
self.dataType = dataType
125135
accessor = { (callback: (UnsafeRawPointer) -> Void) in
@@ -137,6 +147,7 @@ public struct ShaderConstant {
137147
/// - Parameters:
138148
/// - dataType: The Metal data type of the constant.
139149
/// - value: The value of the constant.
150+
// BUG: https://github.com/schwa/Compute/issues/16 Get away from Any and use an enum.
140151
public init(dataType: MTLDataType, value: some Any) {
141152
self.dataType = dataType
142153
accessor = { (callback: (UnsafeRawPointer) -> Void) in

Sources/Compute/Support.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,36 @@ internal extension MTLSize {
113113
return "[\(width), \(height), \(depth)]"
114114
}
115115
}
116+
117+
// MARK: -
118+
119+
public struct Composite <each T> {
120+
private let children: (repeat each T)
121+
122+
public init(_ children: repeat each T) {
123+
self.children = (repeat each children)
124+
}
125+
}
126+
127+
extension Composite: Equatable where repeat each T: Equatable {
128+
public static func == (lhs: Self, rhs: Self) -> Bool {
129+
for (left, right) in repeat (each lhs.children, each rhs.children) {
130+
guard left == right else {
131+
return false
132+
}
133+
}
134+
return true
135+
}
136+
}
137+
138+
extension Composite: Hashable where repeat each T: Hashable {
139+
public func hash(into hasher: inout Hasher) {
140+
for child in repeat (each children) {
141+
child.hash(into: &hasher)
142+
}
143+
}
144+
}
145+
146+
extension Composite: Sendable where repeat each T: Sendable {
147+
}
148+

0 commit comments

Comments
 (0)