Skip to content

Commit

Permalink
UsdView: clean & setup for cross-platform, add HgiGL.
Browse files Browse the repository at this point in the history
* Also migrate initial HgiInterop.GetHgiFromMetalDriver() to be cross-platform,
  renaming the function to HgiInterop.GetHgiFromDriver() to retrieve all platform
  Hgis from HdDriver's VtValue.

Signed-off-by: furby™ <devs@wabi.foundation>
  • Loading branch information
furby-tm committed Sep 17, 2024
1 parent 9bd56e3 commit 761029d
Show file tree
Hide file tree
Showing 20 changed files with 574 additions and 242 deletions.
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,7 @@ let package = Package(
.target(name: "Trace"),
.target(name: "Garch"),
.target(name: "Hgi"),
.target(name: "Vt"),
],
resources: [
.process("Resources")
Expand Down
12 changes: 3 additions & 9 deletions Sources/HdSt/renderDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,19 +209,13 @@ void HdStRenderDelegate::SetDrivers(HdDriverVector const &drivers)

// For Storm we want to use the Hgi driver, so extract it.
for (HdDriver *hdDriver : drivers) {
if (hdDriver->name == HgiTokens->renderDriver && hdDriver->driver.IsHolding<Hgi *>()) {
_hgi = hdDriver->driver.UncheckedGet<Hgi *>();
break;
}
#if defined(ARCH_OS_DARWIN)
if (hdDriver->name == HgiTokens->renderDriver) {
Hgi *hgiMetal = HgiInterop::GetHgiFromMetalDriver(hdDriver->driver);
if (hgiMetal) {
_hgi = hgiMetal;
Hgi *platformHgi = HgiInterop::GetHgiFromDriver(hdDriver->driver);
if (platformHgi) {
_hgi = platformHgi;
break;
}
}
#endif
}

TF_VERIFY(_hgi, "HdSt requires Hgi HdDriver");
Expand Down
15 changes: 15 additions & 0 deletions Sources/HgiGL/hgi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ HgiGL::~HgiGL()
delete _device;
}

// static.
HgiGLPtr HgiGL::CreateHgi()
{
HgiGLPtr hgi = std::make_shared<HgiGL>();

hgi.reset(dynamic_cast<HgiGL *>(Hgi::GetPlatformDefaultHgi()));

return hgi;
}

VtValue HgiGL::GetValue(HgiGLPtr ptr) const
{
return VtValue(ptr.get());
}

bool HgiGL::IsBackendSupported() const
{
// Want OpenGL 4.5 or higher.
Expand Down
7 changes: 5 additions & 2 deletions Sources/HgiGL/include/HgiGL/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
#ifndef PXR_IMAGING_HGIGL_DEVICE_H
#define PXR_IMAGING_HGIGL_DEVICE_H

#include "pxr/pxrns.h"

#include "Arch/swiftInterop.h"

#include "Hgi/graphicsCmdsDesc.h"
#include "HgiGL/api.h"
#include "HgiGL/contextArena.h"
#include "HgiGL/hgi.h"
#include "pxr/pxrns.h"

#include <fstream>
#include <ostream>
Expand Down Expand Up @@ -64,7 +67,7 @@ class HgiGLDevice final {
// The default arena is used in the absence of a user provided arena.
HgiGLContextArena _defaultArena;
HgiGLContextArena *_activeArena;
};
} SWIFT_IMMORTAL_REFERENCE;

PXR_NAMESPACE_CLOSE_SCOPE

Expand Down
16 changes: 14 additions & 2 deletions Sources/HgiGL/include/HgiGL/hgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
#ifndef PXR_IMAGING_HGI_GL_HGI_H
#define PXR_IMAGING_HGI_GL_HGI_H

#include "pxr/pxrns.h"

#include "Arch/swiftInterop.h"

#include "Hgi/hgiImpl.h"
#include "Hgi/tokens.h"
#include "HgiGL/api.h"
#include "HgiGL/capabilities.h"
#include "HgiGL/garbageCollector.h"
#include "pxr/pxrns.h"

#include "Vt/value.h"

#include <functional>
#include <memory>
Expand All @@ -25,6 +30,7 @@ class HgiGLDevice;
using HgiGLOpsFn = std::function<void(void)>;
using HgiGLOpsVector = std::vector<HgiGLOpsFn>;
using HgiGLContextArenaHandle = HgiHandle<class HgiGLContextArena>;
using HgiGLPtr = std::shared_ptr<class HgiGL>;

/// \class HgiGL
///
Expand Down Expand Up @@ -59,6 +65,12 @@ class HgiGL final : public Hgi {
HGIGL_API
~HgiGL() override;

HGIGL_API
static HgiGLPtr CreateHgi();

HGIGL_API
VtValue GetValue(HgiGLPtr ptr) const;

/// ------------------------------------------------------------------------
/// Virtual API
/// ------------------------------------------------------------------------
Expand Down Expand Up @@ -194,7 +206,7 @@ class HgiGL final : public Hgi {
std::unique_ptr<HgiGLCapabilities> _capabilities;
HgiGLGarbageCollector _garbageCollector;
int _frameDepth;
};
} SWIFT_IMMORTAL_REFERENCE;

/// ----------------------------------------------------------------------------
/// API Version & History
Expand Down
27 changes: 24 additions & 3 deletions Sources/HgiInterop/hgiInterop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

#if defined(PXR_GL_SUPPORT_ENABLED)
# include "HgiInterop/opengl.h"
# include "HgiGL/hgi.h"
#endif

#if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
# include "HgiInterop/vulkan.h"
# include "HgiVulkan/hgi.h"
#endif

#if defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
Expand Down Expand Up @@ -104,17 +106,36 @@ void HgiInterop::TransferToApp(Hgi *srcHgi,
TF_CODING_ERROR("Unsupported source Hgi backend: %s", srcApi.GetText());
}

#if defined(ARCH_OS_DARWIN)
// static.
Hgi* HgiInterop::GetHgiFromMetalDriver(VtValue const &hdDriver)
Hgi* HgiInterop::GetHgiFromDriver(VtValue const &hdDriver)
{
/* keep sorted, in order of preferred hgi per platform.
* which is metal above all else on darwin, followed by
* vulkan over opengl on windows and linux, and finally
* we fallback to the base hgi class, in the case that
* none of the specific platform hgis were passed in. */

#if defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
if (hdDriver.IsHolding<HgiMetal *>()) {
return hdDriver.UncheckedGet<HgiMetal *>();
}
#endif // defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
#if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
if (hdDriver.IsHolding<HgiVulkan *>()) {
return hdDriver.UncheckedGet<HgiVulkan *>();
}
#endif // defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
#if defined(PXR_GL_SUPPORT_ENABLED)
if (hdDriver.IsHolding<HgiGL *>()) {
return hdDriver.UncheckedGet<HgiGL *>();
}
#endif // defined(PXR_GL_SUPPORT_ENABLED)
if (hdDriver.IsHolding<Hgi *>()) {
return hdDriver.UncheckedGet<Hgi *>();
}

return nullptr;
}
#endif // defined(ARCH_OS_DARWIN)

PXR_NAMESPACE_CLOSE_SCOPE

Expand Down
93 changes: 57 additions & 36 deletions Sources/HgiInterop/hgiInterop.mm
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,41 @@
// so we duplicate this file and compile only the mm one for all apple
// platforms.
#if defined(__APPLE__)
#include "HgiInterop/hgiInteropImpl.h"
#include "Hgi/hgiImpl.h"
#include "Hgi/tokens.h"

#if defined(PXR_GL_SUPPORT_ENABLED)
# include "HgiInterop/opengl.h"
#endif

#if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
# include "HgiInterop/vulkan.h"
#endif

#if defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
# include "HgiMetal/hgi.h"
# if defined(ARCH_OS_OSX)
# include "HgiInterop/metal.h"
# endif // defined(ARCH_OS_OSX)
#endif // defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
# include "Hgi/hgiImpl.h"
# include "Hgi/tokens.h"
# include "HgiInterop/hgiInteropImpl.h"

# if defined(PXR_GL_SUPPORT_ENABLED)
# include "HgiInterop/opengl.h"
# include "HgiGL/hgi.h"
# endif

# if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
# include "HgiInterop/vulkan.h"
# include "HgiVulkan/hgi.h"
# endif

# if defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
# include "HgiMetal/hgi.h"
# if defined(ARCH_OS_OSX)
# include "HgiInterop/metal.h"
# endif // defined(ARCH_OS_OSX)
# endif // defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED

PXR_NAMESPACE_OPEN_SCOPE

struct HgiInteropImpl {
#if defined(PXR_GL_SUPPORT_ENABLED)
# if defined(PXR_GL_SUPPORT_ENABLED)
std::unique_ptr<HgiInteropOpenGL> _openGLToOpenGL;
#endif // defined(PXR_GL_SUPPORT_ENABLED)
#if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
# endif // defined(PXR_GL_SUPPORT_ENABLED)
# if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
std::unique_ptr<HgiInteropVulkan> _vulkanToOpenGL;
#endif // defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
#if defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
# if !defined(ARCH_OS_IPHONE)
# endif // defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
# if defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
# if !defined(ARCH_OS_IPHONE)
std::unique_ptr<HgiInteropMetal> _metalToOpenGL;
# endif // !defined(ARCH_OS_IPHONE)
#endif // defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
# endif // !defined(ARCH_OS_IPHONE)
# endif // defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
};

HgiInterop::HgiInterop() : _hgiInteropImpl(std::make_unique<HgiInteropImpl>()) {}
Expand All @@ -64,7 +66,7 @@
return;
}

#if defined(PXR_GL_SUPPORT_ENABLED) && !defined(ARCH_OS_IPHONE)
# if defined(PXR_GL_SUPPORT_ENABLED) && !defined(ARCH_OS_IPHONE)
if (srcApi == HgiTokens->OpenGL) {
// Transfer OpenGL textures to OpenGL application
if (!_hgiInteropImpl->_openGLToOpenGL) {
Expand All @@ -73,9 +75,9 @@
return _hgiInteropImpl->_openGLToOpenGL->CompositeToInterop(
srcColor, srcDepth, dstFramebuffer, dstRegion);
}
#endif
# endif

#if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
# if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
if (srcApi == HgiTokens->Vulkan) {
// Transfer Vulkan textures to OpenGL application
// XXX: It's possible that if we use the same HgiInterop with a
Expand All @@ -88,9 +90,9 @@
return _hgiInteropImpl->_vulkanToOpenGL->CompositeToInterop(
srcColor, srcDepth, dstFramebuffer, dstRegion);
}
#endif
# endif

#if (defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED) && !defined(ARCH_OS_IPHONE)
# if (defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED) && !defined(ARCH_OS_IPHONE)
if (srcApi == HgiTokens->Metal) {
// Transfer Metal textures to OpenGL application
// XXX: It's possible that if we use the same HgiInterop with a
Expand All @@ -103,23 +105,42 @@
return _hgiInteropImpl->_metalToOpenGL->CompositeToInterop(
srcColor, srcDepth, dstFramebuffer, dstRegion);
}
#endif
# endif

TF_CODING_ERROR("Unsupported source Hgi backend: %s", srcApi.GetText());
}

#if defined(ARCH_OS_DARWIN)
// static.
Hgi* HgiInterop::GetHgiFromMetalDriver(VtValue const &hdDriver)
Hgi* HgiInterop::GetHgiFromDriver(VtValue const &hdDriver)
{
/* keep sorted, in order of preferred hgi per platform.
* which is metal above all else on darwin, followed by
* vulkan over opengl on windows and linux, and finally
* we fallback to the base hgi class, in the case that
* none of the specific platform hgis were passed in. */

#if defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
if (hdDriver.IsHolding<HgiMetal *>()) {
return hdDriver.UncheckedGet<HgiMetal *>();
}
#endif // defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
#if defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
if (hdDriver.IsHolding<HgiVulkan *>()) {
return hdDriver.UncheckedGet<HgiVulkan *>();
}
#endif // defined(PXR_VULKAN_SUPPORT_ENABLED) && PXR_VULKAN_SUPPORT_ENABLED
#if defined(PXR_GL_SUPPORT_ENABLED)
if (hdDriver.IsHolding<HgiGL *>()) {
return hdDriver.UncheckedGet<HgiGL *>();
}
#endif // defined(PXR_GL_SUPPORT_ENABLED)
if (hdDriver.IsHolding<Hgi *>()) {
return hdDriver.UncheckedGet<Hgi *>();
}

return nullptr;
}
#endif // defined(ARCH_OS_DARWIN)

PXR_NAMESPACE_CLOSE_SCOPE

#endif // defined(__APPLE__)
#endif // defined(__APPLE__)
15 changes: 12 additions & 3 deletions Sources/HgiInterop/include/HgiInterop/hgiInteropImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,19 @@ class HgiInterop final {
VtValue const &dstFramebuffer,
GfVec4i const &dstRegion);

#if defined(ARCH_OS_DARWIN)
/// Retrieve an Hgi, from a VtValue, typically from a client's HdDriver.
/// This is especially useful for programming languages such as Swift, where
/// the Hgi base class cannot be utilized, so clients must interface with the
/// platform specific Hgi (such as HgiGL, HgiMetal, and HgiVulkan). As such,
/// we cannot rely on inquiring or retrieving the base (Hgi) class from VtValue,
/// typically done by calling: `IsHolding<Hgi *>()` since platform Hgis created
/// by client (Swift code in this case) can only be retrieved by their respective
/// platform-specific Hgis (ex: `IsHolding<HgiGL *>()`, `IsHolding<HgiMetal *>()`)
/// which this function encapsulates for all the different Hgi backends, if you
/// ever require checking whether a `VtValue.IsHolding<Hgi *>()`, or casting this
/// VtValue back to the base Hgi class, you should utilize this function instead.
HGIINTEROP_API
static Hgi *GetHgiFromMetalDriver(VtValue const &hdDriver);
#endif // defined(PXR_METAL_SUPPORT_ENABLED) && PXR_METAL_SUPPORT_ENABLED
static Hgi *GetHgiFromDriver(VtValue const &hdDriver);

private:
HgiInterop &operator=(const HgiInterop &) = delete;
Expand Down
Loading

0 comments on commit 761029d

Please sign in to comment.