Skip to content

Autodesk: Hgi Backend Selection #2736

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
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
2 changes: 1 addition & 1 deletion extras/imaging/examples/hdTiny/rendererPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ HdTinyRendererPlugin::DeleteRenderDelegate(HdRenderDelegate *renderDelegate)
}

bool
HdTinyRendererPlugin::IsSupported(bool /* gpuEnabled */) const
HdTinyRendererPlugin::IsSupported(bool /* gpuEnabled */, TfToken /*hgiToken*/) const
{
// Nothing more to check for now, we assume if the plugin loads correctly
// it is supported.
Expand Down
2 changes: 1 addition & 1 deletion extras/imaging/examples/hdTiny/rendererPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class HdTinyRendererPlugin final : public HdRendererPlugin
HdRenderDelegate *renderDelegate) override;

/// Checks to see if the plugin is supported on the running system.
virtual bool IsSupported(bool gpuEnabled = true) const override;
virtual bool IsSupported(bool gpuEnabled = true, TfToken hgiToken = TfToken("")) const override;

private:
// This class does not support copying.
Expand Down
9 changes: 8 additions & 1 deletion pxr/imaging/hd/rendererPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,14 @@ HdRendererPlugin::~HdRendererPlugin() = default;
HdPluginRenderDelegateUniqueHandle
HdRendererPlugin::CreateDelegate(HdRenderSettingsMap const& settingsMap)
{
if (!IsSupported()) {
TfToken backendToken;

auto iter = settingsMap.find(TfToken("HgiBackend"));
if (iter != settingsMap.end()) {
backendToken = iter->second.Get<TfToken>();
}

if (!IsSupported(true, backendToken)) {
return nullptr;
}

Expand Down
2 changes: 1 addition & 1 deletion pxr/imaging/hd/rendererPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class HdRendererPlugin : public HfPluginBase {
/// parameter indicates if the GPU is available for use by the plugin in
/// case this information is necessary to make this determination.
///
virtual bool IsSupported(bool gpuEnabled = true) const = 0;
virtual bool IsSupported(bool gpuEnabled = true, TfToken token = TfToken("")) const = 0;

protected:
HdRendererPlugin() = default;
Expand Down
4 changes: 2 additions & 2 deletions pxr/imaging/hdSt/renderDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,9 +537,9 @@ HdStRenderDelegate::CommitResources(HdChangeTracker *tracker)
}

bool
HdStRenderDelegate::IsSupported()
HdStRenderDelegate::IsSupported(const TfToken& hgiToken)
{
return Hgi::IsSupported();
return Hgi::IsSupported(hgiToken);
}

TfTokenVector
Expand Down
2 changes: 1 addition & 1 deletion pxr/imaging/hdSt/renderDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class HdStRenderDelegate final : public HdRenderDelegate
// Returns whether or not HdStRenderDelegate can run on the current
// hardware.
HDST_API
static bool IsSupported();
static bool IsSupported(const TfToken& token = TfToken(""));

// Returns a raw pointer to the draw items cache owned (solely) by the
// render delegate.
Expand Down
99 changes: 96 additions & 3 deletions pxr/imaging/hgi/hgi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,77 @@ _MakeNewPlatformDefaultHgi()
return instance;
}

static Hgi*
_MakeHgiOfChoice(const TfToken& type)
{
// If a token other than supported type is passed on current platform,
// return the defualt HGI device supported by current platform.
const char* hgiType = type.data();
#if defined(ARCH_OS_LINUX)
if (std::strcmp(hgiType, "HgiGL") != 0)
#if defined(PXR_VULKAN_SUPPORT_ENABLED)
if (std::strcmp(hgiType, "HgiVulkan") != 0)
#else
if (std::strcmp(hgiType, "HgiVulkan") == 0)
{
TF_CODING_ERROR(
"Build requires PXR_VULKAN_SUPPORT_ENABLED to support HgiVulkan on this platform. "
"Hence the default supported HGI type will be created");
return _MakeNewPlatformDefaultHgi();
}
else
#endif
#elif defined(ARCH_OS_DARWIN)
if (std::strcmp(hgiType, "HgiMetal") != 0)
#elif defined(ARCH_OS_WINDOWS)
if (std::strcmp(hgiType, "HgiGL") != 0)
#if defined(PXR_VULKAN_SUPPORT_ENABLED)
if (std::strcmp(hgiType, "HgiVulkan") != 0)
#else
if (std::strcmp(hgiType, "HgiVulkan") == 0) {
TF_CODING_ERROR("Build requires PXR_VULKAN_SUPPORT_ENABLED to support HgiVulkan on this platform. Hence the default supported HGI type will be created");
return _MakeNewPlatformDefaultHgi();
}
else
#endif
#else
#error Unknown Platform
return nullptr;
#endif
{
TF_CODING_ERROR("Build does not support proposed HGI type \"%s\" on this platform. Hence the default supported HGI type will be created", hgiType);
return _MakeNewPlatformDefaultHgi();
}

PlugRegistry& plugReg = PlugRegistry::GetInstance();

const TfType plugType = plugReg.FindDerivedTypeByName<Hgi>(hgiType);

PlugPluginPtr plugin = plugReg.GetPluginForType(plugType);
if (!plugin || !plugin->Load()) {
TF_CODING_ERROR(
"[PluginLoad] PlugPlugin could not be loaded for TfType '%s'\n",
plugType.GetTypeName().c_str());
return nullptr;
}

HgiFactoryBase* factory = plugType.GetFactory<HgiFactoryBase>();
if (!factory) {
TF_CODING_ERROR("[PluginLoad] Cannot manufacture type '%s' \n",
plugType.GetTypeName().c_str());
return nullptr;
}

Hgi* instance = factory->New();
if (!instance) {
TF_CODING_ERROR("[PluginLoad] Cannot construct instance of type '%s'\n",
plugType.GetTypeName().c_str());
return nullptr;
}

return instance;
}

Hgi*
Hgi::GetPlatformDefaultHgi()
{
Expand All @@ -128,12 +199,34 @@ Hgi::CreatePlatformDefaultHgi()
return HgiUniquePtr(_MakeNewPlatformDefaultHgi());
}

HgiUniquePtr
Hgi::CreateHgiOfChoice(const TfToken& token)
{
return HgiUniquePtr(_MakeHgiOfChoice(token));
}

bool
Hgi::IsSupported()
Hgi::IsSupported(const TfToken& hgiToken)
{
if (HgiUniquePtr const instance = CreatePlatformDefaultHgi()) {
// TODO: By current design, a Hgi instance of default back-end is created
// and initialized as a method of confirming support on a platform. Once
// this is done, Hgi is destroyed along with the created API contexts.
// This is not the best way to check for support on a platform. Hence, IsSupported
// needs to be re-written.

// As of now, this function is called when initializing a render-delegate but only
// for checking support for platform default Hgi back-ends. To be able to check
// support for Hgi back-ends of (non-default) choice, a token can be passed
// Eg: TfToken("HgiVulkan") to this function so that an object of Hgi type of choice
// is created and initialized to confirm support on platform.
HgiUniquePtr instance = nullptr;
if (!hgiToken.IsEmpty())
instance = CreateHgiOfChoice(hgiToken);
else
instance = CreatePlatformDefaultHgi();

if(instance)
return instance->IsBackendSupported();
}

return false;
}
Expand Down
13 changes: 12 additions & 1 deletion pxr/imaging/hgi/hgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ class Hgi
HGI_API
static HgiUniquePtr CreatePlatformDefaultHgi();

/// Helper function to return a Hgi object of choice supported by current platform.
/// For example on Linux this may allow HgiGL only while on macOS HgiMetal.
/// If the HGI device specified is not available on the current platform the default
/// HGI type (HgiGL on windows and linux, HgiMetal on mac) will be created.
/// Caller, usually the application, owns the lifetime of the Hgi object and
/// the object is destroyed when the caller drops the unique ptr.
/// Thread safety: Not thread safe.
/// Supported TfToken values are HgiGL, HgiMetal, HgiVulkan
HGI_API
static HgiUniquePtr CreateHgiOfChoice(const TfToken& type);

/// Determine if Hgi instance can run on current hardware.
/// Thread safety: This call is thread safe.
HGI_API
Expand All @@ -150,7 +161,7 @@ class Hgi
/// the object's IsBackendSupported() function.
/// Thread safety: Not thread safe.
HGI_API
static bool IsSupported();
static bool IsSupported(const TfToken& token = TfToken(""));

/// Returns a GraphicsCmds object (for temporary use) that is ready to
/// record draw commands. GraphicsCmds is a lightweight object that
Expand Down
5 changes: 5 additions & 0 deletions pxr/imaging/hgiInterop/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ if (PXR_ENABLE_METAL_SUPPORT)
list(APPEND optionalCppFiles metal.mm)
list(APPEND optionalPrivateHeaders metal.h)
else()
if (PXR_ENABLE_VULKAN_SUPPORT)
list(APPEND optionalLibraries hgiVulkan)
list(APPEND optionalCppFiles vulkan.cpp)
list(APPEND optionalPrivateHeaders vulkan.h)
endif()
# No OpenGL-to-OpenGL interop when using Metal.
list(APPEND optionalCppFiles opengl.cpp)
list(APPEND optionalPrivateHeaders opengl.h)
Expand Down
21 changes: 13 additions & 8 deletions pxr/imaging/hgiInterop/hgiInterop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@
#if defined(PXR_METAL_SUPPORT_ENABLED)
#include "pxr/imaging/hgiMetal/hgi.h"
#include "pxr/imaging/hgiInterop/metal.h"
#elif defined(PXR_VULKAN_SUPPORT_ENABLED)
#include "pxr/imaging/hgiVulkan/hgi.h"
#include "pxr/imaging/hgiInterop/vulkan.h"
#else
#include "pxr/imaging/hgiInterop/opengl.h"
// Include Vulkan headers if vulkan build option option enabled.
#if defined(PXR_VULKAN_SUPPORT_ENABLED)
#include "pxr/imaging/hgiVulkan/hgi.h"
#include "vulkan.h"
#endif
// Always include opengl (even if vulkan build option enabled)
#include "pxr/imaging/hgiInterop/opengl.h"
#endif

PXR_NAMESPACE_OPEN_SCOPE
Expand Down Expand Up @@ -63,18 +66,20 @@ void HgiInterop::TransferToApp(
} else {
TF_CODING_ERROR("Unsupported Hgi backend: %s", srcApi.GetText());
}
#elif defined(PXR_VULKAN_SUPPORT_ENABLED)
#else

#if defined(PXR_VULKAN_SUPPORT_ENABLED)
if (srcApi==HgiTokens->Vulkan && dstApi==HgiTokens->OpenGL) {
// Transfer Vulkan textures to OpenGL application
if (!_vulkanToOpenGL) {
_vulkanToOpenGL = std::make_unique<HgiInteropVulkan>(srcHgi);
}
_vulkanToOpenGL->CompositeToInterop(
srcColor, srcDepth, dstFramebuffer, dstRegion);
} else {
TF_CODING_ERROR("Unsupported Hgi backend: %s", srcApi.GetText());

}
#else
else
#endif
if (srcApi==HgiTokens->OpenGL && dstApi==HgiTokens->OpenGL) {
// Transfer OpenGL textures to OpenGL application
if (!_openGLToOpenGL) {
Expand Down
5 changes: 3 additions & 2 deletions pxr/imaging/hgiInterop/hgiInterop.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ class HgiInterop final

#if defined(PXR_METAL_SUPPORT_ENABLED)
std::unique_ptr<HgiInteropMetal> _metalToOpenGL;
#elif defined(PXR_VULKAN_SUPPORT_ENABLED)
std::unique_ptr<HgiInteropVulkan> _vulkanToOpenGL;
#else
#if defined(PXR_VULKAN_SUPPORT_ENABLED)
std::unique_ptr<HgiInteropVulkan> _vulkanToOpenGL;
#endif
std::unique_ptr<HgiInteropOpenGL> _openGLToOpenGL;
#endif
};
Expand Down
2 changes: 1 addition & 1 deletion pxr/imaging/plugin/hdEmbree/rendererPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ HdEmbreeRendererPlugin::DeleteRenderDelegate(HdRenderDelegate *renderDelegate)
}

bool
HdEmbreeRendererPlugin::IsSupported(bool /* gpuEnabled */) const
HdEmbreeRendererPlugin::IsSupported(bool /* gpuEnabled */, TfToken /* hgiToken */) const
{
// Nothing more to check for now, we assume if the plugin loads correctly
// it is supported.
Expand Down
2 changes: 1 addition & 1 deletion pxr/imaging/plugin/hdEmbree/rendererPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class HdEmbreeRendererPlugin final : public HdRendererPlugin

/// Checks to see if the embree plugin is supported on the running system
///
bool IsSupported(bool gpuEnabled = true) const override;
bool IsSupported(bool gpuEnabled = true, TfToken hgiToken = TfToken("")) const override;

private:
// This class does not support copying.
Expand Down
4 changes: 2 additions & 2 deletions pxr/imaging/plugin/hdStorm/rendererPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ HdStormRendererPlugin::DeleteRenderDelegate(HdRenderDelegate *renderDelegate)
}

bool
HdStormRendererPlugin::IsSupported(bool gpuEnabled) const
HdStormRendererPlugin::IsSupported(bool gpuEnabled, TfToken hgiToken) const
{
return gpuEnabled ? HdStRenderDelegate::IsSupported() : false;
return gpuEnabled ? HdStRenderDelegate::IsSupported(hgiToken) : false;
}


Expand Down