From 1fe5ee147f9567f3c7d06c93c92ddfcfd96bb136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furby=E2=84=A2?= Date: Tue, 30 Jun 2026 21:57:54 -0600 Subject: [PATCH] [OpenExec] Add ExecUsdSystemWrapper to expose ExecUsdSystem to Swift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce ExecUsdSystemWrapper to wrap the underlying OpenUSD ExecUsdSystem type to Swift. Resolves #31 Signed-off-by: Furby™ --- SwiftUsd.docc/AboutThisRepo/ChangeLog.md | 1 + .../WrappedTypes.md | 3 +- source/SwiftOverlay/Typedefs.h | 2 + .../ExecUsdCacheViewNoncopyableWrapper.swift | 70 +++++++++ source/Wrappers/ExecUsdSystemWrapper.cpp | 87 +++++++++++ source/Wrappers/ExecUsdSystemWrapper.h | 144 ++++++++++++++++++ source/swiftUsd.h | 2 + 7 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 source/Wrappers/ExecUsdCacheViewNoncopyableWrapper.swift create mode 100644 source/Wrappers/ExecUsdSystemWrapper.cpp create mode 100644 source/Wrappers/ExecUsdSystemWrapper.h diff --git a/SwiftUsd.docc/AboutThisRepo/ChangeLog.md b/SwiftUsd.docc/AboutThisRepo/ChangeLog.md index e422872579..dc0342f993 100644 --- a/SwiftUsd.docc/AboutThisRepo/ChangeLog.md +++ b/SwiftUsd.docc/AboutThisRepo/ChangeLog.md @@ -14,6 +14,7 @@ Changes to SwiftUsd ### TBD Released TBD, based on OpenUSD TBD - Add `Overlay.HgiGLWrapper`, exposing HgiGL alongside HgiMetal in the Swift bindings +- Add `Overlay.ExecUsdSystem`, exposing ExecUsdSystem in the Swift bindings ### 7.0.1 Released 2026-06-04, based on OpenUSD v26.05 diff --git a/SwiftUsd.docc/WrappedSymbolDocumentation/WrappedTypes.md b/SwiftUsd.docc/WrappedSymbolDocumentation/WrappedTypes.md index 0dbf7f855c..3dfcc3fec7 100644 --- a/SwiftUsd.docc/WrappedSymbolDocumentation/WrappedTypes.md +++ b/SwiftUsd.docc/WrappedSymbolDocumentation/WrappedTypes.md @@ -18,6 +18,7 @@ Since Swift-Cxx interop doesn't currently support specializing class templates f - ``OpenUSD/Overlay/UsdRelationship_Vector`` - ``OpenUSD/Overlay/String_Set`` - ``OpenUSD/Overlay/SdfLayerHandle_Set`` +- ``OpenUSD/Overlay/ExecUsdValueKey_Vector`` ### Namespace Overlay Access these types by prefixing their name with `Overlay` @@ -30,4 +31,4 @@ Access these types by prefixing their name with `Overlay` - ``OpenUSD/Overlay/HgiMetalWrapper`` - ``OpenUSD/Overlay/UsdImagingGLEngineWrapper`` - ``OpenUSD/Overlay/UsdAppUtilsFrameRecorderWrapper`` - +- ``OpenUSD/Overlay/ExecUsdSystemWrapper`` diff --git a/source/SwiftOverlay/Typedefs.h b/source/SwiftOverlay/Typedefs.h index 447307bf1f..aa5f95d989 100644 --- a/source/SwiftOverlay/Typedefs.h +++ b/source/SwiftOverlay/Typedefs.h @@ -44,6 +44,7 @@ #include "pxr/base/tf/diagnosticBase.h" #include "pxr/base/vt/array.h" #include "pxr/usd/sdf/assetPath.h" +#include "pxr/exec/execUsd/valueKey.h" namespace Overlay { #if SwiftUsd_PXR_ENABLE_IMAGING_SUPPORT @@ -66,6 +67,7 @@ namespace Overlay { typedef std::vector> TfDiagnosticBase_Unique_Ptr_Vector; typedef std::vector UsdShadeInput_Vector; typedef std::vector> SdfLayer_RefPtr_Vector; + typedef std::vector ExecUsdValueKey_Vector; typedef std::set String_Set; typedef std::set SdfLayerHandle_Set; diff --git a/source/Wrappers/ExecUsdCacheViewNoncopyableWrapper.swift b/source/Wrappers/ExecUsdCacheViewNoncopyableWrapper.swift new file mode 100644 index 0000000000..f38bdf1f2d --- /dev/null +++ b/source/Wrappers/ExecUsdCacheViewNoncopyableWrapper.swift @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// 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 +//===----------------------------------------------------------------------===// + +import Foundation + +extension Overlay { + /// Non-escaping, move-only wrapper around `pxr.ExecUsdCacheView`. + /// + /// Only valid for the duration of the closure passed to + /// `Overlay.Compute(_:_:_:)`. `~Copyable` + `borrowing` at the call site + /// prevent it from escaping, since `ExecUsdCacheView` must not outlive + /// the `ExecUsdSystem`/`ExecUsdRequest` that created it. + public struct ExecUsdCacheViewNoncopyableWrapper: ~Copyable { + var cacheView: pxr.ExecUsdCacheView + + init(_ cacheView: consuming pxr.ExecUsdCacheView) { + self.cacheView = cacheView + } + + public func Get(_ index: CInt) -> pxr.VtValue { + cacheView.Get(index) + } + } +} + +extension Overlay { + public static func Compute(_ system: inout Overlay.ExecUsdSystemWrapper, + _ request: consuming pxr.ExecUsdRequest, + _ body: (borrowing ExecUsdCacheViewNoncopyableWrapper) throws(E) -> T + ) throws(E) -> T { + try withExtendedLifetime(request) { _ throws(E) -> T in + let rawView = __Overlay.ComputeUnsafe(&system, request) + return try body(ExecUsdCacheViewNoncopyableWrapper(rawView)) + } + } + + #if compiler(>=6.2) + // Swift-Cxx interop only gained rvalue reference support in Swift 6.2; + // __Overlay.ComputeWithOverridesUnsafe(_:_:consuming:) relies on it. + public static func ComputeWithOverrides(_ system: inout Overlay.ExecUsdSystemWrapper, + _ request: consuming pxr.ExecUsdRequest, + consuming valueOverrides: consuming pxr.ExecUsdValueOverrideVector, + _ body: (borrowing ExecUsdCacheViewNoncopyableWrapper) throws(E) -> T + ) throws(E) -> T { + let localOverrides = consume valueOverrides + + return try withExtendedLifetime(request) { _ throws(E) -> T in + let rawView = __Overlay.ComputeWithOverridesUnsafe(&system, request, consuming: localOverrides) + return try body(ExecUsdCacheViewNoncopyableWrapper(rawView)) + } + } + #endif // #if compiler(>=6.2) +} diff --git a/source/Wrappers/ExecUsdSystemWrapper.cpp b/source/Wrappers/ExecUsdSystemWrapper.cpp new file mode 100644 index 0000000000..2f8a18f6a8 --- /dev/null +++ b/source/Wrappers/ExecUsdSystemWrapper.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// 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 +//===----------------------------------------------------------------------===// + +#include "swiftUsd/Wrappers/ExecUsdSystemWrapper.h" + +#include + +// MARK: Construction + +Overlay::ExecUsdSystemWrapper::ExecUsdSystemWrapper(const pxr::UsdStageRefPtr &stage) : + _impl(std::make_shared(stage)) +{ +} + +// MARK: Time + +void Overlay::ExecUsdSystemWrapper::ChangeTime(pxr::UsdTimeCode time) { + _impl->ChangeTime(time); +} + +// MARK: Requests + +pxr::ExecUsdRequest Overlay::ExecUsdSystemWrapper::BuildRequest(std::vector &&valueKeys, + pxr::ExecRequestComputedValueInvalidationCallback &&valueCallback, + pxr::ExecRequestTimeChangeInvalidationCallback &&timeCallback) { + return _impl->BuildRequest(std::move(valueKeys), + std::move(valueCallback), + std::move(timeCallback)); +} + +void Overlay::ExecUsdSystemWrapper::PrepareRequest(const pxr::ExecUsdRequest &request) { + _impl->PrepareRequest(request); +} + +pxr::ExecUsdCacheView Overlay::ExecUsdSystemWrapper::Compute(const pxr::ExecUsdRequest &request) { + return _impl->Compute(request); +} + +pxr::ExecUsdCacheView Overlay::ExecUsdSystemWrapper::ComputeWithOverrides(const pxr::ExecUsdRequest &request, + pxr::ExecUsdValueOverrideVector &&valueOverrides) { + return _impl->ComputeWithOverrides(request, std::move(valueOverrides)); +} + +// MARK: SwiftUsd implementation access + +pxr::ExecUsdSystem* Overlay::ExecUsdSystemWrapper::get() const { + return _impl.get(); +} + +std::shared_ptr Overlay::ExecUsdSystemWrapper::get_shared() const { + return _impl; +} + +Overlay::ExecUsdSystemWrapper::operator bool() const { + return (bool)_impl; +} + +Overlay::ExecUsdSystemWrapper::ExecUsdSystemWrapper(std::shared_ptr impl) : + _impl(impl) {} + +pxr::ExecUsdCacheView __Overlay::ComputeUnsafe(Overlay::ExecUsdSystemWrapper &system, + const pxr::ExecUsdRequest &request) { + return system.Compute(request); +} + +pxr::ExecUsdCacheView __Overlay::ComputeWithOverridesUnsafe(Overlay::ExecUsdSystemWrapper &system, + const pxr::ExecUsdRequest &request, + pxr::ExecUsdValueOverrideVector &&valueOverrides) { + return system.ComputeWithOverrides(request, std::move(valueOverrides)); +} diff --git a/source/Wrappers/ExecUsdSystemWrapper.h b/source/Wrappers/ExecUsdSystemWrapper.h new file mode 100644 index 0000000000..bb14382b64 --- /dev/null +++ b/source/Wrappers/ExecUsdSystemWrapper.h @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// 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 +//===----------------------------------------------------------------------===// + +// Original documentation for pxr::ExecUsdSystem from +// https://github.com/PixarAnimationStudios/OpenUSD/blob/v26.05/pxr/exec/execUsd/system.h + +#ifndef SWIFTUSD_WRAPPERS_EXECUSDSYSTEMWRAPPER_H +#define SWIFTUSD_WRAPPERS_EXECUSDSYSTEMWRAPPER_H + +#include "swiftUsd/defines.h" +#include "swiftUsd/SwiftOverlay/SwiftCxxMacros.h" + +#include +#include +#include + +#include "pxr/pxr.h" +#include "pxr/usd/usd/stage.h" +#include "pxr/usd/usd/timeCode.h" + +#include "pxr/exec/ef/timeInterval.h" + +#include "pxr/exec/execUsd/system.h" +#include "pxr/exec/execUsd/request.h" +#include "pxr/exec/execUsd/valueKey.h" +#include "pxr/exec/execUsd/valueOverride.h" +#include "pxr/exec/execUsd/cacheView.h" + +namespace Overlay { + /// \class ExecUsdSystem + /// + /// The implementation of a system to procedurally compute values based on + /// USD scene description and computation definitions. + /// + /// ExecUsdSystem specializes the base ExecSystem class and owns + /// USD-specific structures and logic necessary to compile, schedule and + /// evaluate requested computation values. + /// + /// The ExecUsdSystem extends the lifetime of the UsdStage it is + /// constructed with, although it is atypical for an ExecUsdSystem to + /// outlive its stage in practice. As a rule of thumb, the ExecUsdSystem + /// lives right alongside the UsdStage in most use-cases. + /// + class ExecUsdSystemWrapper { + public: + ExecUsdSystemWrapper(const pxr::UsdStageRefPtr &stage); + + /// Changes the \p time at which values are computed. + /// + /// Calling this method re-resolves time-dependent inputs from the + /// scene graph at the new \p time, and determines which of these + /// inputs are *actually* changing between the old and new time. + /// Computed values that are dependent on the changing inputs are then + /// invalidated, and requests are notified of the time change. + void ChangeTime(pxr::UsdTimeCode time); + + /// Builds a request for the given \p valueKeys. + /// + /// The optionally provided \p valueCallback will be invoked when + /// previously computed value keys become invalid as a result of authored + /// value changes or structural invalidation of the scene. If multiple + /// value keys become invalid at the same time, they may be batched into a + /// single invocation of the callback. + pxr::ExecUsdRequest BuildRequest( + std::vector &&valueKeys, + pxr::ExecRequestComputedValueInvalidationCallback &&valueCallback = + pxr::ExecRequestComputedValueInvalidationCallback(), + pxr::ExecRequestTimeChangeInvalidationCallback &&timeCallback = + pxr::ExecRequestTimeChangeInvalidationCallback()); + + /// Prepares a given \p request for execution. + /// + /// This ensures the exec network is compiled and scheduled for the + /// value keys in the request. Compute() will implicitly prepare the + /// request if needed, but calling PrepareRequest() separately enables + /// clients to front-load compilation and scheduling cost. + void PrepareRequest(const pxr::ExecUsdRequest &request); + + /// Executes the given \p request and returns a cache view for + /// extracting the computed values. + /// + /// This implicitly calls PrepareRequest(), though clients may choose + /// to call PrepareRequest() ahead of time and front-load the + /// associated compilation and scheduling cost. + pxr::ExecUsdCacheView Compute(const pxr::ExecUsdRequest &request) + SWIFT_UNAVAILABLE_MESSAGE("Use Overlay.Compute(_:_:_:) instead"); + + /// Executes the given \p request in the presence of + /// \p valueOverrides, and returns a cache view for extracting the + /// computed values. + /// + /// The overrides only apply for a single invocation of + /// ComputeWithOverrides, and do not affect subsequent calls to + /// Compute or ComputeWithOverrides. + pxr::ExecUsdCacheView ComputeWithOverrides(const pxr::ExecUsdRequest &request, + pxr::ExecUsdValueOverrideVector &&valueOverrides) + SWIFT_UNAVAILABLE_MESSAGE("Use Overlay.ComputeWithOverrides(_:_:consuming:_:) instead"); + + /// MARK: SwiftUsd implementation access + + /// SwiftUsd wrapping constructor + ExecUsdSystemWrapper(std::shared_ptr impl); + + /// Gets the underlying ExecUsdSystem instance + pxr::ExecUsdSystem*_Nullable get() const; + + /// Gets the underlying ExecUsdSystem instance + std::shared_ptr get_shared() const; + + /// Returns `true` if the underlying instance is valid + explicit operator bool() const; + + private: + std::shared_ptr _impl; + }; +} + +namespace __Overlay { + pxr::ExecUsdCacheView ComputeUnsafe(Overlay::ExecUsdSystemWrapper &system, + const pxr::ExecUsdRequest &request); + + pxr::ExecUsdCacheView ComputeWithOverridesUnsafe(Overlay::ExecUsdSystemWrapper &system, + const pxr::ExecUsdRequest &request, + pxr::ExecUsdValueOverrideVector &&valueOverrides); +} + +#endif /* SWIFTUSD_WRAPPERS_EXECUSDSYSTEMWRAPPER_H */ diff --git a/source/swiftUsd.h b/source/swiftUsd.h index 930b65822b..5c882e989c 100644 --- a/source/swiftUsd.h +++ b/source/swiftUsd.h @@ -43,6 +43,7 @@ #include "swiftUsd/CxxOnly/Deprecated.h" #include "swiftUsd/Wrappers/ArResolverWrapper.h" +#include "swiftUsd/Wrappers/ExecUsdSystemWrapper.h" #include "swiftUsd/Wrappers/HgiGLWrapper.h" #include "swiftUsd/Wrappers/HgiMetalWrapper.h" #include "swiftUsd/Wrappers/HgiWrapper.h" @@ -68,6 +69,7 @@ #includeforswiftdocc "swiftUsd/TfNotice/SwiftKey.h" #includeforswiftdocc "swiftUsd/Wrappers/ArResolverWrapper.h" +#includeforswiftdocc "swiftUsd/Wrappers/ExecUsdSystemWrapper.h" #includeforswiftdocc "swiftUsd/Wrappers/HgiGLWrapper.h" #includeforswiftdocc "swiftUsd/Wrappers/HgiMetalWrapper.h" #includeforswiftdocc "swiftUsd/Wrappers/HgiWrapper.h"