Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions SwiftUsd.docc/AboutThisRepo/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ Changes to SwiftUsd
```
}

### TBD
Released TBD, based on OpenUSD TBD
- Add zero-copy `VtArray` reads via `withUnsafeBufferPointer(_:)` and single-copy construction from an `UnsafeBufferPointer`

### 8.0.0
Released 2026-07-22, based on OpenUSD v26.08
- Add support for writing, distributing, and using OpenUSD plugins in Swift/C++ with Swift Package Manager
Expand Down
47 changes: 47 additions & 0 deletions source/SwiftOverlay/VtArray.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===----------------------------------------------------------------------===//
// This source file is part of github.com/apple/SwiftUsd
//
// Copyright © 2025 Apple Inc. and the SwiftUsd project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
//===----------------------------------------------------------------------===//

#ifndef SWIFTUSD_SWIFTOVERLAY_VTARRAY_H
#define SWIFTUSD_SWIFTOVERLAY_VTARRAY_H

#include <type_traits>
#include "pxr/base/vt/array.h"

namespace __Overlay {
// expose `assign` in a way Swift will import. VtArray uses copy-on-write
// storage, so this constructs the array with a single copy of the source
// range, rather than the element-by-element push_back the Collection
// initializer falls back to.
//
// Swift 6.3 fixes https://github.com/swiftlang/swift/pull/82161, but on Swift 6.1 and Swift 6.2,
// templated methods taking pointers without nullability annotations are assumed to be non-null,
// and templated methods taking pointers with nullability annotations aren't imported. So,
// use ptrdiff_t instead
template <typename VtArray>
inline void VtArray_assign(VtArray& array, ptrdiff_t frontPtr, ptrdiff_t backPtr) {
using Element = typename VtArray::ElementType;
static_assert(std::is_same_v<VtArray, pxr::VtArray<Element>>);
const Element* front = reinterpret_cast<const Element*>(frontPtr);
const Element* back = reinterpret_cast<const Element*>(backPtr);
array.assign(front, back);
}
}

#endif // SWIFTUSD_SWIFTOVERLAY_VTARRAY_H
292 changes: 246 additions & 46 deletions source/SwiftOverlay/VtArrayProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,21 @@ extension __Overlay {
associatedtype ElementType
func __beginUnsafe() -> UnsafePointer<ElementType>?
func __endUnsafe() -> UnsafePointer<ElementType>?

func __cdataUnsafe() -> UnsafePointer<ElementType>?
func size() -> Int

mutating func __assign(_ p: UnsafeBufferPointer<ElementType>)
}
}
extension __Overlay.VtArray_Sequence where Element == Self.ElementType {
public func makeIterator() -> __Overlay.VtArray_Sequence_Iterator<Self> {
.init(begin: __beginUnsafe(), end: __endUnsafe(), s: self)
}

public borrowing func withUnsafeBufferPointer<T, E>(_ code: (UnsafeBufferPointer<ElementType>) throws(E) -> T) throws(E) -> T {
try code(UnsafeBufferPointer(start: __cdataUnsafe(), count: size()))
}
}

extension __Overlay {
Expand All @@ -132,65 +141,256 @@ extension __Overlay {
}
}

extension pxr.VtBoolArray: __Overlay.VtArrayProtocol {}
extension pxr.VtDoubleArray: __Overlay.VtArrayProtocol {}
extension pxr.VtFloatArray: __Overlay.VtArrayProtocol {}
extension pxr.VtHalfArray: __Overlay.VtArrayProtocol {}
extension __Overlay.VtArrayProtocol {
public init(_ buffer: UnsafeBufferPointer<ElementType>) {
self.init()
self.__assign(buffer)
}
}

extension pxr.VtCharArray: __Overlay.VtArrayProtocol {}
extension pxr.VtUCharArray: __Overlay.VtArrayProtocol {}
extension pxr.VtShortArray: __Overlay.VtArrayProtocol {}
extension pxr.VtUShortArray: __Overlay.VtArrayProtocol {}
extension pxr.VtIntArray: __Overlay.VtArrayProtocol {}
extension pxr.VtUIntArray: __Overlay.VtArrayProtocol {}
extension pxr.VtInt64Array: __Overlay.VtArrayProtocol {}
extension pxr.VtUInt64Array: __Overlay.VtArrayProtocol {}
extension pxr.VtBoolArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtDoubleArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtFloatArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtHalfArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtVec4iArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec3iArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec2iArray: __Overlay.VtArrayProtocol {}
extension pxr.VtCharArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtUCharArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtShortArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtUShortArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtIntArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtUIntArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtInt64Array: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtUInt64Array: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtVec4hArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec3hArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec2hArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec4iArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtVec3iArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtVec2iArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtVec4fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec3fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec2fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec4hArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtVec3hArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtVec2hArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtVec4dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec3dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec2dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec4fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtVec3fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtVec2fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtMatrix4fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtMatrix3fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtMatrix2fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtVec4dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtVec3dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtVec2dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtMatrix4dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtMatrix3dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtMatrix2dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtMatrix4fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtMatrix3fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtMatrix2fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtRange3fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtRange3dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtRange2fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtRange2dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtRange1fArray: __Overlay.VtArrayProtocol {}
extension pxr.VtRange1dArray: __Overlay.VtArrayProtocol {}
extension pxr.VtMatrix4dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtMatrix3dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtMatrix2dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtRange3fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtRange3dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtRange2fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtRange2dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtRange1fArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtRange1dArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtIntervalArray: __Overlay.VtArrayProtocol {}
extension pxr.VtRect2iArray: __Overlay.VtArrayProtocol {}
extension pxr.VtIntervalArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtRect2iArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

// VtStringArray gains Codable conformance in Codable.swift,
// but it can't satisfy the requirements that ElementType is Codable
// because std.string isn't Codable
extension pxr.VtStringArray: __Overlay.VtArray_WithoutCodableProtocol {}
extension pxr.VtTokenArray: __Overlay.VtArrayProtocol {}
extension pxr.VtStringArray: __Overlay.VtArray_WithoutCodableProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtTokenArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtQuathArray: __Overlay.VtArrayProtocol {}
extension pxr.VtQuatfArray: __Overlay.VtArrayProtocol {}
extension pxr.VtQuatdArray: __Overlay.VtArrayProtocol {}
extension pxr.VtQuaternionArray: __Overlay.VtArrayProtocol {}
extension pxr.VtQuathArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtQuatfArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtQuatdArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}
extension pxr.VtQuaternionArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension Overlay.SdfAssetPath_VtArray: __Overlay.VtArrayProtocol {}
extension Overlay.SdfAssetPath_VtArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}

extension pxr.VtTimeCodeArray: __Overlay.VtArrayProtocol {}
extension pxr.VtTimeCodeArray: __Overlay.VtArrayProtocol {
public mutating func __assign(_ p: UnsafeBufferPointer<ElementType>) {
__Overlay.VtArray_assign(&self, Int(bitPattern: p.baseAddress), Int(bitPattern: p.baseAddress.map { $0 + p.count }))
}
}